基本知識

本章では、Androidオートメーションに関する基本知識を紹介します。本章の説明は必ず最後までお読みください。以降の章では繰り返し説明しません。Androidオートメーションと通常のWebオートメーションには大きな違いがありますが、多くの共通点もあります。通常のWebオートメーションでは、F12開発者ツールを使って簡単にWebページのレイアウトや要素IDなどの情報を確認し、XPATHを介して要素を取得し、クリックや待機などの操作を行います。もちろん、Androidでも同様のロジックであり、「セレクター」と呼ばれるものを使って要素を選択し、クリックや判断などの操作を行うことができますので、入門が難しいと心配する必要はありません。

モバイルとWebオートメーションの共通点と相違点

モバイルのオートメーションとWebの間には多くの共通点がありますが、もちろん多くの違いもあります。seleniumを例にとると、通常、seleniumを使ってWebページを制御するには、ブラウザ、webdriver、seleniumの3つが必要です。もちろん、モバイルも同様で、モバイルのスマートフォンがブラウザに相当し、FIRERPAがwebdriverに相当し、FIRERPAのPythonライブラリであるlamdaがseleniumに相当します。そして、それらの目標は同じで、ユーザー操作をシミュレートし、テスト、データ収集、またはタスクの自動実行を実現することです。また、どちらもスクリプト駆動であり、要素の位置特定、クリック、スクリーンショット、判断などの操作を行います。こう見ると、実はかなり似ています。

しかし、それらは異なります。まず、モバイルのオートメーションにはスマートフォンとコンピュータが必要ですが、Webオートメーションは自分のコンピュータ上で行うことができます。また、使用する技術も異なります。Webでは、Selenium、Puppeteer、Playwrightなどのツールが一般的です。モバイルでは、通常、FIRERPA、AutoJS、Appium、uiautomatorなどが使用されます。

Webでは、一般的な位置特定方法は主にHTML DOM構造に基づくxpathやcsspathであり、要素の階層は比較的直感的です。一方、モバイルでは、一般的な位置特定方法はセレクターですが、AndroidアプリのUIもXMLレイアウトを使用しているため、XMLを介してxpathで選択することもできます。通常、Webオートメーションでは互換性の問題をあまり考慮する必要がなく、ほとんどの場合、ブラウザや起動時の解像度を固定することで、デバイスに起因するほとんどの互換性の問題を回避できます。しかし、Androidでは、さまざまなブランドやモデルのデバイスが異なり、画面サイズやシステムバージョンなどがオートメーションコードの互換性に影響を与える可能性があります。しかし、恐れる必要はありません。影響はありますが、それほど大きくはありません。

各種オートメーションツールの違い

前述の通り、私たちが例に挙げたいくつかの一般的なAndroidオートメーションツール間にも多くの違いがあります。まず私たちの立場を明確にしておきますが、FIRERPAはすべてのオートメーションツールの中で最も安定しており、機能が最も完全で、最も強力で、プロジェクト化管理と応用に最も適しています。

注釈

私たちの立場は偏見ではなく、6年間にわたる絶え間ない探求と最適化の末に形成されたものです。あなたが歩んできた道、踏んできた落とし穴は、私たちもほとんど経験済みです。

AutoJS

よく使われるAutoJSやその関連派生製品は、自己制御型に属し、デバイスにAPKをインストールし、jsでスクリプトを記述して操作する必要があります。通常、AutoJSはオートメーションレベルの操作しかできず、初心者や趣味での使用に適しており、入門のハードルが低いという利点があります。しかし、その設計自体が大規模なスクリプトの制御、管理、更新には適していません。非中央集権的で、管理されていない状態です。正確な大規模制御はできません。

Appium

テスト担当者がよく使用するAppiumは、C/Sアーキテクチャに属し、AutoJSよりもクラスター制御に適していますが、明らかな欠点があります。AndroidだけでなくIOSもサポートするなど、ほとんどのシステムのオートメーションに適用できるため、サイズが大きく肥大化しており、大規模なデプロイには非常に不向きです。

u2

最後にuiautomator2ですが、これもC/Sアーキテクチャに属し、Appiumに比べてより精密で、十分にスリム化されており、余分なものが少なく、機能もちょうど良いです。しかし、私たちがなぜそれを捨てたかというと、主な理由はマルチデバイス環境下で安定しないことです。次に、自動インストール関連のロジックは初心者には適していますが、プロフェッショナルなクラスター制御にとっては、余分で制御しにくく、メンテナンスもされていません。

