Android 11 强制执行了一些存储规则,链接请参阅:Android 11 中的存储更新
用例:我有 2 个应用程序,应用程序 A 将文件(.txt)写入外部存储,应用程序 B 将从外部存储读取文件,无需用户交互。但在Android 11上读写时抛出异常,提示权限被拒绝。
所以我做了一些研究,发现只有MediaStore API和存储访问框架允许访问其他应用程序创建的文件,链接参考:数据和文件存储概述
但这两种方法都不适合我的用例:
那么,有没有其他方法可以访问 Android 11 上不同应用程序创建的外部存储上的非媒体文件?
尽管我进行了所有研究,但我没有找到解决我的问题的方法。
感谢您的帮助。
更新
我尝试了FileProvider但当我尝试启动活动时,它总是显示错误
E/AndroidRuntime:致命异常:主进程:com.example.testapp,PID:20141 android.content.ActivityNotFoundException:找不到处理 Intent { act=com.example.app2.action.RECEIVE dat=content://com 的活动.example.testapp.fileprovider/myfiles/default_user.txt flg=0x1 } 在 android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2067) 在 android.app.Instrumentation.execStartActivity(Instrumentation.java:1727) 在 android.app .Activity.startActivityForResult(Activity.java:5320)
这就是我从应用程序 1 启动应用程序 2 活动的方式
File filePath = new File(getFilesDir(), "files");
File newFile = new File(filePath, "default_user.txt");
Intent intent = new Intent();
intent.setAction("com.example.app2.action.RECEIVE");
intent.setData(FileProvider.getUriForFile(this, "com.example.testapp.fileprovider", newFile));
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)
应用程序 1 清单
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:requestLegacyExternalStorage="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestApp">
<activity android:name=".StorageActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
</activity>
<service
android:name=".service.TestService"
android:enabled="true"
android:exported="true" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.testapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
Run Code Online (Sandbox Code Playgroud)
应用程序 2 清单
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestApp">
<activity android:name=".ReceiverActivity">
<intent-filter>
<action android:name="com.example.app2.action.RECEIVE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="content"
android:host="com.example.testapp" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Run Code Online (Sandbox Code Playgroud)
您应该使用启动意图直接启动 app2。
try {
File file = new File( .... );
Uri uri = FileProvider.getUriForFile(context, getPackageName() + ".fileprovider", file);
String apkPackage = "com.example.app2";
Intent intent = context.getPackageManager().getLaunchIntentForPackage(apkPackage);
if ( intent==null )
{
Toast.makeText(context, "Sorry, could not get launch intent for: " + apkPackage, Toast.LENGTH_LONG).show();
return;
}
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
context.startActivity(intent);
}
catch ( IllegalArgumentException e)
{
e.printStackTrace();
Toast.makeText(context, "IllegalArgumentException: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
catch ( Exception e)
{
e.printStackTrace();
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
Run Code Online (Sandbox Code Playgroud)
您不需要在 app2 的清单中使用意图过滤器。
接收方可以通过以下方式获取 uri:
Uri uri = getIntent().getData();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7555 次 |
| 最近记录: |