diff --git a/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java b/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java index ccdbfd8b..9d432bea 100644 --- a/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java +++ b/src/main/java/com/nutomic/syncthingandroid/activities/MainActivity.java @@ -1,7 +1,7 @@ package com.nutomic.syncthingandroid.activities; +import android.Manifest; import android.annotation.SuppressLint; -import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.ComponentName; @@ -14,10 +14,14 @@ import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; import android.support.design.widget.TabLayout; +import android.support.v4.app.ActivityCompat; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; @@ -25,13 +29,13 @@ import android.support.v7.app.ActionBarDrawerToggle; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; -import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import android.widget.Toast; import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.fragments.DeviceListFragment; @@ -40,6 +44,7 @@ import com.nutomic.syncthingandroid.fragments.FolderListFragment; import com.nutomic.syncthingandroid.syncthing.RestApi; import com.nutomic.syncthingandroid.syncthing.SyncthingService; +import java.util.Arrays; import java.util.Date; import java.util.concurrent.TimeUnit; @@ -62,70 +67,82 @@ public class MainActivity extends SyncthingActivity */ private static final long USAGE_REPORTING_DIALOG_DELAY = TimeUnit.DAYS.toMillis(3); - private AlertDialog mLoadingDialog; + private static final int REQUEST_WRITE_STORAGE = 142; + private AlertDialog mLoadingDialog; private AlertDialog mDisabledDialog; + private ViewPager mViewPager; + + private FolderListFragment mFolderListFragment; + private DeviceListFragment mDeviceListFragment; + private DrawerFragment mDrawerFragment; + + private ActionBarDrawerToggle mDrawerToggle; + private DrawerLayout mDrawerLayout; + + private SharedPreferences mPreferences; + /** - * Causes population of folder and device lists, unlocks info drawer. + * Handles various dialogs based on current state. */ @Override - @SuppressLint("InflateParams") public void onApiChange(SyncthingService.State currentState) { - if (currentState == SyncthingService.State.ACTIVE && - new Date().getTime() > getFirstStartTime() + USAGE_REPORTING_DIALOG_DELAY && - getApi().getUsageReportAccepted() == RestApi.UsageReportSetting.UNDECIDED) { - showUsageReportingDialog(); - } else if (currentState == SyncthingService.State.ERROR) { - finish(); - } else if (currentState != SyncthingService.State.ACTIVE && !isFinishing()) { - if (currentState == SyncthingService.State.DISABLED) { - if (mLoadingDialog != null) { - mLoadingDialog.dismiss(); - mLoadingDialog = null; - } - mDisabledDialog = SyncthingService.showDisabledDialog(MainActivity.this); - } else if (mLoadingDialog == null) { - LayoutInflater inflater = getLayoutInflater(); - View dialogLayout = inflater.inflate(R.layout.dialog_loading, null); - TextView loadingText = (TextView) dialogLayout.findViewById(R.id.loading_text); - loadingText.setText((getService().isFirstStart()) - ? R.string.web_gui_creating_key - : R.string.api_loading); - - mLoadingDialog = new AlertDialog.Builder(MainActivity.this) - .setCancelable(false) - .setView(dialogLayout) - .show(); - - final SharedPreferences sp = - PreferenceManager.getDefaultSharedPreferences(MainActivity.this); - + switch (currentState) { + case INIT: + mLoadingDialog.show(); // Make sure the first start dialog is shown on top. - if (sp.getBoolean("first_start", true)) { - showFirstStartDialog(sp); + if (isFirstStart()) { + showFirstStartDialog(); } - } - return; + break; + case STARTING: + mLoadingDialog.show(); + dismissDisabledDialog(); + int permissionState = ContextCompat.checkSelfPermission(this, + Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (permissionState != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + REQUEST_WRITE_STORAGE); + } + break; + case ACTIVE: + mLoadingDialog.hide(); + dismissDisabledDialog(); + mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); + mDrawerFragment.requestGuiUpdate(); + if (new Date().getTime() > getFirstStartTime() + USAGE_REPORTING_DIALOG_DELAY && + getApi().getUsageReportAccepted() == RestApi.UsageReportSetting.UNDECIDED) { + showUsageReportingDialog(); + } + break; + case ERROR: + finish(); + break; + case DISABLED: + mLoadingDialog.hide(); + if (!isFinishing()) { + mDisabledDialog = SyncthingService.showDisabledDialog(MainActivity.this); + } + break; } + } - if (mLoadingDialog != null) { - mLoadingDialog.dismiss(); - mLoadingDialog = null; - } + private void dismissDisabledDialog() { if (mDisabledDialog != null) { - mDisabledDialog.dismiss(); + mDisabledDialog.cancel(); mDisabledDialog = null; } + } - mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); - mDrawerFragment.requestGuiUpdate(); + private boolean isFirstStart() { + return mPreferences.getBoolean("first_start", true); } /** * Returns the unix timestamp at which the app was first installed. */ - @TargetApi(9) private long getFirstStartTime() { PackageManager pm = getPackageManager(); long firstInstallTime = 0; @@ -140,14 +157,14 @@ public class MainActivity extends SyncthingActivity /** * Displays information for first app start. */ - private void showFirstStartDialog(final SharedPreferences sp) { + private void showFirstStartDialog() { new AlertDialog.Builder(MainActivity.this) .setTitle(R.string.welcome_title) .setMessage(R.string.welcome_text) .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - sp.edit().putBoolean("first_start", false).apply(); + mPreferences.edit().putBoolean("first_start", false).apply(); } }) .show(); @@ -186,18 +203,6 @@ public class MainActivity extends SyncthingActivity } }; - private FolderListFragment mFolderListFragment; - - private DeviceListFragment mDeviceListFragment; - - private DrawerFragment mDrawerFragment; - - private ViewPager mViewPager; - - private ActionBarDrawerToggle mDrawerToggle; - - private DrawerLayout mDrawerLayout; - /** * Initializes tab navigation. */ @@ -205,6 +210,7 @@ public class MainActivity extends SyncthingActivity super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + mPreferences = PreferenceManager.getDefaultSharedPreferences(this); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mViewPager = (ViewPager) findViewById(R.id.pager); @@ -236,13 +242,27 @@ public class MainActivity extends SyncthingActivity mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); mDrawerLayout.setDrawerListener(mDrawerToggle); setOptimalDrawerWidth(findViewById(R.id.drawer)); + + LayoutInflater inflater = getLayoutInflater(); + @SuppressLint("InflateParams") + View dialogLayout = inflater.inflate(R.layout.dialog_loading, null); + TextView loadingText = (TextView) dialogLayout.findViewById(R.id.loading_text); + loadingText.setText((isFirstStart()) + ? R.string.web_gui_creating_key + : R.string.api_loading); + + mLoadingDialog = new AlertDialog.Builder(MainActivity.this) + .setCancelable(false) + .setView(dialogLayout) + .create(); } @Override public void onDestroy() { super.onDestroy(); - if (mLoadingDialog != null) { - mLoadingDialog.dismiss(); + mLoadingDialog.dismiss(); + if (mDisabledDialog != null) { + mDisabledDialog.dismiss(); } if (getService() != null) { getService().unregisterOnApiChangeListener(this); @@ -323,7 +343,7 @@ public class MainActivity extends SyncthingActivity * Closes the drawer. Use when navigating away from activity. */ public void closeDrawer() { - mDrawerLayout.closeDrawer(Gravity.LEFT); + mDrawerLayout.closeDrawer(GravityCompat.START); } /** @@ -332,8 +352,8 @@ public class MainActivity extends SyncthingActivity @Override public boolean onKeyDown(int keyCode, KeyEvent e) { if (keyCode == KeyEvent.KEYCODE_MENU) { - if (!mDrawerLayout.isDrawerOpen(Gravity.LEFT)) - mDrawerLayout.openDrawer(Gravity.RIGHT); + if (!mDrawerLayout.isDrawerOpen(GravityCompat.START)) + mDrawerLayout.openDrawer(GravityCompat.END); else closeDrawer(); @@ -399,11 +419,28 @@ public class MainActivity extends SyncthingActivity .setView(v) .setPositiveButton(R.string.yes, listener) .setNegativeButton(R.string.no, listener) - .setNeutralButton("Open Website", listener) - .setCancelable(false) + .setNeutralButton(R.string.open_website, listener) .show(); } }); } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + switch (requestCode) { + case REQUEST_WRITE_STORAGE: + Log.d(TAG, Arrays.toString(grantResults)); + if (grantResults.length == 0 || + grantResults[0] != PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, R.string.toast_write_storage_permission_required, + Toast.LENGTH_LONG).show(); + finish(); + } + break; + default: + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + } + } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 3c698ea3..e2db192f 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -30,6 +30,10 @@ off + Open Website + + Write storage permission is required for this app +