もちろん、これらはすべて通常の利用には非常に適しています。しかし、私たちの進む道は少し特殊です。なぜなら、ビジネスでは、通常、オートメーションだけを行うことはありえないからです。例えば、あるアプリをテストし、リクエストとレスポンス、リクエスト時間などを記録する必要があるタスクがあるとします。どうしますか?あなたの解決策には、多くの追加の手動操作が含まれているか、あるいは非常に不安定または互換性に問題があるかのどちらかだと思います。しかし、FIRERPAの世界では、すべての操作をコードで行うことができます。あなたが触れるのはコードだけであり、安定性と互換性はFIRERPAに任せることができます。実際、私たちはこれらと比較すべきではありません。なぜなら、機能面でFIRERPAは上記のすべてのソリューションの上位集合であり、私たちが踏んできたすべての落とし穴と歩んできた道を含んでいるからです。

オートメーションの基本フロー

通常、あなたは解決策を事前に調査する必要があります。通常のオートメーションのみを行うのか、それともオートメーションと同時にアプリケーションの実行データを取得する必要があるのか。通常、データを取得するには2つの方法があります。1つは中間者(Man-in-the-Middle)を介してHTTP/s通信を傍受する方法、もう1つはHookを介してデータを傍受する方法です。中間者方式は比較的簡単で通常の使用に適していますが、一部のアプリケーションでは機能しない場合があります。Hook方式は多くのリバースエンジニアリングの知識が必要で、初心者には難しく、特殊な状況での使用に適しています。

中間者による取得

中間者方式は比較的簡単です。ドキュメントで中間者証明書のインストール、プロキシの設定に関する内容を見つけ、mitmproxyと組み合わせるだけで実現できます。もし全くわからない場合は、私たちの公式startmitm.pyスクリプトを参考にしてください。そこにはすべてのロジックが記述されており、いつでもコピーまたは再利用できます。

Hookによる取得

Hook方式では、初級以上のリバースエンジニアリング関連の能力が必要です。これまでに聞いたことがない場合は、現時点ではこの方法を考慮する必要はありません。総じて言えば、Hook方式はfridaスクリプトを記述し、関連する関数呼び出しをフックし、パラメータや戻り値を取得して送信し、アプリケーションにインジェクトするというプロセスです。「Fridaを使用してデータをアップロードする」の章で、簡単なデモと使用方法を学ぶことができます。

オートメーションコード

もちろん、オートメーションコードも不可欠な要素です。なぜなら、関連するロジックをトリガーするためにオートメーションが必要だからです。オートメーションコードを記述するための通常のフローは次のようになります。まず、FIRERPAのリモートデスクトップを開く必要があります。次のようなインターフェースが表示されるはずです。

リモートデスクトップ

次に、自動操作したいアプリを開き、リモートデスクトップの右上にある目のアイコンをクリックすると、次のようなインターフェースが表示されます。ここで、操作したい要素を選択し、クリックすると要素情報を表示できます。

豆知識

もちろんコードで開くこともできます。これらについては後で説明します。

要素の選択

右側にtextやresourceIdなどの要素情報が表示されているのがわかります。今、この要素をクリックしたいとします。その場合、次のようなコードを記述します。このコードの意味は、「textが'同意'である要素をクリックする」です。

d(text="同意").click()

注釈

これは単なる例です。セレクターの書き方はたくさんあり、この例では最も簡単な書き方のみを紹介しています。

さて、最も簡単な書き方を理解しましたね。if elseなどの制御ロジックを記述し、existsなどの他のインターフェースと組み合わせることで、完全な自動操作フローを実現できます。ほら、それほど難しくないでしょう。

UIレイアウトの検査

通常、オートメーションコードを記述するにはUIレイアウトの検査が不可欠です。これはセレクターの条件を取得する唯一の方法です。まず、ブラウザでデバイスのリモートデスクトップを開く必要があります。次に、リモートデスクトップの右上にある目のアイコンをクリックしてレイアウト検査モードに入ります。このモードでは、左側の画面上の点線の枠をクリックして、対応する要素の情報を表示できます。その中の属性をセレクターのパラメータとして使用できます。再度目のアイコンをクリックすると、レイアウト検査モードが終了します。レイアウト検査はページの変更に伴って更新されません。常にショートカットキーを押した瞬間の画面レイアウトが表示されます。レイアウトを更新する必要がある場合は、手動でショートカットキー CTRL + R を押してください。

要素の検査

ヒント

レイアウト検査画面でTABキーを押して、すべての要素を順番に表示することもできます。

UIセレクター

UIセレクター(Selector)はAndroid要素を操作するために使用されます。XPATHルールのようなものだと理解しても構いません。違いはありますが、おおよその用途は同じです。FIRERPAでは、セレクターは Selector ですが、ほとんどの場合、このクラスに直接触れる必要はありません。前述の文章で、これを見たことがあるはずです。完全な形では、以下のオプションパラメータが含まれています。

