在哪里可以找到有关 Android 的“服务调用”shell 命令的信息?
Posted
技术标签:
【中文标题】在哪里可以找到有关 Android 的“服务调用”shell 命令的信息?【英文标题】:Where to find info on Android's "service call" shell command? 【发布时间】:2013-12-12 04:49:30 【问题描述】:在设备上使用adb shell
或终端模拟器,输入它会清除所有通知(需要su
)
service call notification 1
这将发送一条短信(不需要su
)
service call isms 5 s16 "PhoneNumber" i32 0 i32 0 s16 "BodyText"
在哪里可以了解有关service call
的更多信息?我找到了this question 并感谢答案对一切含义的细分。但是我在哪里可以找到关于 notification 2
可能试图调用的方法的信息?
运行service call
不完整,并打印了这个用法:
Usage: service [-h|-?]
service list
service check SERVICE
service call SERVICE CODE [i32 INT | s16 STR] ...
Options:
i32: Write the integer INT into the send parcel.
s16: Write the UTF-16 string STR into the send parcel.
我运行了service list
,它为我的设备返回了 78 项服务,包括 isms
和 notification
,并且对于大多数服务,将打印似乎是命名空间的内容(com.android.internal.telephony.ISms
用于 isms
和 android.app.INotificationManager
对于notification
)。我如何使用这些信息来了解我可以使用这些服务做什么?
【问题讨论】:
也在android.stackexchange.com/q/57778/1302询问 是的,由我。我不确定哪个社区能够更好地回答我的问题。我认为两个社区都可以从中受益。 【参考方案1】:简而言之
与服务调用命令相关的代码只是函数的参数和顺序 该函数出现在该服务的aidl文件中。这是一个语法
service call <your_service_name> <number at which the function appears in your_service_name.aidl> <type of the argument like i32 or i64> <argument>
详细说明 我遇到了很多问题要了解它,因此我将在剪贴板服务的帮助下分享解决方案。 首先您需要了解您感兴趣的服务 - 为此,您需要通过键入来查找特定 android 系统的所有服务
adb shell service list
这就是你会得到的-
.
.
.
59 ethernet: [android.net.IEthernetManager]
60 wifip2p: [android.net.wifi.p2p.IWifiP2pManager]
61 rttmanager: [android.net.wifi.IRttManager]
62 wifiscanner: [android.net.wifi.IWifiScanner]
63 wifi: [android.net.wifi.IWifiManager]
64 overlay: [android.content.om.IOverlayManager]
65 netpolicy: [android.net.INetworkPolicyManager]
66 netstats: [android.net.INetworkStatsService]
67 network_score: [android.net.INetworkScoreService]
68 textservices: [com.android.internal.textservice.ITextServicesManager]
69 network_management: [android.os.INetworkManagementService]
70 clipboard: [android.content.IClipboard]
71 statusbar: [com.android.internal.statusbar.IStatusBarService]
.
.
.
因为我对剪贴板服务感兴趣,所以它看起来是这样的
70 clipboard: [android.content.IClipboard]
所以从这里我们可以总结出服务名是剪贴板服务,包路径是android.content.IClipboard
那你需要知道IClipboard.aidl所在的完整路径。 要知道您需要在谷歌上搜索 IClipboard.aidl。 您需要在结果中从 android.googlesource.com 网站中查找某些内容,例如我的情况-
https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/core/java/android/content/IClipboard.aidl
所以在 +/android-4.2.2_r1 之后是你的路径所在。让路径为 path_of_clipboard.aidl=
/core/java/android/content/IClipboard.aidl
由于这些服务调用代码依赖于 android 系统,因此您需要知道您的 android 操作系统名称- 就我而言,它是 8.1.0 所以我会去下面的网站,谷歌在那里放代码,然后从页面的左侧选择我的操作系统版本-
https://android.googlesource.com/platform/frameworks/base/
就我而言,它是 android-8.1.0_r50。这里 r50 并不重要。您可以选择任何修订。现在我将点击链接,然后我的网址将如下所示
https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r51
然后在添加 path_of_clipboard.aidl 之后,我的完整 url 会是这样的
https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r51/core/java/android/content/IClipboard.aidl
这里会有很多接口中的方法。就像我的情况
void setPrimaryClip(in ClipData clip, String callingPackage);
ClipData getPrimaryClip(String pkg);
ClipDescription getPrimaryClipDescription(String callingPackage);
boolean hasPrimaryClip(String callingPackage);
void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
String callingPackage);
void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener);
/**
* Returns true if the clipboard contains text; false otherwise.
*/
boolean hasClipboardText(String callingPackage);
因此,第一个方法(即 setPrimaryClip)的代码将是 1,因为它出现在第一位,而最后一个方法(即 hasClipboardText)的代码将是 7,因为它出现在aidl 文件中的第七位。对于其他方法也是如此。 所以如果我想调用第七个方法,我会输入
adb shell service call clipboard 7
您可能已经看到,我没有输入调用包名称,因为它不是必需的。
如果方法需要参数,那么您可以像本例所示那样传递它。让我们假设一个方法,其代码为 8 在剪贴板中,如下所示 -
getDemo(String arg1, int arg2, boolean arg3)
所以我会这样称呼它
adb shell call clipboard 8 s16 "first_argument" i32 12 i32 1
这里 i32 代表 32 位整数,s16 代表字符串。我们甚至可以将布尔值作为整数传递,如示例所示。 在布尔整数中,1 代表真,0 代表假。Source
提示 保持 logcat 处于打开状态(就像在 android studio 中一样)以检查执行该 adb 命令时发生的任何错误。
【讨论】:
“在我的例子中是 android-8.1.0_r50”:你是指单个设备上的 Android 版本,还是 Gradle 配置中的 compileSdkVersion? r50 并不重要,因为它们不会在版本之间的接口文件中引入新功能。我已经编辑过了。 很高兴知道,顺便说一句,答案很好。但是,我的问题是:我们是在寻找已安装的设备 Android OS 版本,还是编译应用程序的版本? (即compileSdkVersion) 我们正在考虑设备上安装的版本,因为与应用关联的版本对我来说没有任何意义。 完美,感谢您的澄清。我不确定发出调用的应用程序的编译版本是否改变了 shell 命令的解释方式。 (即使用 Pie SDK 28 编译的应用程序,在 Oreo 操作系统上运行)【参考方案2】:这是我关于Calling Android services from ADB shell 的帖子。它包括一个小 bash 脚本,我使用该脚本为我的特定设备自动下载正确版本的服务源代码,然后对其进行解析以找出所有方法的事务代码。
【讨论】:
这真的是答案!太糟糕了,我花了 2 年时间才找到你的剧本!众所周知,每个服务调用在很大程度上都依赖于 AOS/API,调用编号越低,越有可能跨 AOS 版本兼容。对于更大的数字,例如service call phone 87 i32 0 i32 1
(将网络设置为仅使用 2G GSM)很可能会在所有其他设备上失败,而不是预期。【参考方案3】:
我在这里的第一个答案,希望对你有用。
为了解释这个小谜语,让我使用 android 4.3.1。 This 链接在您的情况下可能是必不可少的。将 java 代码向下滚动到第 669 行。等待您的 TRANSACTION 块与 com.android.internal.telephony.ISms
服务严格相关,并且可能您的答案是您可以做更多的事情。
在您的情况下,您正在调用 TRANSACTION_sendText。说明在第 673 行,您可以在其中找到
static final int TRANSACTION_sendText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
代码的最后一部分由数字“4”组成。每个 TRANSACTION 编号 + 1 = 正确的编号。这就是为什么service call isms 5
负责sendText
而不是sendMultipartText
。
相同的规则适用于所有服务。
我相信您现在已经了解了如何检查 TRANSACTIONs 以获取通知服务。好开心。
【讨论】:
您链接到的 java 文件不是官方源代码树的一部分。它是从 AIDL 文件生成的 - android.googlesource.com/platform/frameworks/base/+/… 。我发现它也更容易解析 @AlexP 没抓住重点——您需要执行此操作的信息是 in 编译的文件。源 AIDL 文件根本没有事务编号,因为它们是在编译时生成的。 @GlennMaynard,我没有遗漏任何东西。我完全有能力自己计算文本文件中的行数 - 这是 AIDL 编译过程的相关(查找交易编号)部分的全部范围。 更容易计算函数的数量(每页相隔一页——你不计算行,可能有几十行),希望你以同样的方式在心理上编译文件,而不是搜索并在那里看到实际的常数值?抱歉,如果这感觉有点做作。【参考方案4】:使用service call notification 1
等并不安全,因为它可能在您运行它的任何设备上执行完全不同的操作。
您可以改用android-svc。例如。拨打号码(不打电话):
android-svc --adb call 'phone.dial("555-0199")'
它还为您提供有关数据类型的信息。例如
android-svc --adb method-signature 'phone.dial'
将打印:
void dial(String number);
它还可以首先列出给定服务的方法...
此 gif 取自 the repository:
请注意,在最新版本的 Android 中,您发送 SMS 的 isms 调用将不再起作用,因为 isms
服务不再具有 sendText
方法。你现在可能不得不使用sendTextForSubscriber,因为它需要更多的参数,所以更难调用。
另外,直接回答您的问题在哪里可以找到有关 Android 的“服务调用”shell 命令的信息?: Look at the source code.
Usage: service [-h|-?]
service list
service check SERVICE
service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR | null | fd f | nfd n | afd f ] ...
Options:
i32: Write the 32-bit integer N into the send parcel.
s16: Write the UTF-16 string STR into the send parcel.
自 Android 6 起可用:
i64: Write the 64-bit integer N into the send parcel.
f: Write the 32-bit single-precision number N into the send parcel.
d: Write the 64-bit double-precision number N into the send parcel.
自 Android 11 起可用:
null: Write a null binder into the send parcel.
fd: Write a file descriptor for the file f to the send parcel.
nfd: Write file descriptor n to the send parcel.
afd: Write an ashmem file descriptor for a region containing the data from file f to the send parcel.
一直可用的隐藏选项:
intent: Write and Intent int the send parcel. ARGS can be action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]
【讨论】:
以上是关于在哪里可以找到有关 Android 的“服务调用”shell 命令的信息?的主要内容,如果未能解决你的问题,请参考以下文章
在哪里可以找到有关 openssh/sftp-server 协议的文档?
在哪里可以找到有关 Firebase 云消息传递可用声音的文档?