Android 中使用intent.putExtra实现Activity之间的参数传递

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
👉点击跳转到网站

1.Bundle简介:

Bundle主要用于传输数据,它保存的数据,是以key-value的形式存储的。
Bundle常用于在Activity间传递数据 ,当bundle传递的是对象或对象数组时,必须实现Serializable或Parcelable接口.。

intent.putExtra(键值对,具体要传递的值)

 @Override
    public void onClick(View v) {
   
   
        Intent intent = new Intent(this,MainActivity2.class)
<think>我们目前的问题是:如何在已有的Android打印代码中修改以实现打印网络图片? 原代码是使用ACTION_SEND的Intent,并设置类型为text/plain,传递了一个URL字符串。这种方式通常用于分享文本,而打印图片需要传递图片数据。 要实现打印网络图片,我们需要做以下步骤: 1. 下载网络图片到本地(因为打印需要文件路径或Uri) 2. 创建一个指向该图片文件的Uri 3. 使用Intent.ACTION_SEND,但是设置类型为图片类型(如image/*),并附加图片的Uri和EXTRA_STREAM 4. 启动Activity 但是,我们的目标打印应用包名为"com.bld.settings.print",我们需要确认它是否支持通过ACTION_SEND和EXTRA_STREAM来打印图片。 另一种更标准的打印图片方法是使用Android的打印框架,但这里我们已经指定了打印应用的包名,所以我们可以尝试使用相同的Intent方式,但传递图片。 修改步骤: 步骤1:下载网络图片并保存到本地文件(可以使用plus.downloader下载) 步骤2:获取文件的本地路径,并转换为Uri(注意:Android Q及以上版本需要使用FileProvider) 步骤3:修改Intent,设置Action为Intent.ACTION_SEND,类型为图片类型(例如"image/png"或"image/*") 步骤4:使用intent.putExtra(Intent.EXTRA_STREAM, uri)添加图片Uri 步骤5:启动Activity 由于我们是运行在uni-app的5+环境,可以使用plus.downloader下载图片,但要注意异步操作。 但是,原代码是同步执行的,我们需要将下载操作改为异步,并在下载成功后启动打印。 由于Android 7.0以上对文件访问有严格限制,我们需要使用FileProvider来共享文件。因此在原生开发中我们通常需要配置FileProvider,但在5+环境中,我们可以使用plus.android.invoke来调用方法生成Uri,或者使用plus.io.convertLocalFileSystemURL将本地路径转换为可访问的URI。 具体修改代码: 由于代码较长,我们分步骤实现: 1. 下载图片 2. 获取下载图片的路径,并转换为合适的Uri 3. 创建Intent并启动 注意:我们需要在manifest.json中配置FileProvider(如果需要),但是在5+环境中,我们可以使用`plus.android.invoke`来获取文件的Uri,也可以使用`plus.io`的相关方法。 但是,为了避免复杂配置,我们可以使用`plus.android.invoke`来调用Uri的parse方法(如果目标打印应用可以访问我们的私有目录),或者使用`FileProvider`(需要额外配置)。 由于我们无法确定目标打印应用是否能直接访问我们的私有目录,建议使用FileProvider共享文件。但是,在5+环境中,默认已经配置了FileProvider,我们可以使用如下方式获取Uri: 使用`plus.android.invoke`调用`android.support.v4.content.FileProvider`(或AndroidX中的类)来获取Uri,但这样比较麻烦。 另一种简单方式:使用`intent`的`setDataAndType`方法,但需要设置权限。不过,我们可以尝试使用`file://`类型的Uri,但Android 7.0以上禁止了file://跨应用访问。因此,我们需要使用FileProvider。 5+环境已经为我们配置了FileProvider,其authority为`${appid}.provider`,其中appid是应用的appid,在manifest.json中配置的。 在5+环境中,我们可以使用`plus.io.getFileInfo`和`plus.io.resolveLocalFileSystemURL`等来获取文件,但如何获取FileProvider的Uri呢? 5+提供了`plus.android.invoke`来调用原生方法,我们可以这样: 步骤一:下载图片并保存到应用的私有目录(如_downloads目录) 步骤二:使用FileProvider获取该文件的Uri 但我们也可以使用5+提供的`plus.android`接口来创建Uri。 参考5+的文档,我们可以使用以下方法: 由于5+环境已经封装了文件共享,我们可以使用`plus.android.io.xxx`?实际上,5+没有直接提供,但我们可以通过反射调用。 这里提供一个相对简单的方法: 1. 使用`plus.downloader`下载图片到应用的`_downloads`目录(这个目录是应用私有目录,但可以通过FileProvider共享) 2. 使用FileProvider获取Uri,需要知道authority,这个authority在manifest.json的"plus"->"distribute"->"google"下有配置,默认为`${appid}.provider`,我们可以从manifest中获取appid,但代码中如何获取?实际上,5+环境提供了`plus.runtime.appid`来获取。 3. 使用反射调用FileProvider的getUriForFile方法。 但是,这个过程相对复杂,而且需要处理的异常较多。 另一种思路:使用`intent.setData`设置Uri,并加上读写权限(FLAG_GRANT_READ_URI_PERMISSION)。 由于时间关系,我们采用FileProvider的方式,并提供完整的代码示例。 具体步骤: 1. 下载图片到本地 2. 构造FileProvider的Uri 3. 创建Intent,设置Action和类型,并添加EXTRA_STREAM 4. 给目标包授予读取Uri的权限 5. 启动Activity 但是在5+环境中,我们可以使用`plus.android.invoke`来调用相关API。 由于代码较为复杂,我们分步骤写: 注意:以下代码需要在异步回调中执行,因为下载是异步的。 我们假设要打印的图片URL为:http://example.com/image.jpg 代码如下: ```javascript // 假设图片URL var imgUrl = 'http://10.20.60.228:8080/image.jpg'; // 下载图片 var downloadTask = plus.downloader.createDownload(imgUrl, { filename: '_downloads/print_image.jpg' // 保存到_downloads目录,这是相对路径,5+会自动转换为应用私有目录下的路径 }, function(d, status) { if (status == 200) { // 下载成功,文件路径为 d.filename(绝对路径) var filePath = d.filename; // 获取宿主上下文 var main = plus.android.runtimeMainActivity(); // 通过反射获取AndroidIntent类 var Intent = plus.android.importClass('android.content.Intent'); // 获取File类 var File = plus.android.importClass('java.io.File'); // 获取FileProvider类(使用support包) try { var FileProvider = plus.android.importClass('android.support.v4.content.FileProvider'); } catch (e) { // 如果android.support.v4没有,则尝试AndroidX try { FileProvider = plus.android.importClass('androidx.core.content.FileProvider'); } catch (e) { console.error("FileProvider not found: " + e.message); return; } } // 创建File对象 var file = new File(filePath); // 获取应用的appid var authority = plus.runtime.appid + '.provider'; // 获取文件的Uri var photoURI = FileProvider.getUriForFile(plus.android.currentActivity(), authority, file); // 创建打印Intent var intent = new Intent(Intent.ACTION_SEND); intent.setPackage("com.bld.settings.print"); // 设置类型为图片 intent.setType("image/*"); // 将图片Uri放入Extra中 intent.putExtra(Intent.EXTRA_STREAM, photoURI); // 授予目标包读取Uri的权限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 设置打印方向(如果目标打印应用支持) intent.putExtra("android.intent.extra.PRINT_ORIENTATION", 'PORTRAIT'); // 设置纸张大小为自定义 intent.putExtra("android.intent.extra.PRINT_PAPER_SIZE", "CUSTOM"); intent.putExtra("android.intent.extra.PRINT_PAPER_WIDTH", 50); // 纸张宽度(单位?可能是毫米,也可能是英寸,需要看目标应用支持) intent.putExtra("android.intent.extra.PRINT_PAPER_HEIGHT", 70); // 纸张高度 // 启动打印Activity main.startActivity(intent); } else { console.log('下载失败:' + status); } }); downloadTask.start(); ``` 注意: 1. 由于FileProvider可能存在于不同的包内,我们尝试导入两个不同的包(support和AndroidX)。如果项目中没有使用这些库,可能会失败。在uni-app项目中,默认可能没有包含这些库,所以需要确保这些库存在。在5+环境中,通常已经包含了support v4包。 2. 纸张大小的单位可能是毫米,也可能是英寸,需要查看目标打印应用的文档。这里按照毫米设置,但目标应用可能要求其他单位,需要调整。 3. 下载的保存路径`_downloads/print_image.jpg`,其中`_downloads`是5+引擎定义的应用私有下载目录,无需权限即可写入。 4. 使用FileProvider时,authority必须和manifest.json中配置的一致。在uni-app中,默认的authority是应用的appid(如HBuilder的appid)加上.provider。我们可以通过`plus.runtime.appid`获取appid。 5. 我们添加了FLAG_GRANT_READ_URI_PERMISSION,这样目标应用就有权限读取这个Uri指向的文件。 另外,需要确保在manifest.json中已经配置了FileProvider。在uni-app中,默认已经配置了,但是如果需要自定义,可以在manifest.json的"app-plus"->"distribute"->"android"下配置。 如果目标打印应用不接受ACTION_SEND的图片,那么可能需要使用其他Intent。这取决于目标打印应用的设计。 如果以上方法不行,我们可能需要使用Android原生的打印框架(PrintManager),但那样需要编写更多代码,并且需要处理打印适配器(PrintDocumentAdapter)等。 因此,我们首先尝试这种方法。 关于回调:因为下载是异步的,所以我们需要在下载完成的回调中启动打印。 另外,如果打印应用支持打印URL指向的图片(即直接传入图片URL),那么我们也可以不下载,但是需要目标打印应用支持从网络下载图片。从原代码来看,它是将URL作为文本传递,可能不支持直接打印网络图片。所以我们这里采用下载后打印本地文件的方式。 以上代码需要测试,特别是在目标设备上测试。 如果遇到FileProvider找不到的问题,可能是因为项目中缺少对应的库。在uni-app中,默认会包含android support库,所以通常没问题。 如果运行时报错:FileProvider找不到,可以尝试在项目的nativeResources目录下配置Android原生的build.gradle,添加依赖。但这是原生插件开发的内容,对于普通5+页面,可能无法添加依赖库。因此,如果支持库不存在,可能需要使用其他方法。 另一种获取Uri的方法:使用`Uri.fromFile`,但这个方法在Android 7.0以上会抛出FileUriExposedException。因此,我们必须使用FileProvider。 所以,我们只能使用FileProvider,并且确保authority配置正确。 在uni-app的manifest.json中,默认配置的authority确实是`${appid}.provider`,我们可以通过HBuilderX打包后的AndroidManifest.xml查看。在代码中,我们通过`plus.runtime.appid`获取appid,然后拼接上'.provider'作为authority。 总结:修改后的代码使用下载图片并共享文件的方式,通过FileProvider生成Uri,然后启动打印应用的图片分享Activity。 最后,请注意,如果目标打印应用没有正确处理ACTION_SEND的图片,可能无法启动打印。因此,我们需要确保目标打印应用支持这种方式。 如果上述方法无效,可能需要目标打印应用提供专门的SDK或者查看其文档。 由于引用中提到了回调的问题(引用[2]),这里我们不需要回调,因为startActivity是直接启动的。 因此,我们按照上述代码修改即可。 下面给出完整代码,并添加必要的注释: </think>要在已有的 Android 打印代码中实现打印网络图片功能,需要对原始代码进行以下修改: ### 修改步骤 1. **下载网络图片到本地** 使用 `plus.downloader` 下载网络图片并保存到本地文件: ```javascript // 下载网络图片 var imgUrl = "http://example.com/image.jpg"; // 替换为实际图片URL var downloadTask = plus.downloader.createDownload( imgUrl, {}, function(download, status) { if(status !== 200) { console.error("下载失败: " + status); return; } startPrint(download.filename); // 下载完成后触发打印 } ); downloadTask.start(); ``` 2. **生成图片文件的 Uri** 使用 FileProvider 生成符合 Android 安全规范的 Uri: ```javascript function getFileUri(filePath) { var FileProvider = plus.android.importClass("android.support.v4.content.FileProvider"); var File = plus.android.importClass("java.io.File"); var context = plus.android.runtimeMainActivity(); // 获取应用的 provider authority (格式通常为 "包名.provider") var authority = plus.runtime.appid + ".provider"; var file = new File(filePath); return FileProvider.getUriForFile(context, authority, file); } ``` 3. **修改打印 Intent** 将文本类型改为图片类型,并添加图片 Uri: ```javascript function startPrint(imagePath) { var main = plus.android.runtimeMainActivity(); var Intent = plus.android.importClass('android.content.Intent'); var intent = new Intent(Intent.ACTION_SEND); intent.setPackage("com.bld.settings.print"); // 设置图片类型 intent.setType("image/*"); // 添加图片 Uri var photoURI = getFileUri(imagePath); intent.putExtra(Intent.EXTRA_STREAM, photoURI); // 添加打印参数 intent.putExtra("android.intent.extra.PRINT_ORIENTATION", 'PORTRAIT'); intent.putExtra("android.intent.extra.PRINT_PAPER_SIZE", "CUSTOM"); intent.putExtra("android.intent.extra.PRINT_PAPER_WIDTH", 50); intent.putExtra("android.intent.extra.PRINT_PAPER_HEIGHT", 70); // 授予临时读取权限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); main.startActivity(intent); } ``` ### 完整示例代码 ```javascript // 1. 下载图片 function downloadImage() { var imgUrl = "http://10.20.60.228:8080/image.jpg"; var downloadTask = plus.downloader.createDownload(imgUrl, {}, function(download, status) { if(status !== 200) { console.error("下载失败: " + status); return; } startPrint(download.filename); } ); downloadTask.start(); } // 2. 获取文件Uri function getFileUri(filePath) { try { var FileProvider = plus.android.importClass("android.support.v4.content.FileProvider"); var File = plus.android.importClass("java.io.File"); var context = plus.android.runtimeMainActivity(); var authority = plus.runtime.appid + ".provider"; var file = new File(filePath); return FileProvider.getUriForFile(context, authority, file); } catch(e) { console.error("Uri生成失败: " + e.message); } } // 3. 启动打印 function startPrint(imagePath) { var main = plus.android.runtimeMainActivity(); var Intent = plus.android.importClass('android.content.Intent'); var intent = new Intent(Intent.ACTION_SEND); intent.setPackage("com.bld.settings.print"); intent.setType("image/*"); var photoURI = getFileUri(imagePath); if(!photoURI) return; intent.putExtra(Intent.EXTRA_STREAM, photoURI); intent.putExtra("android.intent.extra.PRINT_ORIENTATION", 'PORTRAIT'); intent.putExtra("android.intent.extra.PRINT_PAPER_SIZE", "CUSTOM"); intent.putExtra("android.intent.extra.PRINT_PAPER_WIDTH", 50); intent.putExtra("android.intent.extra.PRINT_PAPER_HEIGHT", 70); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); main.startActivity(intent); } // 启动流程 downloadImage(); ``` ### 关键配置 在 `manifest.json` 中添加 FileProvider 配置: ```json { "app-plus": { "distribute": { "android": { "permissions": [ "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>" ], "fileProviders": [{ "name": "FileProvider", "authorities": "${applicationId}.provider", "paths": { "root-path": "", "files-path": "Download/" } }] } } } } ``` ### 注意事项 1. **Android 版本兼容** Android 7.0+ 必须使用 FileProvider 代替 `file://` Uri,否则会触发 `FileUriExposedException`[^1] 2. **权限处理** 需要添加存储权限: ```json "permissions": { "Download": { "description": "下载图片", "permissions": ["READ_EXTERNAL_STORAGE"] } } ``` 3. **路径问题** 下载路径推荐使用 `_downloads/` 目录(应用私有目录),避免权限问题: ```javascript plus.downloader.createDownload(imgUrl, { filename: "_downloads/image.jpg" }, ...); ``` 4. **错误处理** 添加下载失败和 Uri 生成失败的异常处理,避免应用崩溃 > 此实现使用Android 标准的 `ACTION_SEND` 机制,兼容大多数打印应用[^2]。如果目标打印机有特殊要求,可能需要调整 MIME 类型或额外参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

路宇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值