package yuku.alkitab.base.ac.base; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.support.annotation.CallSuper; import android.support.v4.app.ActivityCompat; import android.support.v4.app.NavUtils; import android.support.v4.app.TaskStackBuilder; import android.support.v4.content.ContextCompat; import android.support.v4.content.res.ResourcesCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.util.TypedValue; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import com.afollestad.materialdialogs.MaterialDialog; import yuku.afw.storage.Preferences; import yuku.alkitab.base.storage.Prefkey; import yuku.alkitab.base.widget.ConfigurationWrapper; import yuku.alkitab.base.widget.Localized; import yuku.alkitab.debug.R; import java.util.concurrent.atomic.AtomicBoolean; import static yuku.alkitab.base.util.Literals.Array; public abstract class BaseActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { public static final String TAG = BaseActivity.class.getSimpleName(); private static final int REQCODE_PERMISSION_storage = 1; private static final int REQCODE_permissionSettings = 9970; private boolean willNeedStoragePermission; private int lastKnownConfigurationSerialNumber; @Override protected void attachBaseContext(final Context base) { super.attachBaseContext(ConfigurationWrapper.wrap(base)); } @Override protected void onStart() { super.onStart(); applyActionBarAndStatusBarColors(); final int currentConfigurationSerialNumber = ConfigurationWrapper.getSerialCounter(); if (lastKnownConfigurationSerialNumber != currentConfigurationSerialNumber) { Log.d(TAG, "Restarting activity " + getClass().getName() + " because of configuration change " + lastKnownConfigurationSerialNumber + " -> " + currentConfigurationSerialNumber); lastKnownConfigurationSerialNumber = currentConfigurationSerialNumber; recreate(); } } protected void applyActionBarAndStatusBarColors() { // action bar color and status bar color are set based on night mode final ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { if (Preferences.getBoolean(Prefkey.is_night_mode, false)) { actionBar.setBackgroundDrawable(new ColorDrawable(ResourcesCompat.getColor(getResources(), R.color.primary_night_mode, getTheme()))); if (Build.VERSION.SDK_INT >= 21) { getWindow().setStatusBarColor(0xff000000); } } else { final TypedValue tv = new TypedValue(); getTheme().resolveAttribute(R.attr.colorPrimary, tv, true); actionBar.setBackgroundDrawable(new ColorDrawable(tv.data)); if (Build.VERSION.SDK_INT >= 21) { getWindow().setStatusBarColor(ResourcesCompat.getColor(getResources(), R.color.primary_dark, getTheme())); } } } } /** * Call this from subclasses before super.onCreate() to make * the activity ask for storage permission and do not proceed * if the permission is not granted. */ protected void willNeedStoragePermission() { this.willNeedStoragePermission = true; } @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); lastKnownConfigurationSerialNumber = ConfigurationWrapper.getSerialCounter(); if (willNeedStoragePermission) { askStoragePermission(); } // to ensure that title is localized try { final ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), 0); if (activityInfo.labelRes != 0) { setTitle(Localized.text(activityInfo.labelRes)); } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Internal consistency error", e); } } private void askStoragePermission() { if (!( Build.VERSION.SDK_INT < 16 || ( ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED ) )) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE) ) { final AtomicBoolean oked = new AtomicBoolean(false); new MaterialDialog.Builder(this) .content(R.string.storage_permission_rationale) .positiveText(R.string.ok) .onPositive((materialDialog, dialogAction) -> { oked.set(true); ActivityCompat.requestPermissions(this, Array(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE), REQCODE_PERMISSION_storage); }) .dismissListener(dialog -> { if (!oked.get()) { finish(); } }) .show(); } else { ActivityCompat.requestPermissions(this, Array(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE), REQCODE_PERMISSION_storage); } } else { onNeededPermissionsGranted(true); } } /** * Override this to do something after we confirm that all needed permissions are granted. * This is only called if {@link #willNeedStoragePermission()} was called. * * @param immediatelyGranted whether the permission is granted immediately without leaving the first onCreate(). * Use this to determine whether we need to do initialization (e.g. load dir contents) * and to determine whether it is safe to init now. */ protected void onNeededPermissionsGranted(boolean immediatelyGranted) { } @Override public void onRequestPermissionsResult(final int requestCode, final String[] permissions, final int[] grantResults) { if (requestCode == REQCODE_PERMISSION_storage) { // all must be granted boolean allGranted = true; for (final int grantResult : grantResults) { if (grantResult != PackageManager.PERMISSION_GRANTED) { allGranted = false; } } if (allGranted) { onNeededPermissionsGranted(false); } else { if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) || !ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) { // user selects do not ask again final AtomicBoolean oked = new AtomicBoolean(false); new MaterialDialog.Builder(this) .content("You need to have the Storage permission enabled to continue, because we need to store shared media such as Bible versions and fonts.") .positiveText(R.string.ok) .onPositive((materialDialog, dialogAction) -> { oked.set(true); startActivityForResult(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(Uri.fromParts("package", getPackageName(), null)), REQCODE_permissionSettings); }) .negativeText(R.string.cancel) .dismissListener(dialog -> { if (!oked.get()) { finish(); } }) .show(); } else { finish(); } } return; } super.onRequestPermissionsResult(requestCode, permissions, grantResults); } @Override protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (requestCode == REQCODE_permissionSettings) { askStoragePermission(); return; } super.onActivityResult(requestCode, resultCode, data); } @CallSuper @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { navigateUp(); return true; } return super.onOptionsItemSelected(item); } protected void navigateUp() { final Intent upIntent = NavUtils.getParentActivityIntent(this); if (upIntent == null) { // not defined in manifest, let us finish() instead. finish(); return; } if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) { TaskStackBuilder.create(this) .addNextIntentWithParentStack(upIntent) .startActivities(); } else { NavUtils.navigateUpTo(this, upIntent); } } @Override public void onConfigurationChanged(final Configuration newConfig) { super.onConfigurationChanged(newConfig); { // reconfigure toolbar height (Need to have a toolbar with id toolbar) final View v = findViewById(R.id.toolbar); if (v instanceof Toolbar) { final Toolbar toolbar = (Toolbar) v; final ViewGroup.LayoutParams lp = toolbar.getLayoutParams(); final TypedValue tv = new TypedValue(); getTheme().resolveAttribute(R.attr.actionBarSize, tv, true); final int h = (int) tv.getDimension(getResources().getDisplayMetrics()); lp.height = h; toolbar.setLayoutParams(lp); // Workaround for https://code.google.com/p/android/issues/detail?id=79813 toolbar.setMinimumHeight(h); } } } }