Android Q 响应intent.action.VIEW,并复制对应的文件

Android Q 响应intent.action.VIEW,并复制对应的文件

需求:将微信和QQ等第三方应用里的文件直接分享到自己的应用,在自己应用的外部存储目录下复制一份对应文件。

编译版本:29

添加intent-filter

首先在响应的Activity添加意图过滤器,在android:mimeType中添加需要响应的文件类型

<activity android:name=".view.common.ShareFilesActivity">
            <intent-filter android:label="分享"
                tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="text/plain" />
                <data android:mimeType="image/jpeg" />
                <data android:mimeType="image/png" />
                <data android:mimeType="image/bmp" />
                <data android:mimeType="image/tiff" />
                <data android:mimeType="image/gif" />
                <data android:mimeType="image/jpeg" />
                <data android:mimeType="image/x-ms-bmp" />
                <data android:mimeType="image/png" />
                <data android:mimeType="image/x-pcx" />
                <data android:mimeType="image/targa" />
                <data android:mimeType="image/x-photoshop" />

                <data android:mimeType="video/mpeg" />
                <data android:mimeType="audio/mp4"/>
                <data android:mimeType="audio/mp3"/>
                <data android:mimeType="audio/mp3"/>
                <data android:mimeType="video/x-ms-wmv"/>
                <data android:mimeType="video/x-ms-wm"/>
                <data android:mimeType="video/x-ms-wmx"/>

                <data android:mimeType="application/octet-stream" />
                <data android:mimeType="application/pdf" />
                <data android:mimeType="application/msword" />
                <data android:mimeType="application/pdf" />
                <data android:mimeType="application/zip" />
                <data android:mimeType="application/x-xls" />
                <data android:mimeType="application/msword" />
                <data android:mimeType="application/x-ppt"/>
                <data android:mimeType="application/vnd.ms-powerpoint"/>
            </intent-filter>
</activity>

处理Intent

    @Override
    public void initExtras(@Nullable Intent intent) {
        if (intent == null)return;
        String action = intent.getAction();
        if (Intent.ACTION_VIEW.equals(action)){
            if (SCHEME_FILE.equals(intent.getScheme()) || SCHEME_CONTENT.equals(intent.getScheme())) {
                Uri uri = intent.getData();
                copyFileActionView(uri);
            }
        }
    }

解析Uri

android10以后,只需要考虑沙盒里的文件uri和共享文件(匿名uri)、通过文件选择器获取到的uri的转换;其他类型,要么转换不成File,要么拿不到,也就不用再考虑了事实上android10之后,是无法拿到外部文件的绝对路径的,唯一能做的,只是把共享文件复制到沙盒目录下,然后再进行文件操作。沙盒里的文件(file开头),可以直接转成File使用,共享文件(content开头)如果要操作,需要先复制到沙盒目录下。

private static File uriToFileCopy(Uri uri, Context context) throws IOException{
        File file = null;
        if(uri == null) return file;
        //android10以上转换
        if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
            file = new File(uri.getPath());
            InputStream is = new FileInputStream(file);
            File path = FilePathProvider.getPublicDir(context, "enclosure" +
                    "/" + DateTimeUtils.formatDatetime(new Date(),FORMAT_DATE3));
            if (!path.exists()){
                path.mkdir();
            }
            File cache = new File(path.getAbsolutePath(), file.getName());
            FileOutputStream fos = new FileOutputStream(cache);
            copyFileStream(is,fos);
            file = cache;
        } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
            //把文件复制到沙盒目录
            ContentResolver contentResolver = context.getContentResolver();
            String displayName = null;
            //注释掉的方法可以获取到原文件的文件名,但是比较耗时
            Cursor cursor = contentResolver.query(uri, null, null, null, null);
            if (cursor.moveToFirst()) {
                displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
            }

            InputStream is = contentResolver.openInputStream(uri);
            File path = FilePathProvider.getPublicDir(context, "enclosure" +
                    "/" + DateTimeUtils.formatDatetime(new Date(),FORMAT_DATE3));
            if (!path.exists()){
                path.mkdir();
            }
            File cache = new File(path.getAbsolutePath(), displayName);
            FileOutputStream fos = new FileOutputStream(cache);
            copyFileStream(is,fos);
            file = cache;
        }
        return file;
    }

放到异步线程

private void copyFileActionView(Uri path){
        Flowable.just(path)
                .subscribeOn(Schedulers.io())
                .map((Function<Uri, ResponseModel<String>>) s -> {
                    try {
                        File file = uriToFileCopy(s,mView.getContext());
                        if (file == null){
                            return TaskDetailsBiz.obtainResponse(0,mView.getContext().getString(R.string.share_file_fail,"返回为NULL"),null);
                        }else{
                            return TaskDetailsBiz.obtainResponse(1,mView.getContext().getString(R.string.share_file_success),null);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                        return TaskDetailsBiz.obtainResponse(0,mView.getContext().getString(R.string.share_file_fail,e.getMessage()),null);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new ResourceSubscriber<ResponseModel<String>>() {
                    @Override
                    public void onNext(ResponseModel<String> responseModel) {
                        if (responseModel.getStatus()==0){
                            //失败
                        }else {
                            //成功
                        }
                    }

                    @Override
                    public void onError(Throwable t) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
    
public class ResponseModel<T> implements Serializable {
    /**返回状态--失败 */
    public static final int STATUS_FAILED = 0;
    /**返回状态--成功 */
    public static final int STATUS_SUCCESS = 1;
    /**返回状态 0-失败 1-成功 */
    private int resultStatus;
    /**返回消息 */
    private String resultMessage;
    /**返回数据 */
    private T result;
    
    //set and get
}

/**
 * 根据参数构建一个Response
 * @param code 状态码
 * @param message 消息
 * @param t 内容实体
 * @param <T> 内容类型
 * @return response
 */
public static <T> ResponseModel<T> obtainResponse(int code , String message,T t){
    ResponseModel<T> response = new ResponseModel<>();
    response.setMessage(message);
    response.setStatus(code);
    response.setResult(t);
    return response;
}

/**
 * 复制文件流
 * @param inputStream 输入流
 * @param outputStream 输出流
 * @throws IOException IO异常
 */
private static void copyFileStream(InputStream inputStream , OutputStream outputStream) throws  IOException{
    int byteread = 0;
    byte[] buffer = new byte[1024];
    while ( (byteread = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, byteread);
    }
    inputStream.close();
    outputStream.close();
}

以上,就可以在QQ或微信中选择其他应用打开相应文件,并复制到自己的目录进行操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值