package com.github.andlyticsproject; import android.support.v7.app.AppCompatActivity; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Looper; import android.util.Log; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.widget.Toast; import android.widget.ViewSwitcher; import com.github.andlyticsproject.admob.AdmobAccountRemovedException; import com.github.andlyticsproject.admob.AdmobAskForPasswordException; import com.github.andlyticsproject.admob.AdmobGenericException; import com.github.andlyticsproject.admob.AdmobInvalidRequestException; import com.github.andlyticsproject.admob.AdmobInvalidTokenException; import com.github.andlyticsproject.admob.AdmobRateLimitExceededException; import com.github.andlyticsproject.console.AppAccessBlockedException; import com.github.andlyticsproject.console.AuthenticationException; import com.github.andlyticsproject.console.DevConsoleProtocolException; import com.github.andlyticsproject.console.MultiAccountException; import com.github.andlyticsproject.console.NetworkException; import com.github.andlyticsproject.dialog.CrashDialog; import com.github.andlyticsproject.dialog.CrashDialog.CrashDialogBuilder; import com.github.andlyticsproject.util.Utils; import com.google.android.gms.common.GooglePlayServicesUtil; import org.acra.ACRA; public class BaseActivity extends AppCompatActivity { private static final String TAG = BaseActivity.class.getSimpleName(); public static final String EXTRA_AUTH_ACCOUNT_NAME = "com.github.andlyticsproject.accontname"; public static final String EXTRA_PACKAGE_NAME = "com.github.andlyticsproject.packagename"; public static final String EXTRA_DEVELOPER_ID = "com.github.andlyticsproject.developerid"; public static final String EXTRA_ICON_FILE = "com.github.andlyticsproject.iconfile"; public static final int REQUEST_GOOGLE_PLAY_SERVICES = 0; public static final int REQUEST_AUTHORIZATION = 1; public static final int REQUEST_ACCOUNT_PICKER = 2; protected static final int REQUEST_AUTHENTICATE = 42; protected String packageName; protected String developerId; protected String iconFilePath; protected String accountName; private boolean refreshing; private boolean skipMainReload; protected DeveloperAccountManager developerAccountManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); developerAccountManager = DeveloperAccountManager.getInstance(getApplication()); Bundle b = getIntent().getExtras(); if (b != null) { // TODO move packageName and iconFilePath assignments to // BaseDetailsActivity // Will this effect startActivity etc with regard to null behaviour? // Might be best to leave them here packageName = b.getString(BaseActivity.EXTRA_PACKAGE_NAME); developerId = b.getString(BaseActivity.EXTRA_DEVELOPER_ID); iconFilePath = b.getString(BaseActivity.EXTRA_ICON_FILE); accountName = b.getString(BaseActivity.EXTRA_AUTH_ACCOUNT_NAME); developerAccountManager.selectDeveloperAccount(accountName); } } public void startActivity(Class<?> clazz, boolean disableAnimation, boolean skipDataReload) { Intent intent = new Intent(BaseActivity.this, clazz); intent.putExtra(BaseActivity.EXTRA_PACKAGE_NAME, packageName); intent.putExtra(BaseActivity.EXTRA_DEVELOPER_ID, developerId); intent.putExtra(BaseActivity.EXTRA_ICON_FILE, iconFilePath); intent.putExtra(BaseActivity.EXTRA_AUTH_ACCOUNT_NAME, accountName); if (clazz.equals(Main.class)) { // Main does not have singleTask set in the manifest // in order to facilitate easy switching between accounts using list // navigation // We therefore need to clear activity we came from before had in // order // to avoid duplicates intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); } if (disableAnimation) { intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); } if (skipDataReload) { setSkipMainReload(true); } startActivity(intent); } public void handleUserVisibleException(Exception e) { if (e instanceof NetworkException) { Toast.makeText(BaseActivity.this, getString(R.string.network_error), Toast.LENGTH_LONG) .show(); } else if (e instanceof AppAccessBlockedException) { Toast.makeText(BaseActivity.this, getString(R.string.app_access_blocked_error, accountName), Toast.LENGTH_LONG).show(); } else if (e instanceof AuthenticationException) { Toast.makeText(BaseActivity.this, getString(R.string.auth_error, accountName), Toast.LENGTH_LONG).show(); } else if (e instanceof AdmobRateLimitExceededException) { Toast.makeText(BaseActivity.this, getString(R.string.admob_ratelimit_error), Toast.LENGTH_LONG).show(); } else if (e instanceof AdmobAskForPasswordException) { Log.w(TAG, "ask for admob credentials"); setSkipMainReload(true); } else if (e instanceof AdmobAccountRemovedException) { String wrongAccount = ((AdmobAccountRemovedException) e).getAccountName(); Toast.makeText(BaseActivity.this, getString(R.string.admob_missing_error, wrongAccount), Toast.LENGTH_LONG) .show(); } else if (e instanceof AdmobInvalidRequestException) { Toast.makeText(BaseActivity.this, getString(R.string.admob_invalid_request_error), Toast.LENGTH_LONG).show(); } else if (e instanceof AdmobInvalidTokenException) { Toast.makeText(BaseActivity.this, getString(R.string.admob_invalid_token_error), Toast.LENGTH_LONG).show(); } else if (e instanceof AdmobGenericException) { Log.w(TAG, e.getMessage(), e); Toast.makeText(BaseActivity.this, getString(R.string.admob_generic_error), Toast.LENGTH_LONG).show(); } else if (e instanceof DevConsoleProtocolException) { int appVersionCode = Utils.getAppVersionCode(this); if (Preferences.getLatestVersionCode(this) > appVersionCode) { showNewVersionDialog(e); } else { showGoogleErrorDialog(e); } } else if (e instanceof MultiAccountException) { showAspErrorDialog(e); } else { showCrashDialog(e); } } private void showNewVersionDialog(Exception e) { if (!isFinishing()) { CrashDialog.CrashDialogBuilder builder = new CrashDialogBuilder(this); builder.setTitle(getString(R.string.update_required_title)); builder.setMessage(R.string.newversion_desc); builder.setPositiveButton(getString(R.string.update_button), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent goToMarket = null; goToMarket = new Intent(Intent.ACTION_VIEW, Uri .parse(getString(R.string.market_uri))); startActivity(goToMarket); dialog.dismiss(); } }); builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); } } protected void showCrashDialog(final Exception e) { if (!isFinishing()) { CrashDialog.CrashDialogBuilder builder = new CrashDialogBuilder(this); builder.setTitle(getString(R.string.crash_dialog_title)); builder.setMessage(R.string.crash_desc); builder.setPositiveButton(getString(R.string.send_report_button), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (!isFinishing()) { Thread thread = new Thread(new Runnable() { @Override public void run() { sendAracReport(e, true); } }); thread.run(); dialog.dismiss(); } } }); builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); } } private void sendAracReport(Exception e, boolean userTriggered) { ACRA.getErrorReporter().handleSilentException(e); } protected void showGoogleErrorDialog(final Exception e) { if (!isFinishing()) { CrashDialog.CrashDialogBuilder builder = new CrashDialogBuilder(this); builder.setTitle(getString(R.string.crash_dialog_title)); builder.setMessage(getString(R.string.remote_interface_changed_error)); builder.setPositiveButton(getString(R.string.send_report_button), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Thread thread = new Thread(new Runnable() { @Override public void run() { sendAracReport(e, true); } }); thread.run(); dialog.dismiss(); } }); builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); } } protected void showAspErrorDialog(final Exception e) { if (!isFinishing()) { CrashDialog.CrashDialogBuilder builder = new CrashDialogBuilder(this); builder.setTitle(getString(R.string.multiple_dev_accounts_title)); builder.setMessage(getString(R.string.multiple_dev_accounts_error)); builder.setPositiveButton(getString(R.string.logout), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); developerAccountManager.unselectDeveloperAccount(); Preferences.saveSkipAutoLogin(BaseActivity.this, true); Intent intent = new Intent(BaseActivity.this, LoginActivity.class); startActivity(intent); overridePendingTransition(R.anim.activity_fade_in, R.anim.activity_fade_out); } }); builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); developerAccountManager.unselectDeveloperAccount(); Preferences.saveSkipAutoLogin(BaseActivity.this, true); Intent intent = new Intent(BaseActivity.this, LoginActivity.class); startActivity(intent); overridePendingTransition(R.anim.activity_fade_in, R.anim.activity_fade_out); } }); builder.create().show(); } } public ContentAdapter getDbAdapter() { return getAndlyticsApplication().getDbAdapter(); } protected void showLoadingIndicator(ViewSwitcher switcher) { Animation loadingAnim = AnimationUtils.loadAnimation(this, R.anim.loading); loadingAnim.setInterpolator(new LinearInterpolator()); switcher.showNext(); } protected void hideLoadingIndicator(ViewSwitcher switcher) { switcher.showPrevious(); } public AndlyticsApp getAndlyticsApplication() { return (AndlyticsApp) getApplication(); } public boolean shouldRemoteUpdateStats() { long now = System.currentTimeMillis(); long lastUpdate = developerAccountManager.getLastStatsRemoteUpdateTime(accountName); // never updated if (lastUpdate == 0) { return true; } return (now - lastUpdate) >= Preferences.STATS_REMOTE_UPDATE_INTERVAL; } public boolean isRefreshing() { return refreshing; } public void refreshStarted() { ensureMainThread(); refreshing = true; invalidateOptionsMenu(); } public void refreshFinished() { ensureMainThread(); refreshing = false; invalidateOptionsMenu(); } private void ensureMainThread() { Looper looper = Looper.myLooper(); if (looper != null && looper != getMainLooper()) { throw new IllegalStateException("Only call this from your main thread."); } } protected void setSkipMainReload(boolean skipMainReload) { this.skipMainReload = skipMainReload; } protected boolean isSkipMainReload() { return skipMainReload; } public String getPackage() { return packageName; } public String getDeveloperId() { return developerId; } public String getAccountName() { return accountName; } protected boolean checkGooglePlayServicesAvailable() { int connectionStatusCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) { showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode); return false; } return true; } private void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) { runOnUiThread(new Runnable() { public void run() { Dialog dialog = GooglePlayServicesUtil.getErrorDialog(connectionStatusCode, BaseActivity.this, REQUEST_GOOGLE_PLAY_SERVICES); dialog.show(); } }); } }