マッチングタイプ説明
textテキスト完全一致
textContainsテキスト部分一致
textStartsWithテキスト前方一致
classNameクラス名一致
descriptiondescription完全一致
descriptionContainsdescription部分一致
descriptionStartsWithdescription前方一致
clickableクリック可能
longClickable長押し可能
scrollableスクロール可能
resourceIdリソースID一致

ほとんどの場合、resourceId、text、description、textContainsなどがパラメータとして使用されます。要素に通常のresourceIdが存在する場合、それを優先的にSelectorとして使用します。例:d(resourceId="com.xxx:id/mobile_signal")。そうでない場合は、textを使用します。例:d(text="クリックして入る")、またはより曖昧にd(textContains="クリック")。descriptionもtextと同様ですが、使用頻度は比較的低いです。

ヒント

セレクター(Selector)は、前述のUIレイアウト検査機能を通じて取得した関連する主要パラメータを組み合わせて構成されます。

画面座標の定義

オートメーション操作の過程で、詳細な座標や領域座標を使用して操作する必要がある状況に遭遇することは避けられません。しかし、多くの人が座標の問題についてあまり詳しくない可能性があるため、ここでAndroidの画面座標に関する知識を紹介します。

ご存知のように、画像には解像度があり、画面にもあります。Androidの画面では、横向き、縦向き、または自動回転する画面であっても、一貫して左上隅を原点(0,0)とし、右および下方向に拡張される座標系が使用されます。Xが横軸、Yが縦軸です。図のように。

画面座標

上の図からわかるように、画面の左上隅の座標は0,0、右上隅の座標は1080,0、左下隅は0,1920、右下隅は1080,1920です。この情報に基づいて、画面上の任意の点の座標を計算できます。

注釈

画面が元々縦向きか横向きか、あるいは自動回転するかに関わらず、一貫して画面の現在の向きの左上隅が原点となります。

画面上の点

FIRERPAには、画面に関する2つの定義があります。クリックやスクリーンショットなどの一部の操作では、領域または座標情報を提供する必要があります。一般的な座標点については、以下の定義を使用します。これは画面座標(100,100)の点を表します。

Point(x=100, y=100)

領域の定義

領域の定義は、画面上の長方形の領域です。その定義は少し複雑なので、注意深くお読みください。私たちはBoundを使用して画面上の一つの領域を表します。これにはtopleftbottomrightの4つのパラメータが必要です。少し混乱するかもしれませんが、以下をよく理解してください:topは長方形の上辺が画面の上辺からどれだけ離れているかのピクセル距離、leftは長方形の左辺が画面の左辺からどれだけ離れているかのピクセル距離、rightは長方形の右辺が画面の左辺からどれだけ離れているかの距離、bottomは長方形の下辺が画面の上辺からどれだけ離れているかの距離を表します。要するに、すべての距離は原点から放射状に広がるXY軸からの距離であると理解できます。以下に、理解を助けるための図を示します。スマートフォンの画面は引き続き1080x1920で、デバイスは現在縦向きの状態です。

画面領域

今、画面が4等分されていると仮定し、図に示されている左上と右下の2つの領域の定義を取得する必要があります。ルールに従って、領域1の長方形の上辺は画面の上辺から0ピクセル、左辺は画面の左辺から0ピクセル、下辺は画面の上辺から960ピクセル(1920÷2)、右辺は画面の左辺から540ピクセル(1080÷2)です。したがって、その定義は次のようになります。

Bound(top=0, left=0, right=540, bottom=960)

同様に、領域2の長方形の上辺は画面の上辺から960ピクセル、左辺は画面の左辺から540ピクセル、右辺は画面の左辺から1080ピクセル、下辺は画面の上辺から1920ピクセルです。したがって、2番目の長方形の定義は次のようになります。

Bound(top=960, left=540, right=1080, bottom=1920)

Androidアプリのデータ

各Androidアプリは、デバイス上にアプリのデータを保存するための専用ディレクトリを持っています。通常、アプリ関連のデータは /data ディレクトリに保存されます。d.application("com.example").info()インターフェースを呼び出すことで、アプリのデータディレクトリを取得できます。ほとんどの場合、/data/user/0/com.example.testに直接cdしてユーザーディレクトリに移動することもできます。通常の /data ディレクトリに加えて、一部のアプリは /sdcard/Android ディレクトリにマルチメディアなどの他のファイルを保存することもあります。

SMSデータベースの表示

