观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

版权声明

本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/16741030.html

本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

前言

  在使用应用功能时会经常需要携带参数跳转到某个app、分享一些图片等等其他资源到微信上、接收一些其他应用分享来的图片等等其他资源。此篇博客讲解Scheme协议与分享功能

常见的 MIME 类型

  • 超文本标记语言文本 .html、.htmltext/html

  • 普通文本 .txt: text/plain

  • RTF 文本 .rtf: application/rtf

  • GIF 图形 .gif: image/gif

  • JPEG 图形 .jpeg、.jpg: image/jpeg

  • au 声音文件 .au: audio/basic

  • MIDI 音乐文件 mid、.midi: audio/midi、audio/x-midi

  • RealAudio 音乐文件 .ra、.ram: audio/x-pn-realaudio

  • MPEG 文件 .mpg、.mpeg: video/mpeg

  • AVI 文件 .avi: video/x-msvideo

  • GZIP 文件 .gz: application/x-gzip

  • TAR 文件 .tar: application/x-tar

Scheme协议跳转

普通跳转

创建跳转的Activity

class SchemeActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_scheme)
        getUriData()
    }

    fun getUriData(){
        val uri: Uri? = intent.data
        uri?.let {
            // uri
            Log.e("zh", "uri: ${it.toString()}")
            //scheme部分
            Log.e("zh", "scheme: ${it.scheme}")
            //host部分
            Log.e("zh", "host: ${it.host}")
            //port部分
            Log.e("zh", "host: ${it.port}")
            //访问路劲
            Log.e("zh", "path: ${it.path}")
            //路径片段
            Log.e("zh", "pathSegments: ${it.pathSegments}")
            //参数名称
            Log.e("zh", "getQueryParameterNames: ${it.queryParameterNames}")
            // Query部分
            Log.e("zh", "query: ${uri.query}")
        }
    }
}

打印结果:

  uri: zh://com.example.settings:9000/scheme
  scheme: zh
  host: com.example.settings
  host: 9000
  path: /scheme
  pathSegments: [scheme]
  getQueryParameterNames: []
  query: null

AndroidManifest.xml 上注册

  • scheme 协议名称
  • host 作用域
  • port 端口号
  • path 目标路径
        <activity
            android:name=".ui.SchemeActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="zh"
                    android:host="com.example.settings"
                    android:port="9000"
                    android:path="/scheme"/>
            </intent-filter>
        </activity>

其他app里的跳转代码:

            val uri = Uri.parse("zh://com.example.settings:9000/scheme")
            val intent = Intent(Intent.ACTION_VIEW, uri)
            startActivity(intent)

带参跳转

 其他部分与上面一致

跳转的Activity解析参数:

class SchemeActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_scheme)
        getUriData()
    }

    fun getUriData(){
        val uri: Uri? = intent.data
        uri?.let {
            val list = it.queryParameterNames
            for (item in list){
                val parameter = it.getQueryParameter(item)
                Log.e("zh", "parameter ${item} = ${parameter}")
            }
        }
    }
}

其他app里的跳转代码:

            val uri = Uri.parse("zh://com.example.settings:9000/scheme?id=123456&time=${System.currentTimeMillis()}")
            val intent = Intent(Intent.ACTION_VIEW, uri)
            startActivity(intent)

结果:

           E  parameter id = 123456
           E  parameter time = 1678952157640

判断Scheme协议的有效性

            val uri = Uri.parse("zh://com.example.settings:9000/scheme?id=123456&time=${System.currentTimeMillis()}")
            val packageManager = packageManager
            val intent = Intent(ACTION_VIEW, uri)
            val activities: List<ResolveInfo> = packageManager.queryIntentActivities(intent, 0)
            val isValid = !activities.isEmpty()
            if (isValid) {
                startActivity(intent)
            }

接收分享来的资源

下面这个例子使用一个activity来接收分享来的图片,在AndroidManifest.xml 中添加, 请注意以下几个关键:

  • android:exported="true"  一定是true。否则此activity不会出现在分享弹窗的选项里
  • android.intent.action.SEND  为分享单个文件
  • android.intent.action.SEND_MULTIPLE  为分享多个文件

