blob: 3933dfb68d636625c9d9da886cdc5a61d5419aae [file] [log] [blame]
weitan1ed64e22016-04-06 10:52:00 +08001/*
2 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright (C) 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package com.android.email.activity;
20
21
22import android.app.Activity;
23import android.content.Context;
24import android.content.Intent;
25import android.content.pm.PackageManager;
26import android.os.Bundle;
27import android.os.Trace;
28import android.widget.Toast;
29
30import com.android.email.R;
31import java.util.ArrayList;
32import java.util.Arrays;
33
34/**
35 * Activity that asks the user for all {@link #getDesiredPermissions} if any of
36 * {@link #getRequiredPermissions} are missing.
37 *
38 * NOTE: As a result of b/22095159, this can behave oddly in the case where the final permission
39 * you are requesting causes an application restart.
40 */
41public abstract class RequestPermissionsActivityBase extends Activity {
42 public static final String PREVIOUS_ACTIVITY_INTENT = "previous_intent";
43 private static final int PERMISSIONS_REQUEST_ALL_PERMISSIONS = 1;
44
45 /**
46 * @return list of permissions that are needed in order for {@link #PREVIOUS_ACTIVITY_INTENT} to
47 * operate. You only need to return a single permission per permission group you care about.
48 */
49 protected abstract String[] getRequiredPermissions();
50
51 /**
52 * @return list of permissions that would be useful for {@link #PREVIOUS_ACTIVITY_INTENT} to
53 * operate. You only need to return a single permission per permission group you care about.
54 */
55 protected abstract String[] getDesiredPermissions();
56
57 private Intent mPreviousActivityIntent;
58
59 @Override
60 protected void onCreate(Bundle savedInstanceState) {
61 super.onCreate(savedInstanceState);
62 mPreviousActivityIntent = (Intent) getIntent().getExtras().get(PREVIOUS_ACTIVITY_INTENT);
63
64 // Only start a requestPermissions() flow when first starting this activity the first time.
65 // The process is likely to be restarted during the permission flow (necessary to enable
66 // permissions) so this is important to track.
67 if (savedInstanceState == null) {
68 requestPermissions();
69 }
70 }
71
72 /**
73 * If any permissions the Contacts app needs are missing, open an Activity
74 * to prompt the user for these permissions. Moreover, finish the current activity.
75 *
76 * This is designed to be called inside {@link android.app.Activity#onCreate}
77 */
78 protected static boolean startPermissionActivity(Activity activity,
79 String[] requiredPermissions, Class<?> newActivityClass) {
80 if (!RequestPermissionsActivity.hasPermissions(activity, requiredPermissions)) {
81 final Intent intent = new Intent(activity, newActivityClass);
82 intent.putExtra(PREVIOUS_ACTIVITY_INTENT, activity.getIntent());
83 activity.startActivity(intent);
84 activity.finish();
85 return true;
86 }
87 return false;
88 }
89
90 @Override
91 public void onRequestPermissionsResult(int requestCode, String permissions[],
92 int[] grantResults) {
93 if (permissions != null && permissions.length > 0
94 && isAllGranted(permissions, grantResults)) {
95 mPreviousActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
96 startActivity(mPreviousActivityIntent);
97 finish();
98 overridePendingTransition(0, 0);
99 } else {
100 Toast.makeText(this, R.string.missing_required_permission, Toast.LENGTH_SHORT).show();
101 finish();
102 }
103 }
104
105 private boolean isAllGranted(String permissions[], int[] grantResult) {
106 for (int i = 0; i < permissions.length; i++) {
107 if (grantResult[i] != PackageManager.PERMISSION_GRANTED
108 && isPermissionRequired(permissions[i])) {
109 return false;
110 }
111 }
112 return true;
113 }
114
115 private boolean isPermissionRequired(String p) {
116 return Arrays.asList(getRequiredPermissions()).contains(p);
117 }
118
119 private void requestPermissions() {
120 Trace.beginSection("requestPermissions");
121 try {
122 // Construct a list of missing permissions
123 final ArrayList<String> unsatisfiedPermissions = new ArrayList<>();
124 for (String permission : getDesiredPermissions()) {
125 if (checkSelfPermission(permission)
126 != PackageManager.PERMISSION_GRANTED) {
127 unsatisfiedPermissions.add(permission);
128 }
129 }
130 if (unsatisfiedPermissions.size() == 0) {
131 throw new RuntimeException("Request permission activity was called even"
132 + " though all permissions are satisfied.");
133 }
134 requestPermissions(
135 unsatisfiedPermissions.toArray(new String[unsatisfiedPermissions.size()]),
136 PERMISSIONS_REQUEST_ALL_PERMISSIONS);
137 } finally {
138 Trace.endSection();
139 }
140 }
141
142 protected static boolean hasPermissions(Context context, String[] permissions) {
143 Trace.beginSection("hasPermission");
144 try {
145 for (String permission : permissions) {
146 if (context.checkSelfPermission(permission)
147 != PackageManager.PERMISSION_GRANTED) {
148 return false;
149 }
150 }
151 return true;
152 } finally {
153 Trace.endSection();
154 }
155 }
156}