時々、このデバイスで受信したSMSがどこに保存されているかを見たいと思うかもしれません。非常に良いアイデアですし、非常に簡単です。extensionを記述することで、内容を直接読み取り、HTTPインターフェースを介してリアルタイムで取得することも可能です! 私たちは通常のAndroidの考え方に従って進めます。もしあなたの環境が異なる場合は、ご自身で発想を広げてください。Androidでは、SMSアプリの名前はcom.android.mmsであるはずなので、直接/data/user/0/com.android.mmsディレクトリに移動できます。以下の操作で、databasesディレクトリにいくつかのデータベースがあることがわかります。ここにあるmmssms.dbが私たちの目標です。

 λ 10:12 /data/user/0/com.android.mms ➥ ls -la
total 82
drwx------    7 u0_a78   u0_a78        3452 Jan  2  2021 .
drwxrwx--x  381 system   system       53248 May  2 16:46 ..
drwxrws--x    3 u0_a78   u0_a78_c      3452 Jan  2  2021 cache
drwxrws--x    2 u0_a78   u0_a78_c      3452 Jan  2  2021 code_cache
drwxrwx--x    2 u0_a78   u0_a78        3452 Jan  2  2021 databases
drwxrwx--x    7 u0_a78   u0_a78       24576 Feb 26 13:43 files
drwxrwx--x    2 u0_a78   u0_a78        3452 May  4 10:12 shared_prefs
 λ 10:12 /data/user/0/com.android.mms ➥ ls -l databases/
total 504
-rw-rw----    1 u0_a78   u0_a78       24576 Jan  2  2021 dynamic_bubble
-rw-------    1 u0_a78   u0_a78           0 Jan  2  2021 dynamic_bubble-journal
-rw-rw----    1 u0_a78   u0_a78      491520 Feb 27 04:18 mmssms.db
-rw-------    1 u0_a78   u0_a78           0 Jan  2  2021 mmssms.db-journal
 λ 10:12 /data/user/0/com.android.mms ➥

もちろん、読み取りは非常に簡単です。なぜなら、Androidでは通常のアプリのデータベースはSQLiteだからです。ただし、セキュリティの高い一部のアプリでは、データベース自体も暗号化されています。もちろん、FireRPAはこんなに強力なのにそれがないわけがありません。FireRPAは通常のSQLiteを読み取れるだけでなく、WeChat(sqlcipher)aes-256、WeChat Work aes-128、Alibaba系sqlcrypto(aes-128)など、さまざまなタイプのデータベースをリアルタイムで読み取ることもサポートしています(もちろん、秘密鍵を自分で見つける必要があります)。以下では、システムのSMS内容を簡単に読み取る方法をデモンストレーションします。非常に簡単で、コマンド1つで完了します。もちろん、extensionを記述して読み取ることもできます。

sqlite3 databases/mmssms.db .dump

もちろん、出力は大量になりますが、その中から必要なデータが含まれるテーブルをすぐに見つけ、自分でSQLを実行することができます。この方法は98%のAndroidアプリに適用でき、残りの2%は暗号化されたデータベースです。

暗号化されたデータベースの表示

これらの暗号化されたデータベースについては、自分でデータベースの秘密鍵またはその計算・生成方法を見つける必要があります。以下では、関連ソフトウェアのデータベースを読み取る方法を簡単に紹介します。PRAGMAを使用して秘密鍵をプリセットする方法のみを紹介します。これが何かわからない場合は、まずsqliteについて学んでください。

WeChat系 (sqlcipher)

PRAGMA cipher = "sqlcipher";
PRAGMA legacy = 1;
PRAGMA key = "database-key";

WeChat Work (wxsqlite)

PRAGMA cipher = "aes128cbc";
PRAGMA hexkey = "database-key"

Alibaba系 (sqlcrypto)

PRAGMA cipher = "sqlcrypto";
PRAGMA key = "database-key"

ヒント

Androidアプリのデータベースは、必ずしもdatabasesディレクトリにあるとは限りませんよ。

その他のデータの表示

もちろん、アプリのデータディレクトリにはデータベースだけでなく、shared_prefs(xml)など、アプリ関連のパラメータ、設定、キャッシュ、ファイルも含まれています。しかし、ここではこれ以上詳しく説明しませんので、ご自身で探求してみてください。

オートメーション補助手段

オートメーション業務において、すべてのアプリがセレクターによる位置特定に適しているわけではありません。ゲームのような一部のUIはリアルタイムでレンダリングされるため、Androidレベルのページレイアウトが存在しません。したがって、このようなアプリに対しては、OCRや画像マッチングを通じて操作を判断するしかありません。私たちは、これらの業務目標を達成するために、完全なOCR補助ソリューションと、内蔵の画像SIFT、テンプレートマッチングソリューションを提供しています。ドキュメントで関連するインターフェースとその使用方法を見つけることができます。

更新中...