JavaソースコードなしでAndroidアプリをデバッグする:ブレークポイントに関するいくつかの言葉

この記事について



これは、 JavaソースコードなしでAndroidアプリケーションをデバッグすることに関する昨日の私の記事の続きです (誰かがそれを読んでいないなら、それから始めることを強くお勧めします)。 昨日、ApkツールバンドルとNetBeansを設定して使用を開始する方法について順を追って説明しました。 そこの最後の2つのポイントは、次のようなものでした。



13.関心のある命令にブレークポイントを設定します...何とか何とか...



14.ブレークポイントが機能するように、アプリケーションで何かを行います。 その後、段階的なデバッグを実行したり、フィールドや変数の値を表示したりできます。



さらに、落とし穴のセクションでは、アプリケーションを開始するアクティビティのonCreate(...)



メソッドの命令にブレークポイントを設定するなど、最初からアプリケーションのデバッグを開始できない理由について説明しました。



この記事では、最初からJavaソースコードなしでアプリケーションのデバッグを開始する方法を示します。 この記事も初心者向けではありません。 少なくともSmaliアセンブラーの構文を理解し、ペンで.smaliファイルにパッチを当て、そこにコードを正しく入力できる必要があります。



ツール



再びApk-tool 1.4.1NetBeans 6.8が必要です -これらはこれまでで最も古いバージョンです。 新しいバージョンでは、デバッグを機能させることができません。 そして、私だけでなく、テーマ別フォーラムでの議論によって判断します。



昨日の記事ですでにApkツールとNetBeansのインストールについて説明しましたが、それでも繰り返します。 NetBeansはデフォルトでインストールされます。インストールウィザードで[次へ]、[次へ]、[次へ]の順にクリックするだけです。 Apk-toolsのインストールは、 apktool.jar



ファイルをアーカイブから任意のフォルダーに抽出するapktool.jar



です。



アプリケーションの最初にブレークポイントを置く方法



アイデアは一般的にシンプルです。 最初にアプリケーションで開始するアクティビティを見つけ、このアクティビティのonCreate(...)



メソッドの開始時に無限ループに入る必要があります。 アプリケーションが起動し、このアクティビティのコンストラクターを呼び出した直後に、 onCreate(...)



メソッドが呼び出されます。 その結果、制御は無限のサイクルに陥ります。 そこでループが回転している間、実行中のアプリケーションにデバッガーをゆっくりとアタッチし、無限ループの直後にブレークポイントを配置してから、デバッガーの機能を利用して、制御をこのループから抜けさせます。 そしてすぐにブレークポイントに到達しました。 ご覧のとおり、すべてが基本です。



このセクションでは、手順を追って説明します。 この指示はWindows用に書かれていますが、ほとんどの場合、LinuxおよびMac OSで動作します。



指示に正確に従ってください-これは重要です!



  1. Apkツールを使用して、.apkファイルをtemp



    ディレクトリにデコードします。 -d



    オプションを使用しないでください

     java -jar apktool.jar d my.app.apk temp
          
          





    その結果、 temp/smali



    ディレクトリに多数の.smaliファイルが作成されます。

  2. temp/AndroidManifest.xml



    ファイルで、アクティビティを見つけます

     <intent -filter="-filter"> <action android:name="android.intent.action.MAIN"> <category android:name="android.intent.category.LAUNCHER"> </intent>
          
          





    これは、アプリケーションで最初に開始されるアクティビティです。

  3. 最初にアプリケーションで開始するアクティビティを見つけましたか? ここで、このアクティビティのクラス(通常はandroid.app.Activity



    クラスの子孫)を実装する.smaliファイルを見つけます。 temp/smali



    深く見てください。
  4. このクラスで、呼び出しの直後にonCreate(...)



    メソッドを見つけます(通常、この呼び出しは最初から始まります)

     invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
          
          





    onCreate(...)



    で次のコードを記述します。

     :debug sget v0, Lmy/activity/class/MyActivity;->debugFlag:I if-nez v0, :debug
          
          





    気配りのある読者は、おそらく、このコードが前に説明した無限ループであることをすでに推測していました。 当然、 MyActivity



    代わりに実名アクティビティを使用する必要があり、 v0



    代わりに適切なローカルレジスタをこのコードで使用できます。 適切なレジスタがない場合は、それに応じて.registers



    または.registers



    編集して追加します。

  5. また、クラスにフィールドを追加します

     .field static debugFlag:I = 0x01
          
          





    そうしないと、前の段落の無限ループのコードは機能しません。

  6. -d



    オプションを指定せずにtemp



    ディレクトリを.apkファイルに再構築します。

     java -jar apktool.jar b temp my.app.apk
          
          





    もちろん、元のmy.app.apk



    はこの前のどこかにmy.app.apk



    必要があります。




