Intent - 意图
# Intent(意图)
Intent(意图) 是一个消息传递对象,您可以使用它从其他应用组件请求操作。尽管 Intent 可以通过多种方式促进组件之间的通信,但其基本用例主要包括以下三个:
- 启动活动(Activity): Activity 表示应用中的一个"屏幕"。例如应用主入口都是一个Activity,应用的功能通常也以Activity的形式独立,例如微信的主界面、朋友圈、聊天窗口都是不同的Activity。通过将 Intent 传递给 startActivity(),您可以启动新的 Activity 实例。Intent 描述了要启动的 Activity,并携带了任何必要的数据。
- 启动服务(Service): Service 是一个不使用用户界面而在后台执行操作的组件。通过将 Intent 传递给 startService(),您可以启动服务执行一次性操作(例如,下载文件)。Intent 描述了要启动的服务,并携带了任何必要的数据。
- 传递广播: 广播是任何应用均可接收的消息。系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播。通过将 Intent 传递给 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),您可以将广播传递给其他应用。
本模块提供了构建Intent的函数(app.intent()), 启动Activity的函数app.startActivity(), 发送广播的函数app.sendBroadcast()。
使用这些方法可以用来方便的调用其他应用。例如直接打开某个QQ号的个人卡片页,打开某个QQ号的聊天窗口等。
```js
var qq = "283054503";
app.startActivity({
action: "android.intent.action.VIEW",
data:"mqq://im/chat?chat_type=wpa&version=1&src_type=web&uin=" + qq,
packageName: "com.tencent.mobileqq",
});
```
>d 飞云补充说明:
在一个循环体内,使用intent打开指定页面,每次操作完成后,都需要返回或杀死应用。
否则会导致应用打开的页面累计,不久会出现卡应用死的问题。
### 实例
[Auto.js Pro使用Intent跳转,传入抖音uid快速打开用户资料页](http://www.feiyunjs.com/352.html)
[Tasker 打开桌面快捷方式(以微信公众号为例)[No Root]](https://www.jianshu.com/p/b3e47e1a74b0)
## app.intent(options)
- options {Object} 选项,包括:
1. action {string} 意图的Action,指意图要完成的动作,是一个字符串常量,比如"android.intent.action.SEND"。当action以"android.intent.action"开头时,可以省略前缀,直接用"SEND"代替。参见Actions。
2. type {string} 意图的MimeType,表示和该意图直接相关的数据的类型,表示比如"text/plain"为纯文本类型。
3. data {string} 意图的Data,表示和该意图直接相关的数据,是一个Uri, 可以是文件路径或者Url等。例如要打开一个文件, action为"android.intent.action.VIEW", data为"file:///sdcard/1.txt"。
4. category {Array} 意图的类别。比较少用。参见Categories。
5. packageName {string} 目标包名
6. className {string} 目标Activity或Service等组件的名称
7. extras {Object} 以键值对构成的这个Intent的Extras(额外信息)。提供该意图的其他信息,例如发送邮件时的邮件标题、邮件正文。参见Extras。
8. flags {Array} intent的标识,字符串数组,例如["activity_new_task", "grant_read_uri_permission"]。参见Flags。[v4.1.0新增]
9. root {Boolea} 是否以root权限启动、发送该intent。使用该参数后,不能使用context.startActivity()等方法,而应该直接使用诸如app.startActivity({...})的方法。[v4.1.0新增]
根据选项,构造一个意图Intent对象。
例如:
```js
//打开应用来查看图片文件
var i = app.intent({
action: "VIEW",
type: "image/png",
data: "file:///sdcard/1.png"
});
context.startActivity(i);
```
需要注意的是,除非应用专门暴露Activity出来,否则在没有root权限的情况下使用intent是无法跳转到特定Activity、应用的特定界面的。例如我们能通过Intent跳转到QQ的分享界面,是因为QQ对外暴露了分享的Activity;而在没有root权限的情况下,我们无法通过intent跳转到QQ的设置界面,因为QQ并没有暴露这个Activity。
但如果有root权限,则在intent的参数加上"root": true即可。例如使用root权限跳转到Auto.js的设置界面为:
```js
app.startActivity({
packageName: "org.autojs.autojs",
className: "org.autojs.autojs.ui.settings.SettingsActivity_",
root: true
});
```
#### 参数获取:
关于intent的参数如何获取的问题,一些intent是意外发现并且在网络中传播的(例如跳转QQ聊天窗口是因为QQ给网页提供了跳转到客服QQ的方法),如果要自己获取活动的intent的参数,可以通过例如"intent记录","隐式启动"等应用拦截内部intent或者查询暴露的intent。
其中拦截内部intent需要XPosed框架,或者可以通过反编译等手段获取参数。
总之,没有简单直接的方法。
更多信息,请百度安卓Intent或参考Android指南: Intent
> 以下非官方内容
```js
// 安卓innet
var intent = new Intent();
//辅助功能
intent.setAction("android.settings.ACCESSIBILITY_SETTINGS");
//intent.setAction("android.settings.ADD_ACCOUNT_SETTINGS");
//添加账户
//intent.setAction("android.settings.AIRPLANE_MODE_SETTINGS");
//系统设置首页
//intent.setAction("android.settings.APN_SETTINGS");
//APN设置
//intent.setAction("android.settings.APPLICATION_SETTINGS");
//应用管理
//intent.setAction("android.settings.BATTERY_SAVER_SETTINGS");
//节电助手
//intent.setAction("android.settings.BLUETOOTH_SETTINGS");
//蓝牙
//intent.setAction("android.settings.CAPTIONING_SETTINGS");
//字幕
//intent.setAction("android.settings.CAST_SETTINGS");
//无线显示
//intent.setAction("android.settings.DATA_ROAMING_SETTINGS");
//移动网络
//intent.setAction("android.settings.DATE_SETTINGS");
//日期和时间设置
//intent.setAction("android.settings.DEVICE_INFO_SETTINGS");
//关于手机
//intent.setAction("android.settings.DISPLAY_SETTINGS");
//显示设置
//intent.setAction("android.settings.DREAM_SETTINGS");
//互动屏保设置
//intent.setAction("android.settings.HARD_KEYBOARD_SETTINGS");
//实体键盘
//intent.setAction("android.settings.HOME_SETTINGS");
//应用权限,默认应用设置,特殊权限
//intent.setAction("android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS");
//忽略电池优化设置
//intent.setAction("android.settings.INPUT_METHOD_SETTINGS");
//可用虚拟键盘设置
//intent.setAction("android.settings.INPUT_METHOD_SUBTYPE_SETTINGS");
//安卓键盘语言设置(AOSP)
//intent.setAction("android.settings.INTERNAL_STORAGE_SETTINGS");
//内存和存储
//intent.setAction("android.settings.LOCALE_SETTINGS");
//语言偏好设置
//intent.setAction("android.settings.LOCATION_SOURCE_SETTINGS");
//定位服务设置
//intent.setAction("android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS");
//所有应用
//intent.setAction("android.settings.MANAGE_APPLICATIONS_SETTINGS");
//应用管理
//intent.setAction("android.settings.MANAGE_DEFAULT_APPS_SETTINGS");
//与ACTION_HOME_SETTINGS相同
//intent.setAction("android.settings.action.MANAGE_OVERLAY_PERMISSION");
//在其他应用上层显示,悬浮窗
//intent.setAction("android.settings.MANAGE_UNKNOWN_APP_SOURCES");
//安装未知应用 安卓8.0
//intent.setAction("android.settings.action.MANAGE_WRITE_SETTINGS");
//可修改系统设置 权限
//intent.setAction("android.settings.MEMORY_CARD_SETTINGS");
//内存与存储
//intent.setAction("android.settings.NETWORK_OPERATOR_SETTINGS");
//可用网络选择
//intent.setAction("android.settings.NFCSHARING_SETTINGS");
//NFC设置
//intent.setAction("android.settings.NFC_SETTINGS");
//网络中的 更多设置
//intent.setAction("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
//通知权限设置
//intent.setAction("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS");
//勿扰权限设置
//intent.setAction("android.settings.ACTION_PRINT_SETTINGS");
//打印服务设置
//intent.setAction("android.settings.PRIVACY_SETTINGS");
//备份和重置
//intent.setAction("android.settings.SECURITY_SETTINGS");
//安全设置
//intent.setAction("android.settings.SHOW_REGULATORY_INFO");
//监管信息
//intent.setAction("android.settings.SOUND_SETTINGS");
//声音设置
//intent.setAction("android.settings.SYNC_SETTINGS");
//添加账户设置
//intent.setAction("android.settings.USAGE_ACCESS_SETTINGS");
//有权查看使用情况的应用
//intent.setAction("android.settings.USER_DICTIONARY_SETTINGS");
//个人词典
//intent.setAction("android.settings.VOICE_INPUT_SETTINGS");
//辅助应用和语音输入
//intent.setAction("android.settings.VPN_SETTINGS");
//VPN设置
//intent.setAction("android.settings.VR_LISTENER_SETTINGS");
//VR助手
//intent.setAction("android.settings.WEBVIEW_SETTINGS");
//选择webview
//intent.setAction("android.settings.WIFI_IP_SETTINGS");
//高级WLAN设置
//intent.setAction("android.settings.WIFI_SETTINGS");
//选择WIFI,连接WIFI
app.startActivity(intent);
```
```js
//取尾部电话号码并拨打电话
var num = "65454354654554513092815842";
var phone = num.substring(num.length - 11);
log(phone);
var intent = new Intent(Intent.ACTION_CALL, app.parseUri("tel:"+phone));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
```
## app.startActivity(options)
- options {Object} 选项
根据选项构造一个Intent,并启动该Activity。
```js
//打开分享
app.startActivity({
action: "SEND",
type: "text/plain",
data: "file:///sdcard/1.txt"
});
```
> 以下非官方例子
打开短信列表:
```js
app.startActivity({
packageName: "com.android.mms",
className: "com.android.mms.ui.MmsTabActivity",
});
```
## app.sendBroadcast(options)
- options {Object} 选项
根据选项构造一个Intent,并发送该广播。
## app.startService(options)
- options {Object} 选项
根据选项构造一个Intent,并启动该服务。
## app.sendBroadcast(name)
[v4.1.0新增]
- name {string} 特定的广播名称,包括:
1. inspect_layout_hierarchy 布局层次分析
2. inspect_layout_bounds 布局范围
发送以上特定名称的广播可以触发Auto.js的布局分析,方便脚本调试。这些广播在Auto.js发送才有效,在打包的脚本上运行将没有任何效果。
```js
app.sendBroadcast("inspect_layout_bounds");
```
## app.intentToShell(options)
[v4.1.0新增]
options {Object} 选项
根据选项构造一个Intent,转换为对应的shell的intent命令的参数。
例如:
```js
shell("am start " + app.intentToShell({
packageName: "org.autojs.autojs",
className: "org.autojs.autojs.ui.settings.SettingsActivity_"
}), true);
```
参见intent参数的规范。
## app.parseUri(uri)
[v4.1.0新增]
- uri {string} 一个代表Uri的字符串,例如"file:///sdcard/1.txt", "https://www.autojs.org"
返回 {Uri} 一个代表Uri的对象,参见android.net.Uri。
解析uri字符串并返回相应的Uri对象。即使Uri格式错误,该函数也会返回一个Uri对象,但之后如果访问该对象的scheme, path等值可能因解析失败而返回null。
需要注意的是,在高版本Android上,由于系统限制直接在Uri暴露文件的绝对路径,因此如果uri字符串是文件file://...,返回的Uri会是诸如content://...的形式。
## app.getUriForFile(path)
[v4.1.0新增]
- path {string} 文件路径,例如"/sdcard/1.txt"
返回 {Uri} 一个指向该文件的Uri的对象,参见android.net.Uri。
从一个文件路径创建一个uri对象。需要注意的是,在高版本Android上,由于系统限制直接在Uri暴露文件的绝对路径,因此返回的Uri会是诸如content://...的形式。
> 以下非官方文档内容
## Android 跨应用间调用: URL Scheme
在Android开发中,不同Activity之间的跳转和切换是很常见的,这使得APP的内容更加丰富,功能更为多样,但是一个应用所能包括的功能毕竟有限,在很多的场景下需要跨应用调用,比如在应用中跳转到微信支付的页面,或者使用第三方账号登陆时跳转到QQ登陆等等。这样的情况下,要跳转的Activity或者Application是第三方开发的,很可能不知道要具体跳转到哪一个Activity中,或者直接跳转并不安全,诸如这些问题都需要在跨应用间调用时被周全地考虑到。
### URL Scheme简介
Android中的自定义的URL Scheme是一种页面内跳转协议,也可以被称为URLRouter,就是通过类似打开网页的方式去通过路由打开一个Activity,而非直接通过显式Intent方式去进行跳转。
# 示例
## 打开应用
```js
var appName = rawInput("请输入应用名称");
launchApp(appName);
```
## 发送意图-文本消息分享
```js
var content = rawInput('请输入要分享的文本');
app.startActivity({
action: "android.intent.action.SEND",
type: "text/*",
extras: {
"android.intent.extra.TEXT": content
},
packageName: "com.tencent.mobileqq",
className: "com.tencent.mobileqq.activity.JumpActivity"
});
```
## 强制停止应用
```js
"auto";
var appName = rawInput("请输入应用名称");
openAppSetting(getPackageName(appName));
while(!click("强制停止"));
```
## 卸载应用
```js
//输入应用名称
var appName = rawInput('请输入要卸载的应用名称');
//获取应用包名
var packageName = getPackageName(appName);
if(!packageName){
toast("应用不存在!");
}else{
//卸载应用
app.uninstall(packageName);
}
```
## 应用工具
```js
var i = dialogs.select("请选择工具", "获取应用包名", "打开应用详情页", "卸载应用");
if(i == -1){
alert("没有选择任何工具!");
}
switch(i){
case 0:
//获取应用包名
appName = rawInput("请输入应用名称", "QQ");
packageName = getPackageName(appName);
toast(packageName);
setClip(packageName);
toast("已复制到剪贴板");
break;
case 1:
//打开应用详情页
appName = rawInput("请输入应用名称", "微信");
openAppSetting(getPackageName(appName));
break;
case 2:
//卸载应用
appName = rawInput("请输入应用名称");
packageName = getPackageName(appName);
if(packageName == ""){
toast("应用不存在");
}else if(confirm("确定卸载应用" + packageName + "吗?")){
app.uninstall(packageName);
}
break;
}
```