效果图:

        <activity
            android:name=".ui.gallery.ReceiveShareImageActivity"
            android:exported="true" >
            <intent-filter android:label="将图片添加到收藏">
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>
            <intent-filter android:label="将图片添加到收藏">
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>

mimeType的其他类型

        <data android:mimeType="image/*" />
        <data android:mimeType="video/*" />
        <data android:mimeType="audio/*" />
        <data android:mimeType="text/x-vcard" />
        <data android:mimeType="text/x-vcalendar" />
        <data android:mimeType="text/calendar" />
        <data android:mimeType="text/plain" />
        <data android:mimeType="text/html" />
        <data android:mimeType="text/xml" />
        <data android:mimeType="application/zip" />
        <data android:mimeType="application/vnd.ms-excel" />
        <data android:mimeType="application/msword" />
        <data android:mimeType="application/vnd.ms-powerpoint" />
        <data android:mimeType="application/pdf" />
        <data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
        <data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
        <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
        <data android:mimeType="application/x-hwp" />

在activity的onCreate调用如下代码,获取分享来的图片:

    private fun getShareImage() {
        intent.type?.let { type ->
            /*
                单个图片分享接收
            */
            if (intent.action == Intent.ACTION_SEND && type.startsWith("image/")) {
                val uri: Uri? = intent.getParcelableExtra(Intent.EXTRA_STREAM)
                uri?.let { uri ->
                    val inputStream = contentResolver.openInputStream(uri)
                    val bitmap = BitmapFactory.decodeStream(inputStream)
                    inputStream?.close()
                }
            }
            /*
                多个图片分享接收
            */
            if (intent.action == Intent.ACTION_SEND_MULTIPLE && type.startsWith("image/")) {
                val arrayList: ArrayList<Uri>? =
                    intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)
                arrayList?.let { arrayList ->
                    arrayList.forEach {
                        val inputStream = contentResolver.openInputStream(it)
                        val bitmap = BitmapFactory.decodeStream(inputStream)
                        inputStream?.close()
                    }
                }
            }
        }
    }

发送资源分享到其他应用

在设备中获取支持分享的应用

fun getShareImageApps(): List<ResolveInfo> {
    val intent = Intent(Intent.ACTION_SEND, null)
    intent.addCategory(Intent.CATEGORY_DEFAULT)
    intent.type = "image/*"
    var appList = packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL)
    for (item in appList){
        val packageName = item.activityInfo.packageName
        val activityName = item.activityInfo.name
        val appName = item.loadLabel(packageManager)
        val appIcon = item.loadIcon(packageManager)
        Log.e("zh", "获取可分享的应用 应用名称 = ${appName} 包名 = ${packageName}  分享的目标Activity路径 = ${activityName}  图标 = ${appIcon} ")
    }
    return appList
}

结果

