aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-09-06 02:55:05 -0700
committerSteve Kondik <steve@cyngn.com>2016-09-06 02:55:05 -0700
commit578f0a0ed7870b5a8ed28c7c0198a798b389a682 (patch)
tree75750726ea3b9c8d0e9896e99d9013cd081a3d8c
parent0c04e1da60cf8af9e6681f48bf0b4b4b42a57d49 (diff)
downloadandroid_packages_apps_CMFileManager-578f0a0ed7870b5a8ed28c7c0198a798b389a682.tar.gz
android_packages_apps_CMFileManager-578f0a0ed7870b5a8ed28c7c0198a798b389a682.tar.bz2
android_packages_apps_CMFileManager-578f0a0ed7870b5a8ed28c7c0198a798b389a682.zip
cmfm: Use FileProvider for serving files
* On N, apps can no longer share file:// uris to other packages. Apps that wish to do this must use a FileProvider to generate content uris which can then be shared. * This patch only currently handles the external storage case and does not consider arbitrary filesystem paths or root access. This could be implemented in the future, if necessary. The common case of opening a media file is a good start, though. Change-Id: I83aef923dfa26173171a13c0881aeb43337b4e47
-rw-r--r--AndroidManifest.xml10
-rw-r--r--res/xml/provider_paths.xml4
-rwxr-xr-xsrc/com/cyanogenmod/filemanager/activities/NavigationActivity.java6
-rw-r--r--src/com/cyanogenmod/filemanager/activities/PickerActivity.java7
-rw-r--r--src/com/cyanogenmod/filemanager/ui/dialogs/AssociationsDialog.java2
-rwxr-xr-xsrc/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java29
6 files changed, 43 insertions, 15 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7d00f0bc..46602187 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -76,6 +76,16 @@
android:authorities="com.cyanogenmod.filemanager.providers.index"
android:name=".providers.MimeTypeIndexProvider"/>
+ <provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.cyanogenmod.filemanager.providers.file"
+ android:exported="false"
+ android:grantUriPermissions="true">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/provider_paths" />
+ </provider>
+
<service
android:name=".service.MimeTypeIndexService"
android:label="@string/app_name">
diff --git a/res/xml/provider_paths.xml b/res/xml/provider_paths.xml
new file mode 100644
index 00000000..4ff89311
--- /dev/null
+++ b/res/xml/provider_paths.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+ <external-path name="external_files" path="."/>
+</paths>
diff --git a/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java b/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
index e1e4a35f..675a8745 100755
--- a/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
@@ -44,6 +44,7 @@ import android.os.Parcelable;
import android.os.storage.StorageVolume;
import android.provider.Settings;
import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.content.FileProvider;
import android.support.v4.widget.DrawerLayout;
import android.text.TextUtils;
import android.util.Log;
@@ -623,7 +624,10 @@ public class NavigationActivity extends Activity
for (FileSystemObject f : selectedFiles) {
//Beam ignores folders and system files
if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) {
- fileUri.add(Uri.fromFile(new File(f.getFullPath())));
+ fileUri.add(FileProvider.getUriForFile(
+ NavigationActivity.this,
+ "com.cyanogenmod.filemanager.providers.file",
+ new File(f.getFullPath())));
}
}
if (fileUri.size() > 0) {
diff --git a/src/com/cyanogenmod/filemanager/activities/PickerActivity.java b/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
index ba5fa53a..17707a66 100644
--- a/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
+++ b/src/com/cyanogenmod/filemanager/activities/PickerActivity.java
@@ -34,6 +34,7 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.storage.StorageVolume;
+import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -466,7 +467,8 @@ public class PickerActivity extends Activity
if (getIntent().getType() != null) {
intent.setType(getIntent().getType());
}
- intent.setData(Uri.fromFile(src));
+ intent.setData(FileProvider.getUriForFile(this,
+ "com.cyanogenmod.filemanager.providers.file", src));
intent.putExtras(extras);
intent.setComponent(CROP_COMPONENT);
try {
@@ -572,7 +574,8 @@ public class PickerActivity extends Activity
// Try to find the preferred uri scheme
Uri result = MediaHelper.fileToContentUri(context, src);
if (result == null) {
- result = Uri.fromFile(src);
+ result = FileProvider.getUriForFile(context,
+ "com.cyanogenmod.filemanager.providers.file", src);
}
if (Intent.ACTION_PICK.equals(intent.getAction()) && intent.getData() != null) {
diff --git a/src/com/cyanogenmod/filemanager/ui/dialogs/AssociationsDialog.java b/src/com/cyanogenmod/filemanager/ui/dialogs/AssociationsDialog.java
index a90281dd..774b3383 100644
--- a/src/com/cyanogenmod/filemanager/ui/dialogs/AssociationsDialog.java
+++ b/src/com/cyanogenmod/filemanager/ui/dialogs/AssociationsDialog.java
@@ -166,7 +166,7 @@ public class AssociationsDialog implements OnItemClickListener {
public void onClick(DialogInterface dialog, int which) {
ResolveInfo ri = getSelected();
Intent intent =
- IntentsActionPolicy.getIntentFromResolveInfo(
+ IntentsActionPolicy.getIntentFromResolveInfo(mContext,
ri, AssociationsDialog.this.mRequestIntent);
// Open the intent (and remember the action is the check is marked)
diff --git a/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java b/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java
index 67041bb8..3451ebe5 100755
--- a/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java
+++ b/src/com/cyanogenmod/filemanager/ui/policy/IntentsActionPolicy.java
@@ -26,6 +26,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.provider.MediaStore;
+import android.support.v4.content.FileProvider;
import android.util.Log;
import android.widget.Toast;
import com.cyanogenmod.filemanager.R;
@@ -165,6 +166,8 @@ public final class IntentsActionPolicy extends ActionsPolicy {
intent.setData(getUriFromFile(ctx, fso));
}
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
// Resolve the intent
resolveIntent(ctx, intent, choose, onDismissListener);
} catch (Exception e) {
@@ -443,7 +446,8 @@ public final class IntentsActionPolicy extends ActionsPolicy {
* @param request The requested intent
* @return Intent The intent
*/
- public static final Intent getIntentFromResolveInfo(ResolveInfo ri, Intent request) {
+ public static final Intent getIntentFromResolveInfo(Context context,
+ ResolveInfo ri, Intent request) {
Intent intent =
getIntentFromComponentName(
new ComponentName(
@@ -473,7 +477,7 @@ public final class IntentsActionPolicy extends ActionsPolicy {
}
// Grant access to resources if needed
- grantSecureAccessIfNeeded(intent, ri);
+ grantSecureAccessIfNeeded(context, intent, ri);
return intent;
}
@@ -484,7 +488,8 @@ public final class IntentsActionPolicy extends ActionsPolicy {
* @param intent The intent to grant access
* @param ri The resolved info associated with the intent
*/
- public static final void grantSecureAccessIfNeeded(Intent intent, ResolveInfo ri) {
+ public static final void grantSecureAccessIfNeeded(Context context,
+ Intent intent, ResolveInfo ri) {
// If this intent will be serve by the SecureResourceProvider then this uri must
// be granted before we start it, only for external apps. The internal editor
// must receive an file scheme uri
@@ -492,32 +497,33 @@ public final class IntentsActionPolicy extends ActionsPolicy {
String authority = null;
if (uri != null) {
authority = uri.getAuthority();
- grantSecureAccess(intent, authority, ri, uri);
+ grantSecureAccess(context, intent, authority, ri, uri);
} else if (intent.getExtras() != null) {
Object obj = intent.getExtras().get(Intent.EXTRA_STREAM);
if (obj instanceof Uri) {
uri = (Uri) intent.getExtras().get(Intent.EXTRA_STREAM);
authority = uri.getAuthority();
- grantSecureAccess(intent, authority, ri, uri);
+ grantSecureAccess(context, intent, authority, ri, uri);
} else if (obj instanceof ArrayList) {
ArrayList<Uri> uris = (ArrayList<Uri>) intent.getExtras().get(Intent.EXTRA_STREAM);
for (Uri u : uris) {
authority = u.getAuthority();
- grantSecureAccess(intent, authority, ri, u);
+ grantSecureAccess(context, intent, authority, ri, u);
}
}
}
}
- private static final void grantSecureAccess(Intent intent, String authority, ResolveInfo ri,
- Uri uri) {
+ private static final void grantSecureAccess(Context context, Intent intent,
+ String authority, ResolveInfo ri, Uri uri) {
if (authority != null && authority.equals(SecureResourceProvider.AUTHORITY)) {
boolean isInternalEditor = isInternalEditor(ri);
if (isInternalEditor) {
// remove the authorization and change request to file scheme
AuthorizationResource auth = SecureResourceProvider.revertAuthorization(uri);
- intent.setData(Uri.fromFile(new File(auth.mFile.getFullPath())));
-
+ intent.setData(FileProvider.getUriForFile(context,
+ "com.cyanogenmod.filemanager.providers.file",
+ new File(auth.mFile.getFullPath())));
} else {
// Grant access to the package
SecureResourceProvider.grantAuthorizationUri(uri,
@@ -661,7 +667,8 @@ public final class IntentsActionPolicy extends ActionsPolicy {
final File file = new File(fso.getFullPath());
Uri uri = MediaHelper.fileToContentUri(ctx, file);
if (uri == null) {
- uri = Uri.fromFile(file);
+ uri = FileProvider.getUriForFile(ctx,
+ "com.cyanogenmod.filemanager.providers.file", file);
}
return uri;
}