安卓实现分享图片与文本,适配7.0以上文件访问权限问题

引言:
今天看官方文档,分享简单数据,即在app内实现分享文本和图片到其他应用。文本分享着还没有毛病,几行代码就解决了:

        Intent intent=new Intent();
        intent.setAction(Intent.ACTION_SEND);
        /*发送文本时使用*/
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TEXT,MESSAGE);//发送的文本
        Intent share=Intent.createChooser(intent,"MyTitle");
        startActivity(share);

至于详细呢,建议先去看看官方文档:
将简单数据发送到其他应用

然后呢,我看了之后,准备分享一张图片,然后问题就来了:我如何将项目中的图片转成uri呢?
查阅相关资料(百度)后我发现可以先将Bitmap处理为二进制流,然后写入到文件里,最后将文件转成Uri。
然后剩下操作就与上面文本的类似了,类型换成图片,就可以实现分享了。
1.将Bitmap处理为二进制流:

//先转化为二进制流
        ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
        Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.test);
        bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
        byte[] bytes=outputStream.toByteArray();

2.将二进制流写入到文件里:

//再存入到文件中
		final String path=getFilesDir().getCanonicalPath()+"/"+"test.png";
        File file=new File(path);
        FileOutputStream fileOutputStream=new FileOutputStream(file);
        fileOutputStream.write(bytes);
        fileOutputStream.flush();
        fileOutputStream.close();

3.文件转uri:

//再从文件获取Uri
        if(file.exists()){
            //7.0开始,需通过FileProvider共享文件
            if(Build.VERSION.SDK_INT>=24){
                Uri uri= FileProvider.getUriForFile(MainActivity.this,"com.example.mydrawabletest.fileprovider",file);
               // intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.putExtra(Intent.EXTRA_STREAM,uri);
            }else{
                Uri uri=Uri.fromFile(file);
                intent.putExtra(Intent.EXTRA_STREAM,uri);
            }
        }

这也是最坑的点,此时你会发现,若你对7.0以上设备不进行处理,则会得到如下结果:
在这里插入图片描述
大概意思就是不能直接访问文件,那么就需要用到FileProvider了,详细用法参照官方文档:
设置文件分享
好了,那我先给出我的配置:
清单文件:

<provider
            android:authorities="com.example.mydrawabletest.fileprovider"
            android:name="androidx.core.content.FileProvider"
            android:grantUriPermissions="true"
            >
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths"/>
        </provider>

res/xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path
        name="files_path"
        path="/"/>
</paths>

paths标签对里面子元素可以是:
external-path,代表外部存储目录
cache-path,app私有存储缓存目录
files-path,app私有存储文件目录
看下面这张图可能更好理解,由于我最初定义的保存图片的目录就是下面的files下,因此我选择了files-path,这便是最底层目录,所以我path属性的值就只有一个‘/’,其实可以什么都不要。
在这里插入图片描述
温馨提示:
由于Uri解析和文件写入都涉及到了文件访问,权限一定要给上对吧,为了兼容高版本要动态申请哦,给出完整实例代码吧(与分享功能实现无关的部分请都忽略,带来不便,请谅解):

package com.example.mydrawabletest;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final String MESSAGE="www.baidu.com";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main)
        judgePermission();
    }

    private void judgePermission() {
        /**
         * 先检查权限是否打开,打开了就可以直接访问,未打开则先申请一波权限
         */
        if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!=
        PackageManager.PERMISSION_GRANTED||(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED)){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                makeAnExtraRequest();
            }
        }else{
            shareMessage();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    private void makeAnExtraRequest() {
        int code = 100;
        String[] permissions = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };

        for (String string : permissions) {
            if (this.checkSelfPermission(string) != PackageManager.PERMISSION_GRANTED) {
                this.requestPermissions(permissions, code);
                code++;
                return;
            }
        }
    }

    private void shareMessage() {
        Intent intent=new Intent();
        intent.setAction(Intent.ACTION_SEND);
        /*
        发送文本时使用
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TEXT,MESSAGE);
        Intent share=Intent.createChooser(intent,"MyTitle");
        startActivity(share);
         */

        /*
        发送图片时使用
         */
        //getUriOne(intent);
        try {
            getUriTwo(intent);
        } catch (IOException e) {
            e.printStackTrace();
        }
        intent.setType("image/png");
        Intent share=Intent.createChooser(intent,"MyTitle");
        startActivity(share);
    }

    private void getUriTwo(Intent intent) throws IOException {
        final String path=getFilesDir().getCanonicalPath()+"/"+"test.png";
        //先转化为二进制流
        ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
        Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.test);
        bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
        byte[] bytes=outputStream.toByteArray();

        //再存入到文件中
        File file=new File(path);
        FileOutputStream fileOutputStream=new FileOutputStream(file);
        fileOutputStream.write(bytes);
        fileOutputStream.flush();
        fileOutputStream.close();


        //再从文件获取Uri
        if(file.exists()){
            //7.0开始,需通过FileProvider共享文件
            if(Build.VERSION.SDK_INT>=24){
                Uri uri= FileProvider.getUriForFile(MainActivity.this,"com.example.mydrawabletest.fileprovider",file);
               // intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.putExtra(Intent.EXTRA_STREAM,uri);
            }else{
                Uri uri=Uri.fromFile(file);
                intent.putExtra(Intent.EXTRA_STREAM,uri);
            }
        }

    }

    private void getUriOne(Intent intent) {
        /*
        此方法虽然可行,但是MediaStore.Images.Media.insertImage这个方法已经废弃,不推荐
         */
        Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.test);
        Uri uri=Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(),bitmap,null,null));
        intent.putExtra(Intent.EXTRA_STREAM,uri);
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        shareMessage();
    }
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
安卓11引入了新的存储访问框架,对于应用程序的文件上传权限进行了一些限制。为了解决安卓11上的应用上传文件权限问题,可以采取以下方法: 1. 更新应用:确保您的应用程序是最新版本,以便支持安卓11的新存储访问框架。更新应用程序可能包括应用程序的权限和存储访问方式的更新。 2. 请求文件权限:确保您的应用程序在使用文件上传功能之前请求必要的文件权限。在安卓11中,您可能需要请求"MANAGE_EXTERNAL_STORAGE"权限访问外部存储。 3. 新的存储访问方式:当访问外部存储时,应使用新的存储访问API。使用新的API,您可以使用MediaStore类实现文件上传,例如使用MediaStore.createDocument()创建并导出文件。 4. 使用特定目录:在安卓11中,您的应用程序可能无法直接访问外部存储的根目录。为了解决这个问题,您可以将文件保存在应用程序专属目录或使用getExternalFilesDir()方法获取应用程序私有目录的访问权限。 5. 与用户共享存储:如果您的应用程序需要与其他应用程序共享文件,则可以使用"getFilesDir()"获取应用程序私有目录,然后使用FileProvider类来生成可与其他应用程序共享的文件URI。 总之,为了解决安卓11上的应用上传文件权限问题,您需要更新应用程序、请求必要的权限新的存储访问方式,以及考虑使用特定目录和共享存储功能。这些方法可以帮助您的应用程序在安卓11上成功上传文件

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tran_sient

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值