2023-07-06 10:00:41.583  8917-8917  zh      获取可分享的应用 应用名称 = 蓝牙 包名 = com.android.bluetooth  分享的目标Activity路径 = com.android.bluetooth.opp.BluetoothOppLauncherActivity  图标 = android.graphics.drawable.AdaptiveIconDrawable@8b826dc 
2023-07-06 10:00:41.645  8917-8917  zh      获取可分享的应用 应用名称 = 图片转文档(PDF/Excel/Word/PPT) 包名 = cn.wps.moffice_eng  分享的目标Activity路径 = cn.wps.moffice.entrance.pictodoc.PicToDocEntranceActivity  图标 = android.graphics.drawable.BitmapDrawable@72d316b 
2023-07-06 10:00:41.648  8917-8917  zh      获取可分享的应用 应用名称 = 图片工具集(压缩、抠图、消除…) 包名 = cn.wps.moffice_eng  分享的目标Activity路径 = cn.wps.moffice.entrance.pictool.PicToolEntranceActivity  图标 = android.graphics.drawable.BitmapDrawable@d5b961 
2023-07-06 10:00:41.651  8917-8917  zh      获取可分享的应用 应用名称 = 保存到WPS云文档 包名 = cn.wps.moffice_eng  分享的目标Activity路径 = cn.wps.moffice.main.cloud.drive.upload.UploadFileActivity  图标 = android.graphics.drawable.BitmapDrawable@e6b7947 
2023-07-06 10:00:41.742  8917-8917  zh      获取可分享的应用 应用名称 = 钉钉 包名 = com.alibaba.android.rimet  分享的目标Activity路径 = com.alibaba.android.rimet.biz.BokuiActivity  图标 = android.graphics.drawable.AdaptiveIconDrawable@a0974e0 
2023-07-06 10:00:41.768  8917-8917  zh      获取可分享的应用 应用名称 = 今日头条 包名 = com.ss.android.article.news  分享的目标Activity路径 = com.ss.android.publish.send.TTSendPostActivity  图标 = android.graphics.drawable.BitmapDrawable@2e84a3f 
2023-07-06 10:00:41.782  8917-8917  zh      获取可分享的应用 应用名称 = 将图片添加到收藏 包名 = com.zh.calligraphy  分享的目标Activity路径 = com.zh.calligraphy.ui.share.ReceiveShareImageActivity  图标 = android.graphics.drawable.VectorDrawable@c89ea6a 

向目标应用分享图片

    //向目标apk分享图片
    fun shareSingleImage() {
        //分享给微信朋友圈
        val componentName = ComponentName("com.tencent.mm","com.tencent.mm.ui.tools.ShareToTimeLineUI")
        val file = File(FileConstant.SAVE_IMAGE_PATH, "1664357696014.jpg")
        val imageUri = Uri.fromFile(file)
        val shareIntent = Intent()
        shareIntent.setComponent(componentName)
        shareIntent.action = Intent.ACTION_SEND
        shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri)
        shareIntent.type = "image/*"
        startActivity(Intent.createChooser(shareIntent, "分享到"))
    }

单个图片分享

    //分享单张图片
    fun shareSingleImage() {
        //可以通过bitmap分享图片
//        val imageUri: Uri = Uri.parse(MediaStore.Images.Media.insertImage(activity?.contentResolver, bitmap, null, null))
        //通过文件分享图片
        val file = File(FileConstant.SAVE_IMAGE_PATH, "1664357696014.jpg")
        val imageUri = Uri.fromFile(file)
        val shareIntent = Intent()
        shareIntent.action = Intent.ACTION_SEND
        shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri)
        shareIntent.type = "image/*"
        startActivity(Intent.createChooser(shareIntent, "分享到"))
    }

多个图片分享

    //分享多张图片
    fun shareMoreImage() {
        val file = File(FileConstant.SAVE_IMAGE_PATH, "1664357696014.jpg")
        val imageUri = Uri.fromFile(file)
        val shareIntent = Intent()
        shareIntent.action = Intent.ACTION_SEND_MULTIPLE
        val list = ArrayList<Uri>()
        list.add(imageUri)
        shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, list)
        shareIntent.type = "image/*"
        startActivity(Intent.createChooser(shareIntent, "分享到"))
    }

分享文字

    //分享文字
    fun shareText() {
        val shareIntent = Intent()
        shareIntent.action = Intent.ACTION_SEND
        shareIntent.putExtra(Intent.EXTRA_TEXT, "This is my Share text.")
        shareIntent.type = "text/plain"
        //设置分享列表的标题,并且每次都显示分享列表
        startActivity(Intent.createChooser(shareIntent, "分享到"))
    }

使用Uri分享请注意

首先需要在分享之前onCreate里调用,解决资源分享报错问题

    private fun detectFileUriExposure() {
        val builder: StrictMode.VmPolicy.Builder = Builder()
        StrictMode.setVmPolicy(builder.build())
        builder.detectFileUriExposure()
    }

 

End

posted on 2022-09-29 12:16  观心静  阅读(1186)  评论(0)    收藏  举报