在上篇文章 Android Studio 插件开发入门 中实现了在IntelliJ IDEA中点击一个菜单按钮弹出对话框。
本文在上文的基础上介绍如何编写一个IDE插件,实现获取App当前画面的Activity名称,文中有些内容是直接延用上篇文章内容,如有不明白的地方可以查看上一篇文章。
ADB命令
adb shell "dumpsys window | grep mCurrentFocus"
adb 信息
mCurrentFocus=Window{cead29 u0 com.tencent.mm/com.tencent.mm.ui.LauncherUI}
信息内容
首先 build.gradle文件中引入Android插件库并同步。
intellij {
plugins 'android'
}
然后在 plugin.xml 文件中添加Android插件依赖。
<depends>com.intellij.modules.platformdepends>
//依赖Android 插件
<depends>org.jetbrains.androiddepends>
如果不在 plugin.xml 中添加上述代码,运行插件时会出现如下异常
Caused by: java.lang.ClassNotFoundException:
org.jetbrains.android.sdk.AndroidSdkUtils PluginClassLoader
完成前面的工作后,只需要在 AnAction.actionPerformed 方法中执行 adb shell 命令,然后将信息在对话框中显示即可实现想要的功能。
在此先简单介绍下,需要用到的几个类。
class ADBAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val project: Project = e.project ?: error("project is error")
val device: IDevice = getConnectedDevice(project) ?: error("no connected device")
//展示已连接的设备信息
MessageDialog(device.name, device.abis.toString()).show()
}
/**
* 对象获取当前连接的设备
*/
private fun getConnectedDevice(project: Project): IDevice? {
//获取所有以连接的设备
val devices: List<IDevice> =
AndroidSdkUtils.getDebugBridge(project)?.devices?.asList() ?: return null
//如果设备数量大于1 则让用户选择一个设备
if (devices.size > 1) {
val facet = AndroidUtils.getApplicationFacets(project).firstOrNull() ?: return null
//选择设备,并返回值
return DeviceSelectionUtils.chooseRunningDevice(
facet,
TargetDeviceFilter.UsbDeviceFilter(),
DeviceCount.SINGLE
)?.firstOrNull()
} else {
return devices.firstOrNull()
}
}
}
运行程序,查看效果
获取了连接的设备信息,在通过设备的 device.executeShellCommand() 方法执行shell命令即可。
可以看到该方法需要传入一个 IShellOutputReceiver 用于接收 shell 命令的输出日志,通过该类我们可以将输出的信息日志信息解析并展示出来。
自定义 IShellOutputReceiver 。
class ADBMessageReceiver : MultiLineReceiver() {
//记录所有信息
private var messageLines: MutableList<String> = ArrayList()
override fun processNewLines(strings: Array<out String>) {
messageLines.addAll(strings)
}
override fun isCancelled(): Boolean = false
//输出日志接收完成后 回调此方法
override fun done() {
//拼接字符串
val message =
if (messageLines.isEmpty())
"No message"
else
messageLines.joinToString(separator = "")
/**
* message格式:mCurrentFocus=Window{cead29 u0 com.tencent.mm/com.tencent.mm.ui.LauncherUI}
*/
val array = message.split("/")
if (array.size == 2) {
val packageName = array[0].split(" ").last()
val activityName = array[1].replace("}", "")
MessageDialog(packageName, activityName).show()
} else {
Messages.showMessageDialog(message, "adb title", Messages.getInformationIcon())
}
}
}
执行shell命令
override fun actionPerformed(e: AnActionEvent) {
val project: Project = e.project ?: error("project is error")
val device: IDevice = getConnectedDevice(project) ?: error("no connected device")
//执行 shell 命令
val shell = "dumpsys window | grep mCurrentFocus"
device.executeShellCommand(shell,ADBMessageReceiver())
}
功能实现后,修改一下对话框的画面显示,比如 OK/Cancel 按钮,Lable的文本显示,大小等等。
修改自定义的 MessageDialog
class MessageDialog(
private val packageName: String,
private val activityName: String
) : DialogWrapper(true) {
init {
init()
}
override fun createCenterPanel(): JComponent? {
return MyMessageDialog().apply {
textPackageName.text = packageName
textActivityName.text = activityName
}.root
}
//重写创建对话框按钮的方法,只显示一个关闭按钮
override fun createActions(): Array<Action> {
val action = cancelAction.apply { putValue(DEFAULT_ACTION, true) }
return arrayOf(action)
}
}