问题
I play around with the Preview M and test my app on it, especially the "saving a file to external storage" part. Before the download/save process starts, i request for
Manifest.permission.WRITE_EXTERNAL_STORAGE
permission as described on the developer page: https://developer.android.com/preview/features/runtime-permissions.html
The dialog occurs as expected:
"Allow <AppName> to access photos, media, and files on your device?" Deny / Allow
If i hit the "deny"-button, the onRequestPermissionsResult-method of the activity is called.
If i press the "allow"-button, the activity is first recreated and afterwards the onRequestPermissionsResult-method is called. I think it's a result of the granted permission.
But the second situation is tricky because i want to trigger a callback that starts the download, but this object is null at this point:
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
getLogger().error("onRequestPermissionsResult ( " + requestCode + ", " + permissions + ", " + grantResults + " )");
switch (requestCode) {
//permission for saving files?
case PermissionCode.WRITE_EXTERNAL_STORAGE: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//HERE IS THE NULL-OBJECT
if (controller != null) {
controller.triggerCallback();
}
}
break;
}
default: {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
So my questions are:
- Can I avoid this recreation?
- If no, how can i redesign my code to solve the problem - i'm totally idealess at the moment
EDIT 1:
I tried to solve the problem with a handler and postDelayed - but i skipped it.
EDIT 2:
I preliminary solved it and show a Toast to user with the request to push the download button again (in case of granted permission). But Google: ARE YOU SERIOUS?
EDIT 3:
No recreation happens with the latest SDK 6.0 (Version 23) - maybe somebody heard my weeping in Mountain View :-)
回答1:
You can always check the download condition immediately after the activity recreates itself in onCreate()
:
static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0;
boolean initiateDownload = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
initiateDownload = savedInstanceState.getBoolean("toDownload");
}
}
@Override
public void onResume() {
super.onResume();
final boolean hasPermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED;
if(initiateDownload && hasPermission) {
// start download here...
} else {
requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE},
MainActivity.MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initiateDownload = true;
} else {
// denied permission...
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("toDownload", initiateDownload);
}
回答2:
Android may destroy and recreate your activity for a number of reasons. The use case of requesting permissions is no exception. You can use your preferred way of saving and restoring UI state. If your state is parcelable you can do it like the example below. Why this is not mentioned in Request App Permissions or Android RuntimePermissions Sample I don't know.
See more in Saving and restoring transient UI state and Saving UI States
public class ExampleActivity extends AppCompatActivity {
private static final String CURRENT_DOWNLOAD_ITEM = "CURRENT_DOWNLOAD_ITEM";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
currentDownloadItem = savedInstanceState.getParcelable(CURRENT_DOWNLOAD_ITEM);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelable(CURRENT_DOWNLOAD_ITEM, currentDownloadItem);
super.onSaveInstanceState(outState);
}
public void downloadItem(Parcelable item) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
currentDownloadItem = item;
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
} else
perfornDownload(item);
}
private Parcelable currentDownloadItem;
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (currentDownloadItem != null) {
perfornDownload(currentDownloadItem);
currentDownloadItem = null;
} else
Toast.makeText(this, "Please select download again now that we have permission to save it", Toast.LENGTH_LONG).show();
} else
Toast.makeText(this, "Download cancelled, as we don\'t have permission to save the downloaded files", Toast.LENGTH_LONG).show();
break;
}
}
private void perfornDownload(Parcelable item) {
// Here we are sure we have the permission
}
}
来源:https://stackoverflow.com/questions/31432534/android-preview-m-activity-recreates-after-permission-grant