これでmy.app.apk



パッチが適用されmy.app.apk



。 アプリケーションが開始するアクティビティのクラスのonCreate(...)



メソッドの開始時に、無限ループに入りました。 さて、このパッチを適用したmy.app.apk



を取り、昨日の記事の段階的な指示に従ってください (「デバッグ」セクションを参照)。 この手順の9番目のステップでは、アプリケーションを起動した後、黒い画面が表示されることに注意してください。 これは正常です、そうであるはずです! これは、アプリケーションの起動直後に、パッチを適用したonCreate(...)



メソッドが呼び出され、コントロールが無限ループに陥ったことを意味します。 しばらくしてAndroidが応答しないためにアプリケーションを閉じるように要求する場合、指示に従って厳密に拒否してさらに進んでください!



指示の12番目のステップで、NetBeansで、パッチを適用したonCreate(...)



メソッドが配置されている.javaファイルを開きます。 NetBeansのデバッグパネルの一時停止ボタンを使用します。 次に、この開いている.javaファイルで、 onCreate(...)



入力した無限ループコードの後の最初のステートメントにブレークポイントを配置します。 次に、NetBeansデバッガーで変数を表示および編集する機能を使用して、 debugFlag



フィールドの値を0



に変更し、NetBeansのデバッグパネルで[デバッグの続行]ボタンをクリックします。 管理は無限ループを終了し、すぐにブレークポイントに到達します。



これで、アプリケーションを最初から安全にデバッグできるようになりましたonCreate(...)



最初のonCreate(...)



メソッドの最初の呼び出しからです。



waitForDebuggerに関するいくつかの言葉()



読者は、このトピックで少しですが、おそらく、この記事で無限ループを使用するのと同じ目的でandroid.os.Debug.waitForDebugger()



メソッドを使用することに関するトピックフォーラムを読んでください。 この同じ読者は、 onCreate(...)



最初に1つの静的メソッドへの呼び出しを記述することはできますが、何らかの種類の庭を周期的に積み重ねていることに驚くでしょう。

 invoke-static {}, Landroid/os/Debug;->waitForDebugger()V
      
      





メソッドはパラメータなしで呼び出されることに注意してください。つまり、適切なレジスタがない場合、ローカルレジスタを追加する必要はありません。 それは見えるだろう-美! 他に何が必要ですか?



理論的には、何も必要とせず、それを使用してください。 しかし実際には、すべてが少し複雑です。 実際、 android.os.Debug.waitForDebugger()



したフォーカスは常に機能するとは限りません。 多くの場合(私のものを含む)、 android.os.Debug.waitForDebugger()



呼び出した直後にandroid.os.Debug.waitForDebugger()



アプリケーションは実際に「フリーズ」し、デバッガが参加するのを待ちます。 これはDDMSでも確認できます。アプリケーションの反対側に小さな「赤いバグ」アイコンが表示されます。 ただし、デバッガをアプリケーションに接続するとすぐに、制御はすぐにandroid.os.Debug.waitForDebugger()



後の次の命令に渡され、アプリケーションは停止せずにさらに実行を開始します。 android.os.Debug.waitForDebugger()



後にブレークポイントを置く時間はありません。 これに関する議論については、例えばこちらをご覧ください。



なぜandroid.os.Debug.waitForDebugger()



がこのような人のために、そしてそのような人のためにandroid.os.Debug.waitForDebugger()



のか-今のところはわかりません。 おそらくコメントで誰かがこれについて説明するでしょう。 また、コメントで記事について質問することができますし、質問するべきです。 私はできるだけ早く答えようとします、しかし、私が愚かであるならば-辛抱してください。 私は皆に答えようとします。



ハッピーデバッグ!



All Articles