通过FileProvider实现两个App的数据交互

由于 Android 系统尤其是高版本的权限限制,不同 App 间的本地存储数据无法做到直接访问,需要借助如 FileProvider 这样的跨进程通信机制实现交互。

AppB 需要访问 AppA 存在自己内部目录下的文件,可如下实现。

AppA 的处理

在 AndroidManifest.xml 文件中,增加如下配置

<application>
    ...
    <provider
        android:authorities="com.packagename.fileprovider"
        android:name="androidx.core.content.FileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>

    <activity android:name=".FileProviderActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="com.packagename.provider.data" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    ...
</application>

其中

anndroid:authorities 是 provider 唯一标识;

android:name 是 FileProvider 类名,需要引入 androidx 库或者 supportV4 库;

android:resource 是路径映射文件地址;

activity 是用来接收 AppB 发来通信请求的接受类;

在 res/xml 目录下添加 provider_paths.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <root-path name="/" path="." />
    <external-path name="external_file" path="mypath" />
    <external-files-path name="external_app_file" path="myfile" />
    <external-cache-path name="external_app_cache" path="macache" />
    <files-path name="inner_app_file" path="." />
    <cache-path name="inner_app_cache" path="." />
</paths>

root-path 是应用存储地址根目录;

其它标签含义可参考官网;

创建接收类 FileProviderActivity

package com.packagename;

// 包名类名确认和 AndroidManifest 一致,否则跨应用调用会找不到
public class FileProviderActivity extends Activity {

    private static final String TAG = "FileProvider";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        ALog.e(TAG, "action:" + intent.getAction());
        //过滤action,这里action和AndroidManifest里配置的activity action一样
        if ("com.packagename.provider.data".equals(intent.getAction())) {
            try {
                //创建要共享的文件
                File logPath = new File(filepath);
                //获取Uri根据要共享的文件,并传入AndroidManifest中定义的authority
                Uri contentUri = FileProvider.getUriForFile(this, "com.packagename.fileprovider", logPath);
                //创建返回Intent对象
                ALog.e(TAG, "uri:" + contentUri);
                Intent resultIntent = new Intent(Intent.ACTION_SENDTO);
                resultIntent.setClipData(ClipData.newRawUri("", contentUri));
                //        requestIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
                //设置读写权限
                resultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                setResult(RESULT_OK, resultIntent);
            } catch (Exception e) {
                ALog.e(TAG, e);
            }
            finish();
        }
    }
}

AppB 的处理

通过如下代码调起 AppA

// AppA 的action
Intent intent = new Intent("com.packagename.provider.data");
ntent.addCategory(Intent.CATEGORY_DEFAULT);
// AppA FileProviderActivity 的包名和类名
intent.setClassName("com.packagename", "com.packagename.FileProviderActivity");
startActivityForResult(intent, 100);

拿到 AppA 的响应后的处理


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == 100) {
            Log.i(TAG, "itemCount:" + intent.getClipData().getItemCount());
            Uri uri = intent.getClipData().getItemAt(0).getUri();
            Log.e(TAG, "uri===" + uri);
            try {
                if (uri != null && !TextUtils.isEmpty(uri.getPath())) {
                    // 拿到了 AppA 的文件路径,可以读写数据
                }
            } catch (Exception e) {
                Log.e(TAG, e);
            }
        }
    }
    super.onActivityResult(requestCode, resultCode, intent);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Matlab App Designer中,可以通过使用句柄对象来实现两个App之间的交互。句柄对象可以跨越不同的函数和App,在两个App之间进行数据共享和传输。具体的实现方式可以参考Matlab官网提供的文档和示例。注意,在进行句柄对象的创建和使用时,需要格外小心,防止内存泄漏等问题的出现。 ### 回答2: 在MATLAB App Designer中,可以通过两个App之间的交互实现数据共享和功能扩展。两个App之间的交互可以通过方法调用、变量传递和事件响应来实现。 首先,可以通过方法调用来实现两个App之间的交互。一个App可以调用另一个App中定义的方法来获取数据或执行特定的功能。例如,一个App可以通过调用另一个App的方法获取该App中处理后的数据,并在自身中进一步进行分析或可视化。 其次,可以通过变量传递来实现两个App之间的数据共享。一个App可以将数据保存在全局变量中,另一个App可以读取该全局变量中的数据并进行处理。这样,两个App就可以共享同一个数据源,并且对该数据进行不同的操作。 另外,还可以通过事件响应来实现两个App之间的交互。一个App可以将某个事件触发的消息发送给另一个App,并根据该消息来执行相应的操作。例如,一个App可以在某个操作完成后发送一个消息给另一个App,触发另一个App中的相应事件,实现两个App之间的数据同步或功能联动。 总之,MATLAB App Designer提供了多种方式来实现两个App之间的交互,包括方法调用、变量传递和事件响应。通过这些交互方式,可以实现数据共享和功能扩展,提高App的灵活性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值