Android Studio 插件開發實戰——獲取當前Activity名稱

前言

在上篇文章 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命令即可。
executeShellCommand
可以看到該方法需要傳入一個 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())
    }

查看效果
當前Activity

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啓動時間等等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章