OSDN Git Service

eleven: Runtime permissions
authorSteve Kondik <steve@cyngn.com>
Sun, 4 Sep 2016 18:27:33 +0000 (11:27 -0700)
committerSteve Kondik <steve@cyngn.com>
Sun, 4 Sep 2016 18:27:33 +0000 (11:27 -0700)
 * Add prompting for storage permissions in order to bump the
   API level up to level 24.

Change-Id: Id3fc4ee06fe3534b2f94408e96a8163f4fae8f98

src/com/cyanogenmod/eleven/MusicPlaybackService.java
src/com/cyanogenmod/eleven/ui/activities/HomeActivity.java

index bed0afa..485542d 100644 (file)
@@ -13,6 +13,7 @@
 
 package com.cyanogenmod.eleven;
 
+import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.app.AlarmManager;
@@ -27,6 +28,7 @@ import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.SharedPreferences;
 import android.database.ContentObserver;
 import android.database.Cursor;
@@ -529,6 +531,8 @@ public class MusicPlaybackService extends Service {
      */
     private boolean mShowAlbumArtOnLockscreen;
 
+    private boolean mReadGranted = false;
+
     private PowerManager.WakeLock mHeadsetHookWakeLock;
 
     private ShakeDetector.Listener mShakeDetectorListener=new ShakeDetector.Listener() {
@@ -565,19 +569,21 @@ public class MusicPlaybackService extends Service {
         mServiceInUse = false;
         saveQueue(true);
 
-        if (mIsSupposedToBePlaying || mPausedByTransientLossOfFocus) {
-            // Something is currently playing, or will be playing once
-            // an in-progress action requesting audio focus ends, so don't stop
-            // the service now.
-            return true;
+        if (mReadGranted) {
+            if (mIsSupposedToBePlaying || mPausedByTransientLossOfFocus) {
+                // Something is currently playing, or will be playing once
+                // an in-progress action requesting audio focus ends, so don't stop
+                // the service now.
+                return true;
 
-            // If there is a playlist but playback is paused, then wait a while
-            // before stopping the service, so that pause/resume isn't slow.
-            // Also delay stopping the service if we're transitioning between
-            // tracks.
-        } else if (mPlaylist.size() > 0 || mPlayerHandler.hasMessages(TRACK_ENDED)) {
-            scheduleDelayedShutdown();
-            return true;
+                // If there is a playlist but playback is paused, then wait a while
+                // before stopping the service, so that pause/resume isn't slow.
+                // Also delay stopping the service if we're transitioning between
+                // tracks.
+            } else if (mPlaylist.size() > 0 || mPlayerHandler.hasMessages(TRACK_ENDED)) {
+                scheduleDelayedShutdown();
+                return true;
+            }
         }
         stopSelf(mServiceStartId);
 
@@ -601,6 +607,14 @@ public class MusicPlaybackService extends Service {
         if (D) Log.d(TAG, "Creating service");
         super.onCreate();
 
+        if (checkSelfPermission(permission.READ_EXTERNAL_STORAGE) !=
+                PackageManager.PERMISSION_GRANTED) {
+            stopSelf();
+            return;
+        } else {
+            mReadGranted = true;
+        }
+
         mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 
         // Initialize the favorites and recents databases
@@ -743,6 +757,9 @@ public class MusicPlaybackService extends Service {
     @Override
     public void onDestroy() {
         if (D) Log.d(TAG, "Destroying service");
+        if (!mReadGranted) {
+            return;
+        }
         super.onDestroy();
         // Remove any sound effects
         final Intent audioEffectsIntent = new Intent(
@@ -986,6 +1003,9 @@ public class MusicPlaybackService extends Service {
 
     private void scheduleDelayedShutdown() {
         if (D) Log.v(TAG, "Scheduling shutdown in " + IDLE_DELAY + " ms");
+        if (!mReadGranted) {
+            return;
+        }
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                 SystemClock.elapsedRealtime() + IDLE_DELAY, mShutdownIntent);
         mShutdownScheduled = true;
@@ -1636,7 +1656,7 @@ public class MusicPlaybackService extends Service {
      * @param full True if the queue is full
      */
     private void saveQueue(final boolean full) {
-        if (!mQueueIsSaveable) {
+        if (!mQueueIsSaveable || mPreferences == null) {
             return;
         }
 
index 9dd7576..2e136eb 100644 (file)
  */
 package com.cyanogenmod.eleven.ui.activities;
 
+import android.Manifest;
 import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.provider.MediaStore;
@@ -51,6 +54,8 @@ import com.cyanogenmod.eleven.utils.BitmapWithColors;
 import com.cyanogenmod.eleven.utils.MusicUtils;
 import com.cyanogenmod.eleven.utils.NavUtils;
 
+import java.util.ArrayList;
+
 public class HomeActivity extends SlidingPanelActivity implements
         FragmentManager.OnBackStackChangedListener {
     private static final String TAG = "HomeActivity";
@@ -66,6 +71,9 @@ public class HomeActivity extends SlidingPanelActivity implements
     private static final int NEW_PHOTO = 1;
     public static final int EQUALIZER = 2;
 
+    private static final int PERMISSION_REQUEST_STORAGE = 1;
+    private Bundle mSavedInstanceState;
+
     private String mKey;
     private boolean mLoadedBaseFragment = false;
     private boolean mHasPendingPlaybackRequest = false;
@@ -81,6 +89,14 @@ public class HomeActivity extends SlidingPanelActivity implements
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mSavedInstanceState = savedInstanceState;
+
+        if (!needRequestStoragePermission()) {
+            init();
+        }
+    }
+
+    private void init() {
         // if we've been launched by an intent, parse it
         Intent launchIntent = getIntent();
         boolean intentHandled = false;
@@ -89,7 +105,7 @@ public class HomeActivity extends SlidingPanelActivity implements
         }
 
         // if the intent didn't cause us to load a fragment, load the music browse one
-        if (savedInstanceState == null && !mLoadedBaseFragment) {
+        if (mSavedInstanceState == null && !mLoadedBaseFragment) {
             final MusicBrowserPhoneFragment fragment = new MusicBrowserPhoneFragment();
             if (launchIntent != null) {
                 fragment.setDefaultPageIdx(launchIntent.getIntExtra(EXTRA_BROWSE_PAGE_IDX,
@@ -105,10 +121,11 @@ public class HomeActivity extends SlidingPanelActivity implements
 
         getSupportFragmentManager().addOnBackStackChangedListener(this);
 
+
         // if we are resuming from a saved instance state
-        if (savedInstanceState != null) {
+        if (mSavedInstanceState != null) {
             // track which fragments are loaded and if this is the top level activity
-            mTopLevelActivity = savedInstanceState.getBoolean(STATE_KEY_BASE_FRAGMENT);
+            mTopLevelActivity = mSavedInstanceState.getBoolean(STATE_KEY_BASE_FRAGMENT);
             mLoadedBaseFragment = mTopLevelActivity;
 
             // update the action bar based on the top most fragment
@@ -123,6 +140,8 @@ public class HomeActivity extends SlidingPanelActivity implements
         if (!intentHandled) {
             handlePlaybackIntent(launchIntent);
         }
+
+        mSavedInstanceState = null;
     }
 
     @Override
@@ -465,4 +484,59 @@ public class HomeActivity extends SlidingPanelActivity implements
                     !(topFragment instanceof MusicBrowserPhoneFragment));
         }
     }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String permissions[],
+            int[] grantResults) {
+        switch (requestCode) {
+            case PERMISSION_REQUEST_STORAGE: {
+                if (checkPermissionGrantResults(grantResults)) {
+                    init();
+                } else {
+                    finish();
+                }
+            }
+        }
+    }
+
+    private boolean needRequestStoragePermission() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false;
+
+        boolean needRequest = false;
+        String[] permissions = {
+                Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                Manifest.permission.READ_EXTERNAL_STORAGE
+        };
+        ArrayList<String> permissionList = new ArrayList<String>();
+        for (String permission : permissions) {
+            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
+                permissionList.add(permission);
+                needRequest = true;
+            }
+        }
+
+        if (needRequest) {
+            int count = permissionList.size();
+            if (count > 0) {
+                String[] permissionArray = new String[count];
+                for (int i = 0; i < count; i++) {
+                    permissionArray[i] = permissionList.get(i);
+                }
+
+                requestPermissions(permissionArray, PERMISSION_REQUEST_STORAGE);
+            }
+        }
+
+        return needRequest;
+    }
+
+    private boolean checkPermissionGrantResults(int[] grantResults) {
+        for (int result : grantResults) {
+            if (result != PackageManager.PERMISSION_GRANTED) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 }