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

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

 

1: 设置FileProvider

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


            

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

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

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

2: 设置合适的路径

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



    

  • 内部存储路径,与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();
    }

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

你可能感兴趣的:(Android,so库,Fileprovider)