Android 通过Fileprovider建立不同应用间分享so库

1 篇文章 0 订阅
1 篇文章 0 订阅

需求:假如有2个apk,一个客户端(client),一个服务端(service),客户端请求服务端so库文件,服务端分享so库给客户端,客户端进行加载,直接撸代码。

 

1: 设置FileProvider

为了给应用程序定义一个FileProvider,需要在Manifest清单文件中定义一个entry,该entry指明了需要使用的创建Content URI的Authority。此外,还需要一个XML文件的文件名,该XML文件指定了我们的应用可以共享的目录路径。

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.package.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_paths" />        
</provider>

manifest中定义的时候有两点需要注意 :

  • android:authorities 字段指定了希望使用的Authority,该Authority针对于FileProvider所生成的content URI。本例中我的应用的包名为com.package.fileprovider对于自己的应用,要在我们的应用程序包名(android:package的值)之后继续追加“fileprovider”来指定Authority。

  • <provider>下的<meta-data>指向了一个XML文件,该文件指定了我们希望共享的目录路径。“android:resource”属性字段是这个文件的路径和名字(无“.xml”后缀)

2: 设置合适的路径

一旦在Manifest清单文件中为自己的应用添加了FileProvider,就需要指定我们希望共享文件的目录路径。为指定该路径,首先要在“res/xml/”下创建文件“filepaths.xml”。在这个文件中,为每一个想要共享目录添加一个XML标签。

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path  path="libs" name="files"/>
</paths>
  • <files-path name="name" path="path" />
    内部存储路径,与Context.getFilesDir()返回的路径一致
  • name代表URI的路径,为了安全起见,隐藏了具体的目录位置 , 具体的目录位置由path字段指定
  • 所有的path指定的都是目录名,包含了旗下的子目录,而不是文件名.无法通过文件名来指定单个文件,也无法通过通配符的形式指定一系列子文件.

客户端请求so库文件

跳转到service端的Activity

        Intent intent = new Intent(Intent.ACTION_MAIN);
        //参数是包名,类全限定名,注意直接用类名不行
        ComponentName cn = new ComponentName("com.package", "com.package.ServiceActivity");
        intent.setComponent(cn);
        startActivityForResult(intent, 5);

服务端分享so库文件

        File file = new File(getFilesDir() + "libs/", "xxx.so");
        Uri uriForFile = getUriForFile(this, file);
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        intent.setDataAndType(uriForFile, getContentResolver().getType(uriForFile));
        intent.setData(uriForFile);
        setResult(2, intent);
        finish();

   public static Uri getUriForFile(Context context, File file) {
        Uri fileUri = null;
        if (Build.VERSION.SDK_INT >= 24) {
            fileUri = getUriForFile24(context, file);
        } else {
            fileUri = Uri.fromFile(file);
        }
        return fileUri;
    }

   public static Uri getUriForFile24(Context context, File file) {
        Uri fileUri = android.support.v4.content.FileProvider.getUriForFile(context,
                context.getPackageName() + ".fileprovider",
                file);
        return fileUri;
    }

客户端处理服务端分享的so库文件

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == 2) {
            Uri serviceUri = data.getData();
            Log.d(TAG, getFilePathForN(serviceUri, this));
            String filePathForN = getFilePathForN(serviceUri, this);
            System.load(filePathForN);

        }
    }


private static String getFilePathForN(Uri uri, Context context) {
        Uri returnUri = uri;
        Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
        /*
         * Get the column indexes of the data in the Cursor,
         *     * move to the first row in the Cursor, get the data,
         *     * and display it.
         * */
        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
        returnCursor.moveToFirst();
        String name = (returnCursor.getString(nameIndex));
        String size = (Long.toString(returnCursor.getLong(sizeIndex)));
        File file = new File(context.getFilesDir(), name);
        try {
            InputStream inputStream = context.getContentResolver().openInputStream(uri);
            FileOutputStream outputStream = new FileOutputStream(file);
            int read = 0;
            int maxBufferSize = 1 * 1024 * 1024;
            int bytesAvailable = inputStream.available();

            //int bufferSize = 1024;
            int bufferSize = Math.min(bytesAvailable, maxBufferSize);

            final byte[] buffers = new byte[bufferSize];
            while ((read = inputStream.read(buffers)) != -1) {
                outputStream.write(buffers, 0, read);
            }
            Log.e("File Size", "Size " + file.length());
            Log.e("File Size", "name " + name);
            inputStream.close();
            outputStream.close();
            Log.e("File Path", "Path " + file.getPath());
            Log.e("File Size", "Size " + file.length());
        } catch (Exception e) {
            Log.e("Exception", e.getMessage());
        }
        return file.getPath();
    }

到此分享完成,客户端加载完成。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个Android使用FileProvider实现多文件jpg分享的示例代码: 1. 在AndroidManifest.xml文件中添加FileProvider的定义: ``` <provider android:name="androidx.core.content.FileProvider" android:authorities="com.example.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> ``` 2. 在res/xml目录下创建file_paths.xml文件,指定要共享的文件的路径: ``` <paths> <external-path name="external_files" path="."/> </paths> ``` 3. 在代码中获取要分享的文件的Uri,并设置Intent的Action和Type: ``` // 获取要分享的文件列表,此处假设为fileList ArrayList<Uri> uriList = new ArrayList<>(); for (File file : fileList) { Uri uri = FileProvider.getUriForFile(context, "com.example.fileprovider", file); uriList.add(uri); } // 创建分享的Intent Intent shareIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); shareIntent.setType("image/jpeg"); shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); ``` 在上述代码中,如果要分享其他类型的文件,可以将Type设置为对应的MIME类型。同时需要注意,在Intent中添加FLAG_GRANT_READ_URI_PERMISSION标志,以便接收方应用可以读取共享的文件。 4. 启动分享的Activity: ``` Intent chooserIntent = Intent.createChooser(shareIntent, "分享图片"); startActivity(chooserIntent); ``` 以上就是一个简单的使用FileProvider实现多文件jpg分享的实现示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值