file selector component now supports runtime permission

This commit is contained in:
Mariotaku Lee 2015-10-08 10:55:10 +08:00
parent 826e4bc7de
commit 5073d1d26e
6 changed files with 222 additions and 97 deletions

View File

@ -158,6 +158,7 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
int REQUEST_PICK_ACTIVITY = 18;
int REQUEST_SETTINGS = 19;
int REQUEST_OPEN_DOCUMENT = 20;
int REQUEST_REQUEST_PERMISSIONS = 30;
int TABLE_ID_ACCOUNTS = 1;
int TABLE_ID_STATUSES = 12;

View File

@ -1,15 +1,14 @@
package org.mariotaku.twidere.activity.support;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.fragment.ProgressDialogFragment;
import org.mariotaku.twidere.fragment.support.DataExportImportTypeSelectorDialogFragment;
import org.mariotaku.twidere.fragment.support.FileSelectorDialogFragment;
import org.mariotaku.twidere.util.DataImportExportUtils;
import org.mariotaku.twidere.util.ThemeUtils;
@ -19,10 +18,10 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DataExportActivity extends ThemedFragmentActivity implements FileSelectorDialogFragment.Callback,
DataExportImportTypeSelectorDialogFragment.Callback {
public class DataExportActivity extends ThemedFragmentActivity implements DataExportImportTypeSelectorDialogFragment.Callback {
private ExportSettingsTask mTask;
private Runnable mResumeFragmentsRunnable;
@Override
public int getThemeColor() {
@ -35,7 +34,7 @@ public class DataExportActivity extends ThemedFragmentActivity implements FileSe
}
@Override
public void onCancelled(final DialogFragment df) {
public void onCancelled(DialogFragment df) {
if (!isFinishing()) {
finish();
}
@ -49,17 +48,39 @@ public class DataExportActivity extends ThemedFragmentActivity implements FileSe
}
@Override
public void onFilePicked(final File file) {
if (file == null) {
finish();
return;
protected void onResumeFragments() {
super.onResumeFragments();
if (mResumeFragmentsRunnable != null) {
mResumeFragmentsRunnable.run();
}
final DialogFragment df = new DataExportImportTypeSelectorDialogFragment();
final Bundle args = new Bundle();
args.putString(EXTRA_PATH, file.getAbsolutePath());
args.putString(EXTRA_TITLE, getString(R.string.export_settings_type_dialog_title));
df.setArguments(args);
df.show(getSupportFragmentManager(), "select_export_type");
}
@Override
protected void onActivityResult(int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_PICK_DIRECTORY: {
mResumeFragmentsRunnable = new Runnable() {
@Override
public void run() {
if (resultCode == RESULT_OK) {
final String path = data.getData().getPath();
final DialogFragment df = new DataExportImportTypeSelectorDialogFragment();
final Bundle args = new Bundle();
args.putString(EXTRA_PATH, path);
args.putString(EXTRA_TITLE, getString(R.string.export_settings_type_dialog_title));
df.setArguments(args);
df.show(getSupportFragmentManager(), "select_export_type");
} else {
if (!isFinishing()) {
finish();
}
}
}
};
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
@ -84,14 +105,9 @@ public class DataExportActivity extends ThemedFragmentActivity implements FileSe
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
final File extStorage = Environment.getExternalStorageDirectory();
final String storagePath = extStorage != null ? extStorage.getAbsolutePath() : "/";
final FileSelectorDialogFragment f = new FileSelectorDialogFragment();
final Bundle args = new Bundle();
args.putString(EXTRA_ACTION, INTENT_ACTION_PICK_DIRECTORY);
args.putString(EXTRA_PATH, storagePath);
f.setArguments(args);
f.show(getSupportFragmentManager(), "select_file");
final Intent intent = new Intent(this, FileSelectorActivity.class);
intent.setAction(INTENT_ACTION_PICK_DIRECTORY);
startActivityForResult(intent, REQUEST_PICK_DIRECTORY);
}
}

View File

@ -1,8 +1,8 @@
package org.mariotaku.twidere.activity.support;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
@ -10,18 +10,17 @@ import android.support.v4.app.FragmentManager;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.fragment.ProgressDialogFragment;
import org.mariotaku.twidere.fragment.support.DataExportImportTypeSelectorDialogFragment;
import org.mariotaku.twidere.fragment.support.FileSelectorDialogFragment;
import org.mariotaku.twidere.util.DataImportExportUtils;
import org.mariotaku.twidere.util.ThemeUtils;
import java.io.File;
import java.io.IOException;
public class DataImportActivity extends ThemedFragmentActivity implements FileSelectorDialogFragment.Callback,
DataExportImportTypeSelectorDialogFragment.Callback {
public class DataImportActivity extends ThemedFragmentActivity implements DataExportImportTypeSelectorDialogFragment.Callback {
private ImportSettingsTask mImportSettingsTask;
private OpenImportTypeTask mOpenImportTypeTask;
private Runnable mResumeFragmentsRunnable;
@Override
public int getThemeColor() {
@ -48,15 +47,37 @@ public class DataImportActivity extends ThemedFragmentActivity implements FileSe
}
@Override
public void onFilePicked(final File file) {
if (file == null) {
finish();
return;
protected void onActivityResult(int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_PICK_FILE: {
mResumeFragmentsRunnable = new Runnable() {
@Override
public void run() {
if (resultCode == RESULT_OK) {
final String path = data.getData().getPath();
if (mOpenImportTypeTask == null || mOpenImportTypeTask.getStatus() != AsyncTask.Status.RUNNING) {
mOpenImportTypeTask = new OpenImportTypeTask(DataImportActivity.this, path);
mOpenImportTypeTask.execute();
}
} else {
if (!isFinishing()) {
finish();
}
}
}
};
return;
}
}
final String path = file.getAbsolutePath();
if (mOpenImportTypeTask == null || mOpenImportTypeTask.getStatus() != AsyncTask.Status.RUNNING) {
mOpenImportTypeTask = new OpenImportTypeTask(this, path);
mOpenImportTypeTask.execute();
super.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
if (mResumeFragmentsRunnable != null) {
mResumeFragmentsRunnable.run();
}
}
@ -82,14 +103,9 @@ public class DataImportActivity extends ThemedFragmentActivity implements FileSe
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
final File extStorage = Environment.getExternalStorageDirectory();
final String storagePath = extStorage != null ? extStorage.getAbsolutePath() : "/";
final FileSelectorDialogFragment f = new FileSelectorDialogFragment();
final Bundle args = new Bundle();
args.putString(EXTRA_ACTION, INTENT_ACTION_PICK_FILE);
args.putString(EXTRA_PATH, storagePath);
f.setArguments(args);
f.show(getSupportFragmentManager(), "select_file");
final Intent intent = new Intent(this, FileSelectorActivity.class);
intent.setAction(INTENT_ACTION_PICK_FILE);
startActivityForResult(intent, REQUEST_PICK_FILE);
}
}

View File

@ -19,12 +19,18 @@
package org.mariotaku.twidere.activity.support;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import org.mariotaku.twidere.fragment.support.FileSelectorDialogFragment;
import org.mariotaku.twidere.util.PermissionUtils;
import org.mariotaku.twidere.util.ThemeUtils;
import java.io.File;
@ -33,61 +39,110 @@ import static android.os.Environment.getExternalStorageDirectory;
public class FileSelectorActivity extends BaseSupportDialogActivity implements FileSelectorDialogFragment.Callback {
@Override
public int getThemeResourceId() {
return ThemeUtils.getNoDisplayThemeResource(this);
}
@Override
public void onCancelled(final DialogFragment df) {
if (!isFinishing()) {
finish();
}
}
private Runnable mResumeFragmentsRunnable;
@Override
protected void onStart() {
super.onStart();
setVisible(true);
}
@Override
public int getThemeResourceId() {
return ThemeUtils.getNoDisplayThemeResource(this);
}
@Override
public void onDismissed(final DialogFragment df) {
if (!isFinishing()) {
finish();
}
}
@Override
public void onCancelled(final DialogFragment df) {
if (!isFinishing()) {
finish();
}
}
@Override
public void onFilePicked(final File file) {
final Intent intent = new Intent();
intent.setData(Uri.fromFile(file));
setResult(RESULT_OK, intent);
finish();
}
@Override
protected void onStart() {
super.onStart();
setVisible(true);
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
final Uri data = intent.getData();
File initialDirectory = data != null ? new File(data.getPath()) : getExternalStorageDirectory();
if (initialDirectory == null) {
initialDirectory = new File("/");
}
final String action = intent.getAction();
if (!INTENT_ACTION_PICK_FILE.equals(action) && !INTENT_ACTION_PICK_DIRECTORY.equals(action)) {
finish();
return;
}
@Override
public void onDismissed(final DialogFragment df) {
if (!isFinishing()) {
finish();
}
}
final FileSelectorDialogFragment f = new FileSelectorDialogFragment();
final Bundle args = new Bundle();
args.putString(EXTRA_ACTION, action);
args.putString(EXTRA_PATH, initialDirectory.getAbsolutePath());
args.putStringArray(EXTRA_FILE_EXTENSIONS, intent.getStringArrayExtra(EXTRA_FILE_EXTENSIONS));
f.setArguments(args);
f.show(getSupportFragmentManager(), "select_file");
}
@Override
public void onFilePicked(final File file) {
final Intent intent = new Intent();
intent.setData(Uri.fromFile(file));
setResult(RESULT_OK, intent);
finish();
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
if (mResumeFragmentsRunnable != null) {
mResumeFragmentsRunnable.run();
}
}
@Override
public void onRequestPermissionsResult(final int requestCode, final @NonNull String[] permissions,
final @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_REQUEST_PERMISSIONS) {
mResumeFragmentsRunnable = new Runnable() {
@Override
public void run() {
if (PermissionUtils.getPermission(permissions, grantResults, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
PermissionUtils.getPermission(permissions, grantResults, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
showPickFileDialog();
} else {
finishWithDeniedMessage();
}
}
};
}
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
final String action = intent.getAction();
if (!INTENT_ACTION_PICK_FILE.equals(action) && !INTENT_ACTION_PICK_DIRECTORY.equals(action)) {
finish();
return;
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
showPickFileDialog();
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
final String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
ActivityCompat.requestPermissions(this, permissions, REQUEST_REQUEST_PERMISSIONS);
} else {
finishWithDeniedMessage();
}
}
private void finishWithDeniedMessage() {
if (isFinishing()) return;
finish();
}
private void showPickFileDialog() {
final Intent intent = getIntent();
final Uri data = intent.getData();
final String action = intent.getAction();
File initialDirectory = data != null ? new File(data.getPath()) : getExternalStorageDirectory();
if (initialDirectory == null) {
initialDirectory = new File("/");
}
final FileSelectorDialogFragment f = new FileSelectorDialogFragment();
final Bundle args = new Bundle();
args.putString(EXTRA_ACTION, action);
args.putString(EXTRA_PATH, initialDirectory.getAbsolutePath());
args.putStringArray(EXTRA_FILE_EXTENSIONS, intent.getStringArrayExtra(EXTRA_FILE_EXTENSIONS));
f.setArguments(args);
f.show(getSupportFragmentManager(), "select_file");
}
}

View File

@ -0,0 +1,33 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import org.apache.commons.lang3.ArrayUtils;
/**
* Created by mariotaku on 15/10/8.
*/
public class PermissionUtils {
public static int getPermission(String[] permissions, int[] grantResults, String permission) {
final int idx = ArrayUtils.indexOf(permissions, permission);
if (idx != -1) return grantResults[idx];
return 0;
}
}

View File

@ -321,22 +321,26 @@
<item name="textColorDrawerNameSecondary">?android:textColorSecondaryInverse</item>
</style>
<style name="Theme.Twidere.Dark.NoDisplay" parent="Theme.Twidere.Dark.NoActionBar">
<style name="Theme.Twidere.Dark.NoDisplay" parent="Theme.Twidere.Dark.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<!--<item name="android:backgroundDimEnabled">false</item>-->
<item name="android:windowFrame">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowDisablePreview">true</item>
<item name="android:windowNoDisplay">true</item>
<!--<item name="android:windowNoDisplay">true</item>-->
</style>
<style name="Theme.Twidere.Light.NoDisplay" parent="Theme.Twidere.Light.NoActionBar">
<style name="Theme.Twidere.Light.NoDisplay" parent="Theme.Twidere.Light.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<!--<item name="android:backgroundDimEnabled">false</item>-->
<item name="android:windowFrame">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowDisablePreview">true</item>
<item name="android:windowNoDisplay">true</item>
<!--<item name="android:windowNoDisplay">true</item>-->
</style>
<style name="Theme.Test" parent="Theme.Compat.Base" />