/** * Copyright (c) 2015 unfoldingWord * http://creativecommons.org/licenses/MIT/ * See LICENSE file for details. * Contributors: * PJ Fechner <pj@actsmedia.com> */ package activity; import android.Manifest; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; import android.view.KeyEvent; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.TextView; import org.unfoldingword.mobile.R; import fragments.LoadingFragment; import view.UWToolbarViewGroup; /** * A login screen that offers login via email/password. */ abstract public class UWBaseActivity extends ActionBarActivity implements UWToolbarViewGroup.UWToolbarListener{ private static final String TAG = "UWBaseActivity"; private UWToolbarViewGroup toolbar; private LoadingFragment loadingFragment; private RelativeLayout loadingBox; protected boolean isLoading; private boolean isActive = false; /** * * @return The AnimationParadigm for this activity */ abstract public AnimationParadigm getAnimationParadigm(); //region Parent Overrides @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); isActive = true; } @Override protected void onStart() { super.onStart(); isActive = true; } @Override protected void onResume() { super.onResume(); isActive = true; } @Override protected void onPause() { super.onPause(); isActive = false; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { handleBack(); } return super.onOptionsItemSelected(item); } @Override public void onBackPressed() { handleBack(); } /** *Before 2.0 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { handleBack(); return true; } return super.onKeyDown(keyCode, event); } //endregion //region Accessors public boolean isActive() { return isActive; } public UWToolbarViewGroup getToolbar(){ return toolbar; } //endregion //region Setup /** * Sets up the toolbar with the passed parameters * @param hasLogo will show the logo if true * @param titleText will show the title with this text * @param titleClickable whether the title should be clickable * @param rightButtonClickable whether the right button should be shown and clickable. */ public void setupToolbar(boolean hasLogo, String titleText, boolean titleClickable, boolean rightButtonClickable){ setupToolbar(hasLogo, titleText, titleClickable); toolbar.setRightImageVisible(rightButtonClickable); } /** * Sets up the toolbar with the passed parameters * @param hasLogo will show the logo if true * @param titleText will show the title with this text * @param titleClickable whether the title should be clickable */ public void setupToolbar(boolean hasLogo, String titleText, boolean titleClickable){ setupToolbar(hasLogo); toolbar.setTitle(titleText, titleClickable); } /** * Sets up the toolbar based on the passed parameters * @param hasLogo will show the logo if true */ public void setupToolbar(boolean hasLogo){ toolbar = new UWToolbarViewGroup((Toolbar) findViewById(R.id.toolbar), this, hasLogo, getBackResource(), this); setToolbarColor(getResources().getColor(R.color.primary_dark)); } /** * Will set the background color of the toolbar * @param color the desired color resource of the toolbar */ protected void setToolbarColor(int color){ this.toolbar.setBackgroundColor(color); } /** * * @return resource for the back button */ public int getBackResource(){ if(getAnimationParadigm() == AnimationParadigm.ANIMATION_VERTICAL || getAnimationParadigm() == AnimationParadigm.ANIMATION_FORWARD_RIGHT_BACK_DOWN){ return R.drawable.x_button; } else { return R.drawable.back_button_light; } } //endregion //region user interaction //endregion /** * creates a loading box and puts it in the passed viewGroup * @param visible Loading box should be showing * @param viewGroupId */ protected void setLoadingBoxVisible(boolean visible, int viewGroupId){ if(loadingBox == null){ ViewGroup group = (ViewGroup) findViewById(viewGroupId); loadingBox = (RelativeLayout) getLayoutInflater().inflate(R.layout.loading_box, group); loadingBox = (RelativeLayout) findViewById(R.id.loading_box_base_layout); } loadingBox.setVisibility((visible) ? View.VISIBLE : View.GONE); } /** * Creates and Loading fragment. * @param visible true if the fragment should be visible * @param loadingText text to show in the loading fragment * @param cancelable whether the fragment should be cancelable. */ public void setLoadingFragmentVisibility(final boolean visible, final String loadingText, final boolean cancelable){ runOnUiThread(new Runnable() { @Override public void run() { if (!visible) { if (loadingFragment != null) { loadingFragment.dismiss(); } return; } else { if (loadingFragment == null) { loadingFragment = LoadingFragment.newInstance(loadingText); loadingFragment.setCancelable(cancelable); loadingFragment.setListener(new LoadingFragment.LoadingFragmentInteractionListener() { @Override public void loadingCanceled() { loadingFragment.dismiss(); getSupportFragmentManager().popBackStackImmediate(); loadingFragment = null; } }); loadingFragment.show(getSupportFragmentManager(), LoadingFragment.TAG); } else if (!loadingFragment.isVisible()) { loadingFragment.show(getSupportFragmentManager(), LoadingFragment.TAG); } loadingFragment.setLoadingText(loadingText); loadingFragment.setCanCancel(cancelable); } } }); } /** * rotates the screen to portrait if it's currently in landscape, or landscape it it's currently in portrait * @param shouldMakeSensorBased whether the activity should reset to sensor based orientation after changing */ protected void rotate(boolean shouldMakeSensorBased){ if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else{ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } if(shouldMakeSensorBased){ waitAndMakeOrientationSensorBased(); } } /** * waits for 2 second and makes the activity's orientation sensor based */ protected void waitAndMakeOrientationSensorBased(){ Thread thread = new Thread("orientationThread") { @Override public void run() { try { synchronized (this) { wait(2000); } } catch (InterruptedException ex) { ex.printStackTrace(); } setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); } }; thread.start(); } //endregion //region Changing Activities /** * Starts new activity with a vertical popover-like animation * @param nextClass the class of the new activity */ public void goToNewActivity(Class nextClass){ goToNewActivity(new Intent(getApplicationContext(), nextClass)); } /** * Starts new activity with a vertical popover-like animation * @param intent Intent of the new activity */ public void goToNewActivity(Intent intent){ int enterAnimation = AnimationParadigm.getNextAnimationEnter(AnimationParadigm.ANIMATION_VERTICAL); int exitAnimation = AnimationParadigm.getNextAnimationExit(AnimationParadigm.ANIMATION_VERTICAL); startActivity(intent); overridePendingTransition(enterAnimation, exitAnimation); } /** * starts a new activity with the activity's forward animation * @param nextClass class for new activity */ public void goToNextActivity(Class nextClass){ goToNextActivity(new Intent(getApplicationContext(), nextClass)); } /** * starts a new activity with the activity's forward animation * @param intent Intent for new activity */ public void goToNextActivity(Intent intent){ int enterAnimation = AnimationParadigm.getNextAnimationEnter(getAnimationParadigm()); int exitAnimation = AnimationParadigm.getNextAnimationExit(getAnimationParadigm()); startActivity(intent); overridePendingTransition(enterAnimation, exitAnimation); } public void onBackPressed(boolean isSharing) { handleBack(); } /** * goes back to the previous activity using the activity's back animation */ protected void handleBack(){ int enterAnimation = AnimationParadigm.getEndingAnimationEnter(getAnimationParadigm()); int exitAnimation = AnimationParadigm.getEndingAnimationExit(getAnimationParadigm()); finish(); overridePendingTransition(enterAnimation, exitAnimation); } /** * goes to a new activity using the activity's back animation * @param activity new activity class to start */ protected void goBackToActivity(Class activity){ goBackToActivity(activity, null); } /** * starts a new activity using the activity's back animation * @param activity new activity class to start * @param extras option extras to add to the new Intent */ protected void goBackToActivity(Class activity, Bundle extras){ int enterAnimation = AnimationParadigm.getEndingAnimationEnter(AnimationParadigm.ANIMATION_VERTICAL); int exitAnimation = AnimationParadigm.getEndingAnimationExit(AnimationParadigm.ANIMATION_VERTICAL); Intent intent = new Intent(getApplicationContext(), activity); if(extras != null){ intent.putExtras(extras); } startActivity(intent); overridePendingTransition(enterAnimation, exitAnimation); finish(); } //endregion public void showAlert(String title, String message){ showAlert(title, message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); } public void showAlert(String title, String message, DialogInterface.OnClickListener clickListener){ AlertDialog alertDialog = new AlertDialog.Builder(this).create(); alertDialog.setTitle(title); alertDialog.setMessage(message); alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "Dismiss", clickListener); alertDialog.show(); } //region Toolbar Listener @Override public void centerButtonClicked() { } @Override public void leftButtonClicked() { handleBack(); } @Override public void rightButtonClicked() { } //endregion private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; /** * Checks if the app has permission to write to device storage * * If the app does not has permission then the user will be prompted to grant permissions * */ /** * * @return true if app has storage permissions */ public boolean verifyOrRequestStoragePermissions() { if (!verifyStoragePermissions()) { askForStoragePermission(); return false; } else{ return true; } } public boolean verifyStoragePermissions() { return permissionIsAllowed(Manifest.permission.WRITE_EXTERNAL_STORAGE) && permissionIsAllowed(Manifest.permission.READ_EXTERNAL_STORAGE); } private boolean permissionIsAllowed(String permissionID) { return ContextCompat.checkSelfPermission(this, permissionID) == PackageManager.PERMISSION_GRANTED; } public void askForStoragePermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { showAlert("Storage Permission", "Allow access to external storage if you would like to share or receive Versions directly from another device", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { askForStoragePermission(); } }); } else if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) { showAlert("Storage Permission", "Allow access to external storage if you would like to share or receive Versions directly from another device", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { askForStoragePermission(); } }); } else{ ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_EXTERNAL_STORAGE: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { storagePermissionWasGranted(); } } } } public void storagePermissionWasGranted() { } public void showChoiceDialogue(String title, String message, DialogInterface.OnClickListener positiveListener, DialogInterface.OnClickListener negativeListener) { View titleView = View.inflate(getApplicationContext(), R.layout.alert_title, null); ((TextView) titleView.findViewById(R.id.alert_title_text_view)).setText(title); new android.app.AlertDialog.Builder(this) .setCustomTitle(titleView) .setMessage(message) .setIcon(android.R.drawable.ic_dialog_alert) .setPositiveButton("Yes", positiveListener) .setNegativeButton("No", negativeListener) .show(); } }