I have a strange issue which I cannot explain. In the manifest file the launch activity of my app is defined as follows:
<activity
android:name="com.xxx.xxx.xxx.StartupActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Light.NoTitleBar"
android:screenOrientation="sensorPortrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
In the StartUpActivity the following check is performed:
protected void startIntent() {
Intent intent;
if (checkCurrentProfile()) {
Notifier.showHttpToast(R.string.toastLoggedIn);
//try to update the device token in the database
Request.updateDeviceToken();
intent = new Intent(this, GameListActivity.class);
} else {
intent = new Intent(this, RegisterActivity.class);
}
startActivity(intent);
finish();
}
So if the user has a valid account the GameListActivity is shown as root activity:
<activity
android:name="com.xxx.xxx.xxx.xxx.GameListActivity"
android:label="@string/app_name"
android:theme="@style/MyTheme"
android:screenOrientation="sensorPortrait" >
</activity>
The issue now is the following: sometimes the system brings the root activity to the front spontaneously without any user actions. It only occurs sometimes, but I can't figure out the cause. Can anyone help me out here?
The StartUpActivity looks like this:
public class StartupActivity extends StartupCoreActivity implements OnRegisterGCMListener {
private IabHelper mHelper;
private IabHelper.QueryInventoryFinishedListener mQueryInventoryFinishedListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerOnRegisterGCMListener(this);
if (!registerGCMneeded()) {
initInAppBilling();
}
}
@Override
public void registerGCMfinished() {
initInAppBilling();
}
private void initInAppBilling() {
boolean hasPremium = Prefs.getBoolValue(getResources().getString(R.string.pref_key_upgrade_premium), false);
if (hasPremium) {
//unlocking contents not needed
startIntent();
} else {
Prefs.storeValue(getResources().getString(R.string.pref_key_upgrade_premium), false);
mHelper = new IabHelper(this, C.Billing.BILLING_KEY);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (result.isSuccess()) {
queryInventory();
} else {
startIntent();
}
}
});
}
}
private void queryInventory() {
String[] products = {C.Billing.ITEM_SKU};
mQueryInventoryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
if (result.isSuccess()) {
checkPremiumVersion(inv);
} else {
startIntent();
}
}
};
mHelper.queryInventoryAsync(true, Arrays.asList(products), mQueryInventoryFinishedListener);
}
private void checkPremiumVersion(Inventory inv) {
if (inv.hasPurchase(C.Billing.ITEM_SKU)) {
Request.updPremiumVersion();
Prefs.storeValue(getResources().getString(R.string.pref_key_upgrade_premium), true);
Notifier.showHttpToast(R.string.toastPremiumContentsUnlocked);
}
startIntent();
}
}
And the StartupCoreActivity looks like this:
public class StartupCoreActivity extends Activity {
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = xxxx;
GoogleCloudMessaging mGcm;
Context mContext;
String mRegId;
/**
* Substitute you own sender ID here. This is the project number you got
* from the API Console, as described in "Getting Started."
*/
String SENDER_ID = "xxxxxxxxxx";
private OnRegisterGCMListener mOnRegisterGCMListener = null;
public void registerOnRegisterGCMListener(OnRegisterGCMListener listener) {
mOnRegisterGCMListener = listener;
}
protected boolean registerGCMneeded() {
mContext = getApplicationContext();
// Check device for Play Services APK.
if (checkPlayServices()) {
// If this check succeeds, proceed with normal processing.
// Otherwise, prompt user to get valid Play Services APK.
mGcm = GoogleCloudMessaging.getInstance(this);
mRegId = getRegistrationId(mContext);
if (mRegId.isEmpty()) {
registerInBackground();
return true;
} else {
// note we never called setContentView()
return false;
}
}
return false;
}
protected void startIntent() {
Intent intent;
if (checkCurrentProfile()) {
Notifier.showHttpToast(R.string.toastLoggedIn);
//try to update the device token in the database
Request.updateDeviceToken();
intent = new Intent(this, GameListActivity.class);
} else {
intent = new Intent(this, RegisterActivity.class);
}
startActivity(intent);
finish();
}
private boolean checkCurrentProfile() {
KUPlayer me = G.getMySelf();
if (me.getPlayerId() <= 0) {
//database was not present yet and has been created
//or database was present, but profile cannot be read anymore
// make sure Login screen appears ONLY if PlayerID cannot be retrieved anymore
if (G.getPlayerID() <=0) {
Prefs.storeValue(Prefs.PREF_KEY_PWD_SAVED, false);
return false;
}
}
return true;
}
// You need to do the Play Services APK check here too.
@Override
protected void onResume() {
super.onResume();
checkPlayServices();
}
/**
* Check the device to make sure it has the Google Play Services APK. If
* it doesn't, display a dialog that allows users to download the APK from
* the Google Play Store or enable it in the device's system settings.
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
finish();
}
return false;
}
return true;
}
/**
* Registers the application with mGcm servers asynchronously.
* <p>
* Stores the registration ID and the app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (mGcm == null) {
mGcm = GoogleCloudMessaging.getInstance(mContext);
}
mRegId = mGcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + mRegId;
// Persist the mRegId - no need to register again.
storeRegistrationId(mContext, mRegId);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
@Override
protected void onPostExecute(String msg) {
// note we never called setContentView()
if (mOnRegisterGCMListener != null) {
mOnRegisterGCMListener.registerGCMfinished();
}
}
}.execute(null, null, null);
}
/**
* @return Application's version code from the {@code PackageManager}.
*/
private static int getAppVersionCode(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (NameNotFoundException e) {
// should never happen
throw new RuntimeException("Could not get package name: " + e);
}
}
private static String getAppVersionName(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionName;
} catch (NameNotFoundException e) {
// should never happen
throw new RuntimeException("Could not get package name: " + e);
}
}
/**
* Stores the registration ID and the app versionCode in the application's
* {@code SharedPreferences}.
*
* @param mContext application's mContext.
* @param mRegId registration ID
*/
private void storeRegistrationId(Context context, String regId) {
Prefs.storeValue(Prefs.PREF_KEY_DEVICE_TOKEN, regId);
Prefs.storeValue(Prefs.PREF_KEY_APP_VERSION_CODE, getAppVersionCode(context));
Prefs.storeValue(Prefs.PREF_KEY_APP_VERSION_NAME, getAppVersionName(context));
AppRate.resetAfterUpdate();
}
/**
* Gets the current registration ID for application on mGcm service, if there is one.
* <p>
* If result is empty, the app needs to register.
*
* @return registration ID, or empty string if there is no existing
* registration ID.
*/
private String getRegistrationId(Context context) {
String registrationId = Prefs.getStringValue(Prefs.PREF_KEY_DEVICE_TOKEN);
if (registrationId.isEmpty()) {
return "";
}
// Check if app was updated; if so, it must clear the registration ID
// since the existing mRegId is not guaranteed to work with the new
// app version.
int registeredVersion = Prefs.getIntValue(Prefs.PREF_KEY_APP_VERSION_CODE);
int currentVersion = getAppVersionCode(context);
if (registeredVersion != currentVersion) {
return "";
}
return registrationId;
}
}