blob: 751c12f3e215cb0985d26958e2813064d83b49dd [file] [log] [blame]
dazhanaa938df2016-02-23 18:00:55 +08001/*
2 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30package com.android.calendar;
31
32import android.app.Activity;
33import android.content.Context;
34import android.content.Intent;
35import android.content.pm.PackageManager;
36import android.os.Bundle;
37import android.os.Trace;
38import android.widget.Toast;
39
40import java.util.ArrayList;
41import java.util.Arrays;
42
43/**
44 * Activity that asks the user for all {@link #getDesiredPermissions} if any of
45 * {@link #getRequiredPermissions} are missing.
46 *
47 * NOTE: As a result of b/22095159, this can behave oddly in the case where the
48 * final permission you are requesting causes an application restart.
49 */
50public abstract class RequestPermissionsActivityBase extends Activity {
51 public static final String PREVIOUS_ACTIVITY_INTENT = "previous_intent";
52 private static final int PERMISSIONS_REQUEST_ALL_PERMISSIONS = 1;
53
54 /**
55 * @return list of permissions that are needed in order for
56 * {@link #PREVIOUS_ACTIVITY_INTENT} to operate. You only need to
57 * return a single permission per permission group you care about.
58 */
59 protected abstract String[] getRequiredPermissions();
60
61 /**
62 * @return list of permissions that would be useful for
63 * {@link #PREVIOUS_ACTIVITY_INTENT} to operate. You only need to
64 * return a single permission per permission group you care about.
65 */
66 protected abstract String[] getDesiredPermissions();
67
68 private Intent mPreviousActivityIntent;
69
70 @Override
71 protected void onCreate(Bundle savedInstanceState) {
72 super.onCreate(savedInstanceState);
73 mPreviousActivityIntent = (Intent) getIntent().getExtras().get(
74 PREVIOUS_ACTIVITY_INTENT);
75
76 if (savedInstanceState == null) {
77 requestPermissions();
78 }
79 }
80
81 /**
82 * If any permissions the canlendar app needs are missing, open an Activity
83 * to prompt the user for these permissions. Moreover, finish the current
84 * activity.
85 *
86 * This is designed to be called inside
87 * {@link android.app.Activity#onCreate}
88 */
89 protected static boolean startPermissionActivity(Activity activity,
90 String[] requiredPermissions, Class<?> newActivityClass) {
91 if (!RequestPermissionsActivity.hasPermissions(activity,
92 requiredPermissions)) {
93 final Intent intent = new Intent(activity, newActivityClass);
94 intent.putExtra(PREVIOUS_ACTIVITY_INTENT, activity.getIntent());
95 activity.startActivity(intent);
96 activity.finish();
97 return true;
98 }
99 return false;
100 }
101
102 @Override
103 public void onRequestPermissionsResult(int requestCode,
104 String permissions[], int[] grantResults) {
105 if (permissions != null && permissions.length > 0
106 && isAllGranted(permissions, grantResults)) {
107 mPreviousActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
108 startActivity(mPreviousActivityIntent);
109 finish();
110 overridePendingTransition(0, 0);
111 } else {
112 Toast.makeText(this, R.string.on_permission_read_calendar, Toast.LENGTH_SHORT).show();
113 finish();
114 }
115 }
116
117 private boolean isAllGranted(String permissions[], int[] grantResult) {
118 for (int i = 0; i < permissions.length; i++) {
119 if (grantResult[i] != PackageManager.PERMISSION_GRANTED
120 && isPermissionRequired(permissions[i])) {
121 return false;
122 }
123 }
124 return true;
125 }
126
127 private boolean isPermissionRequired(String p) {
128 return Arrays.asList(getRequiredPermissions()).contains(p);
129 }
130
131 private void requestPermissions() {
132 Trace.beginSection("requestPermissions");
133 try {
134 // Construct a list of missing permissions
135 final ArrayList<String> unsatisfiedPermissions = new ArrayList<>();
136 for (String permission : getDesiredPermissions()) {
137 if (checkSelfPermission(permission)
138 != PackageManager.PERMISSION_GRANTED) {
139 unsatisfiedPermissions.add(permission);
140 }
141 }
142 if (unsatisfiedPermissions.size() == 0) {
143 throw new RuntimeException("Request permission activity was called even"
144 + " though all permissions are satisfied.");
145 }
146 requestPermissions(
147 unsatisfiedPermissions.toArray(new String[unsatisfiedPermissions.size()]),
148 PERMISSIONS_REQUEST_ALL_PERMISSIONS);
149 } finally {
150 Trace.endSection();
151 }
152 }
153
154 protected static boolean hasPermissions(Context context,
155 String[] permissions) {
156 Trace.beginSection("hasPermission");
157 try {
158 for (String permission : permissions) {
159 if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
160 return false;
161 }
162 }
163 return true;
164 } finally {
165 Trace.endSection();
166 }
167 }
168}