自动软件签到Android代码,Android辅助工具,G分助手的实现 - 心悦俱乐部app自动签到、领G分...
最近在使用心悅俱樂部這個APP,里面有個代幣叫G分,可以換游戲道具,但需要每天領取,比較繁瑣。于是索性做一個自動領取G分的輔助,姑且叫它G分助手吧。
1. 查看包名和當前Activity
首先使用adb shell連接上手機。在啟動應用之后,輸入dumpsys activity activities命令查看當前的Activity。
image.png
image.png
可以看到,包名是com.tencent.tgclub,歡迎頁是WelcomeActivity,主頁面是MainActivity。
2. 查看當前應用布局,View的id等
在Android sdk目錄下,有一個tools文件夾。這之中有一個monitor工具,也就是之前的DDMS。連接手機到電腦之后,通過monitor即可看到當前應用界面的布局了。
點擊dump view hierarchy
點擊dump
當前應用布局
當前應用布局.png
通過monitor工具,我們就可以獲取到想要點擊View的id,從而為實現模擬點擊做好準備。
3. AccessibilityService的配置
Accessibility Service的教程網上一搜一大把,很簡單,這里就不贅述了。
AccessibilityService的xml配置文件如下:
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged|typeViewClicked"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds|flagRequestEnhancedWebAccessibility|flagRetrieveInteractiveWindows"
android:canRequestEnhancedWebAccessibility="true"
android:canRetrieveWindowContent="true"
android:canPerformGestures="true"
android:description="@string/app_name"
android:notificationTimeout="10"
android:packageNames="com.tencent.tgclub" />
其中特別要指出的是,flagRequestEnhancedWebAccessibility這一項,是為了操作WebView中的內容的。最坑的地方在于,在api 26中這個flag就被廢棄了,而且我并沒有找到替代方法。也就是說,在Android O以后的手機很可能就不能用這個方式了,而且竟然沒有可以替代的方式!(只能用Android 7及以前的手機暫時茍一下)
image.png
4. 實現代碼
4.1 判斷是否開啟AccessibilityService的權限
/**
* 檢測是否本應用輔助功能開啟
*/
fun isAccessibilitySettingsOn(mContext: Context, clazz: Class): Boolean {
var accessibilityEnabled = 0
val service = mContext.packageName + "/" + clazz.canonicalName
try {
accessibilityEnabled = Settings.Secure.getInt(mContext.applicationContext.contentResolver,
Settings.Secure.ACCESSIBILITY_ENABLED)
} catch (e: Exception) {
e.printStackTrace()
}
val mStringColonSplitter = TextUtils.SimpleStringSplitter(':')
if (accessibilityEnabled == 1) {
val settingValue = Settings.Secure.getString(mContext.applicationContext.contentResolver,
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
if (settingValue != null) {
mStringColonSplitter.setString(settingValue)
while (mStringColonSplitter.hasNext()) {
val accessibilityService = mStringColonSplitter.next()
if (accessibilityService.equals(service, ignoreCase = true)) {
return true
}
}
}
}
return false
}
/**
* 檢查是否開啟輔助功能,沒有開啟就跳轉到設置頁面
*/
private fun checkAccessibilityOn() {
if (!isAccessibilitySettingsOn(this, GPointService::class.java)) {
mDialog = makeDialog(this,
"需要打開輔助功能",
"點擊確定,在設置中找到\"G分助手\",打開輔助功能",
"確定",
DialogInterface.OnClickListener { _, _ -> startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)) },
false)
mDialog!!.show()
}
}
4.2 AccessibilityService的實現
4.2.1 需求分析
擬定功能有三點:
簽到
領取月卡積分
喂貓
那么,我們的輔助功能應該是這樣的:
每日定時打開心悅app -> 檢查今日是否完成以上任務 -(如果沒有)-> 執行任務 -> 檢查是否成功 [ -> 上報]
4.2.2 思路
在AccessibilityService的onAccessibilityEvent回調方法中,可以接收到在xml中指定app的事件。
/**
* 檢測到事件。
*/
override fun onAccessibilityEvent(event: AccessibilityEvent) {
Log.v(TAG, "onAccessibilityEvent: " + AccessibilityEvent.eventTypeToString(event.eventType))
if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
// window狀態改變(切換窗口、顯示隱藏、對話框等)
// doSth...
} else if(event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
// 當前window內容改變
// doSth...
}
}
首先檢查一下今日任務是否已經執行完畢了,如果是的話就什么都不做。因為不能讓輔助妨礙了用戶的正常操作,所以在完成了任務之后就不需要再進行操作了。
按照4.2.1中的流程依次執行任務。
執行完畢之后,將結果保存在本地。
4.2.3 設計
思路上捋清楚了,接下來就是具體是設計了。
1. 任務設計
任務的設計主要分為兩個方面。第一,數據結構;第二,存儲方式。
如何得知當日是否已經執行完畢?執行任務之后如何存儲?
最簡單可行的想法就是使用SharedPreferences來進行記錄,讀取之后保存在AccessibilityService中。
private lateinit var mSharedPreferences: SharedPreferences
override fun onServiceConnected() {
Log.d(TAG, "onServiceConnected: GPointService")
mSharedPreferences = getSharedPreferences(SP_NAME, Context.MODE_PRIVATE)
}
另一方面,由于任務狀態包括了簽到、領取月卡積分、喂貓三項,任務重復性高,如果全都寫在AccessibilityService中,冗余度很高,所以單獨抽象一個Task基類出來。這樣做的好處不僅在于可以減少重復代碼,而且如果以后有新的任務,直接繼承這個父類即可,利于擴展:
uml1
最后,創建一個TaskManager的單例類,統一管理任務,將職責從AccessibilityService中分割出來。
uml3
這里任務的設計暫告一段落了。
2. 任務執行
在任務執行之后,還需要保存任務的完成狀態。對于每日更新的任務來說,每天的任務完成之后,需要將任務標記為已完成,并且在第二天的0點(或其他時候)重新變成未完成。
這個花了我很多時間,主要是比較各種方式的優劣。對于定/延時任務,一般來說有這幾種方法:
Timer
Handler
AlarmManager
鑒于任務間隔時間很長,所以這里采用了AlarmManager作為定時任務的方法。
另外,考慮到不同的任務可能會有不同的執行時間和間隔,那么就沒法統一執行時間了。這個問題其實還是很棘手的,雖然有不同的解決方案,但是我最后也沒有找到一個比較完美的。
最終方案
采用過期時間mExpireTime。對于每個Task來說,執行完畢任務之后,設定一個任務過期時間。任務過期之前為保護期,在保護期內,任務不會再次運行。超過過期時間的,或者沒有設置過期時間的,視為過期任務,則執行。同時將isTaskDone()方法修改為shouldRunTask()方法,使其更符合實際邏輯。
每次AccessibilityService的onAccessibilityEvent回調均會調用TaskManager.checkAndRunTasks()方法來檢查所有任務是否過期,對于未過期的任務則跳過,只執行已過期的任務。在checkAndRunTasks方法中,會調用每個Task的shouldRunTask方法,檢查是否應該運行。
對于TaskManager,簡化了外部接口,使得任務的執行更加便捷且清晰;同時當一個任務執行時,其他任務禁止執行,避免互相干擾。
另外對Task類也進行了優化,刪去了過度設計的部分。
umllast
4.3 最終代碼
雖然因為手里沒有Android 7測試樣機,具體功能的實現沒有辦法繼續寫下去了,不過大體框架已經完成,剩下的內容就是往里面寫各個任務的業務邏輯了,甚至根據需求可以添加其他任務。
Github地址是https://github.com/LittleFogCat/gpointhelper,有興趣的可以自己改著玩。(不過我相信沒有人會堅持看到這里。)
事實上,寫到這里,我已經不想領G分了。
總結
以上是生活随笔為你收集整理的自动软件签到Android代码,Android辅助工具,G分助手的实现 - 心悦俱乐部app自动签到、领G分...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微博超话自动签到 php,微博超话自动签
- 下一篇: Android音视频系列(七):PCM音