From 439c7118f1a382e4a02cef17b12cc08be4ad74bd Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Tue, 29 Aug 2017 03:08:09 +0800 Subject: [PATCH] Proper runtime permission implementation --- .../topjohnwu/magisk/MagiskLogFragment.java | 47 ++++++---------- .../com/topjohnwu/magisk/MainActivity.java | 9 ---- .../topjohnwu/magisk/SettingsActivity.java | 5 +- .../topjohnwu/magisk/components/Activity.java | 18 +++++++ .../com/topjohnwu/magisk/utils/Utils.java | 54 +++++++++++-------- 5 files changed, 69 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java index 1094f1e22..436cf0cc4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java @@ -1,11 +1,9 @@ package com.topjohnwu.magisk; +import android.Manifest; import android.annotation.SuppressLint; -import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.text.TextUtils; @@ -25,6 +23,7 @@ import com.topjohnwu.magisk.asyncs.ParallelTask; import com.topjohnwu.magisk.components.Fragment; import com.topjohnwu.magisk.components.SnackbarMaker; import com.topjohnwu.magisk.utils.Shell; +import com.topjohnwu.magisk.utils.Utils; import java.io.File; import java.io.FileWriter; @@ -40,25 +39,18 @@ public class MagiskLogFragment extends Fragment { private static final String MAGISK_LOG = "/cache/magisk.log"; private Unbinder unbinder; + @BindView(R.id.txtLog) TextView txtLog; @BindView(R.id.svLog) ScrollView svLog; @BindView(R.id.hsvLog) HorizontalScrollView hsvLog; - @BindView(R.id.progressBar) ProgressBar progressBar; - private MenuItem mClickedMenuItem; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - } - @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_magisk_log, container, false); unbinder = ButterKnife.bind(this, view); + setHasOptionsMenu(true); txtLog.setTextIsSelectable(true); @@ -92,13 +84,14 @@ public class MagiskLogFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem item) { - mClickedMenuItem = item; switch (item.getItemId()) { case R.id.menu_refresh: new LogManager().read(); return true; case R.id.menu_save: - new LogManager().save(); + Utils.runWithPermission(getActivity(), + Manifest.permission.WRITE_EXTERNAL_STORAGE, + () -> new LogManager().save()); return true; case R.id.menu_clear: new LogManager().clear(); @@ -108,25 +101,15 @@ public class MagiskLogFragment extends Fragment { } } - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == 0) { - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (mClickedMenuItem != null) { - new Handler().postDelayed(() -> onOptionsItemSelected(mClickedMenuItem), 500); - } - } else { - SnackbarMaker.make(txtLog, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show(); - } - } - } - private class LogManager extends ParallelTask { private int mode; private File targetFile; + LogManager() { + super(MagiskLogFragment.this.getActivity()); + } + @SuppressLint("DefaultLocale") @Override protected Object doInBackground(Object... params) { @@ -138,7 +121,7 @@ public class MagiskLogFragment extends Fragment { return logList.toString(); case 1: - getShell().su_raw("echo > " + MAGISK_LOG); + getShell().su_raw("echo -n > " + MAGISK_LOG); SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show(); return ""; @@ -150,7 +133,7 @@ public class MagiskLogFragment extends Fragment { now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND)); - targetFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MagiskManager/" + filename); + targetFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename); if ((!targetFile.getParentFile().exists() && !targetFile.getParentFile().mkdirs()) || (targetFile.exists() && !targetFile.delete())) { @@ -187,9 +170,9 @@ public class MagiskLogFragment extends Fragment { case 2: boolean bool = (boolean) o; if (bool) { - MagiskLogFragment.this.getApplication().toast(targetFile.toString(), Toast.LENGTH_LONG); + getMagiskManager().toast(targetFile.toString(), Toast.LENGTH_LONG); } else { - MagiskLogFragment.this.getApplication().toast(R.string.logs_save_failed, Toast.LENGTH_LONG); + getMagiskManager().toast(R.string.logs_save_failed, Toast.LENGTH_LONG); } break; } diff --git a/app/src/main/java/com/topjohnwu/magisk/MainActivity.java b/app/src/main/java/com/topjohnwu/magisk/MainActivity.java index 906999fe7..e2e8ad246 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MainActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/MainActivity.java @@ -1,15 +1,11 @@ package com.topjohnwu.magisk; -import android.Manifest; import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; -import android.support.v4.app.ActivityCompat; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.DrawerLayout; @@ -52,11 +48,6 @@ public class MainActivity extends Activity setContentView(R.layout.activity_main); ButterKnife.bind(this); - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); - } - setSupportActionBar(toolbar); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) { diff --git a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java index 3ea1f9890..9a7b91a27 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java @@ -1,5 +1,6 @@ package com.topjohnwu.magisk; +import android.Manifest; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; @@ -125,7 +126,9 @@ public class SettingsActivity extends Activity implements Topic.Subscriber { }); hideManager.setOnPreferenceClickListener((pref) -> { - new HideManager(getActivity()).exec(); + Utils.runWithPermission(getActivity(), + Manifest.permission.WRITE_EXTERNAL_STORAGE, + () -> new HideManager(getActivity()).exec()); return true; }); diff --git a/app/src/main/java/com/topjohnwu/magisk/components/Activity.java b/app/src/main/java/com/topjohnwu/magisk/components/Activity.java index 90ea223a1..4404d3db2 100644 --- a/app/src/main/java/com/topjohnwu/magisk/components/Activity.java +++ b/app/src/main/java/com/topjohnwu/magisk/components/Activity.java @@ -1,7 +1,9 @@ package com.topjohnwu.magisk.components; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.WindowManager; @@ -13,6 +15,8 @@ import com.topjohnwu.magisk.utils.Topic; public class Activity extends AppCompatActivity { + private Runnable permissionGrantCallback; + public Activity() { super(); Configuration configuration = new Configuration(); @@ -36,6 +40,20 @@ public class Activity extends AppCompatActivity { super.onDestroy(); } + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (permissionGrantCallback != null) { + permissionGrantCallback.run(); + } + } + permissionGrantCallback = null; + } + + public void setPermissionGrantCallback(Runnable callback) { + permissionGrantCallback = callback; + } + @Override public MagiskManager getApplicationContext() { return (MagiskManager) super.getApplicationContext(); diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 7fe194724..9d2da3974 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -23,6 +23,7 @@ import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; +import android.support.v4.content.ContextCompat; import android.text.TextUtils; import android.widget.Toast; @@ -80,32 +81,28 @@ public class Utils { if (isDownloading) return; - if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { - Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show(); - return; - } + runWithPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> { + File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename); - File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename); + if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs()) + || (file.exists() && !file.delete())) { + Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show(); + return; + } - if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs()) - || (file.exists() && !file.delete())) { - Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show(); - return; - } + Toast.makeText(context, context.getString(R.string.downloading_toast, filename), Toast.LENGTH_LONG).show(); + isDownloading = true; - Toast.makeText(context, context.getString(R.string.downloading_toast, filename), Toast.LENGTH_LONG).show(); - isDownloading = true; + DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - - if (link != null) { - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(link)); - request.setDestinationUri(Uri.fromFile(file)); - receiver.setDownloadID(downloadManager.enqueue(request)); - } - receiver.setFilename(filename); - context.getApplicationContext().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); + if (link != null) { + DownloadManager.Request request = new DownloadManager.Request(Uri.parse(link)); + request.setDestinationUri(Uri.fromFile(file)); + receiver.setDownloadID(downloadManager.enqueue(request)); + } + receiver.setFilename(filename); + context.getApplicationContext().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); + }); } public static String getLegalFilename(CharSequence filename) { @@ -314,4 +311,17 @@ public class Utils { } return builder.toString(); } + + public static void runWithPermission(Context context, String permission, Runnable callback) { + if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { + // Passed in context should be an activity if not granted, need to show dialog! + if (!(context instanceof com.topjohnwu.magisk.components.Activity)) + return; + com.topjohnwu.magisk.components.Activity activity = (com.topjohnwu.magisk.components.Activity) context; + activity.setPermissionGrantCallback(callback); + ActivityCompat.requestPermissions(activity, new String[] { permission }, 0); + } else { + callback.run(); + } + } } \ No newline at end of file