前言
在上篇文章 Android Studio 插件開發入門 中實現了在IntelliJ IDEA中點擊一個菜單按鈕彈出對話框。
本文在上文的基礎上介紹如何編寫一個IDE插件,實現獲取App當前畫面的Activity名稱,文中有些內容是直接延用上篇文章內容,如有不明白的地方可以查看上一篇文章。
1. adb 獲取當前Activity名稱
ADB命令
adb shell "dumpsys window | grep mCurrentFocus"
adb 信息
mCurrentFocus=Window{cead29 u0 com.tencent.mm/com.tencent.mm.ui.LauncherUI}
信息內容
- 微信Package Nmae:com.tencent.mm
- 聊天界面Activiy Name:com.tencent.mm.ui.LauncherUI
2. 引入Android插件庫
首先 build.gradle文件中引入Android插件庫並同步。
intellij {
plugins 'android'
}
然後在 plugin.xml 文件中添加Android插件依賴。
<depends>com.intellij.modules.platform</depends>
//依賴Android 插件
<depends>org.jetbrains.android</depends>
如果不在 plugin.xml 中添加上述代碼,運行插件時會出現如下異常
Caused by: java.lang.ClassNotFoundException:
org.jetbrains.android.sdk.AndroidSdkUtils PluginClassLoader
3. 插件開發
完成前面的工作後,只需要在 AnAction.actionPerformed 方法中執行 adb shell 命令,然後將信息在對話框中顯示即可實現想要的功能。
在此先簡單介紹下,需要用到的幾個類。
- com.intellij.openapi.project:表示IntelliJ項目對象
- com.android.ddmlib.IDevice:表示Android 設備對象
- com.android.ddmlib.AndroidDebugBridge:
3.1 獲取已連接的設備
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()
}
}
}
運行程序,查看效果
3.2 執行adb Shell 命令
獲取了連接的設備信息,在通過設備的 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())
}
查看效果
3.3 完善UI效果
功能實現後,修改一下對話框的畫面顯示,比如 OK/Cancel 按鈕,Lable的文本顯示,大小等等。
修改MyMessageDialog.form
修改自定義的 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)
}
}
最終效果
通過上述方式,可以編寫很多很多與 adb 相關的插件,例如通過adb查看app啓動時間等等。