2013年1月12日土曜日

【Xperia AX SO-01E】電源ボタン長押しメニューに「再起動」追加(3)

電源メニューに「再起動」を追加、まさかの3記事目です。
この記事までのカスタムでは、再起動をタップした後の確認画面や、再起動中のメッセージが「電源を切る」のものと同じままでした。
今回はこれらのメッセージを再起動専用のものにしてみます。

最低限の変更点しか書きません。どの記事までやっているかによってexternal-res.apkのリソースの数が変わってきますが、最低限電源メニューに「再起動」を追加(2)external-res.apkを作る記事までやっていれば機能自体はOKです。

前提は以下です。
・rootとってあること
・作業PCはadbコマンドが使える環境であること
・作業PCにjavaが入っていること
・端末のビルド番号は9.0.G.0.247
・CWMを導入してあること
・母艦はWindows 7
・トラブっても自力で復旧できること(つまり自己責任)

いじるファイルは、以下になります。
/system/framework/external-res.apk
/system/framework/framework.odex

■external-res.apk
external-res.apkの作業フォルダ内、「res」フォルダ以下のxmlにリソース追加します。
まずres\values\public.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <public type="drawable" name="ic_lock_reboot" id="0x7f020000" />
    <public type="drawable" name="ic_lock_recovery" id="0x7f020001" />
    <public type="string" name="global_action_reboot" id="0x7f030000" />
    <public type="string" name="global_action_recovery" id="0x7f030001" />
    <public type="string" name="app_killed_message" id="0x7f030002" />
    <public type="string" name="reboot_title" id="0x7f030003" />
    <public type="string" name="reboot_confirm" id="0x7f030004" />
    <public type="string" name="reboot_progress" id="0x7f030005" />
</resources>

「reboot_title」「reboot_confirm」「reboot_progress」の3つを追加します。それぞれ、再起動確認ダイアログのタイトル、再起動確認ダイアログのメッセージ、再起動中のメッセージになります。
再起動中のタイトルは確認ダイアログのタイトルを兼ねることにします(「電源を切る」の方もそうなっています)。もちろんリソースをもう1つ追加して別タイトルにもできますので、元気がある人は頑張ってください。
「0x7f03xxxx」と振られているリソースIDは、必ず連番にしましょう。追加したIDはframework.odexのソースの方で使いますので、記憶にとどめておいてください。今回はこのIDである前提でいきます。

次にres\values\strings.xml。英語バージョンです。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="global_action_reboot">Reboot</string>
    <string name="global_action_recovery">CWM Reboot</string>
    <string name="app_killed_message">Application killed</string>
    <string name="reboot_title">Reboot</string>
    <string name="reboot_confirm">Your phone will reboot.</string>
    <string name="reboot_progress">Rebooting...</string>
</resources>

続きましてres\values-ja\strings.xml。日本語バージョンです。必ずUTF-8Nで保存しましょう。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="global_action_reboot">再起動</string>
    <string name="global_action_recovery">CWMで再起動</string>
    <string name="app_killed_message">アプリケーションを終了しました</string>
    <string name="reboot_title">再起動</string>
    <string name="reboot_confirm">携帯電話を再起動します。</string>
    <string name="reboot_progress">再起動中...</string>
</resources>

新規でexternal-res.apkをこしらえる場合は、この記事のようにaaptで作成して署名とかしないといけませんが、すでに作っている場合はapktoolで展開、編集、再ビルドという流れで署名のし直しは不要です。

■framework.odex
framework.odexをbaksmaliした展開先の中で、以下のファイルを探してテキストエディタで開きます。
com\android\internal\app\ShutdownThread.smali

「.method private static beginShutdownSequence(Landroid/content/Context;)V」を検索。
その54行くらい下の「const v2, 0x104019c」の周辺に、以下のように処理を追加します。

    .line 201
    .local v1, pd:Landroid/app/ProgressDialog;
    sget-boolean v2, Lcom/android/internal/app/ShutdownThread;->mReboot:Z  #追加

    if-nez v2, :cond_20  #追加

    const v2, 0x104019c

    invoke-virtual {p0, v2}, Landroid/content/Context;->getText(I)Ljava/lang/CharSequence;

    move-result-object v2

    invoke-virtual {v1, v2}, Landroid/app/ProgressDialog;->setTitle(Ljava/lang/CharSequence;)V

    .line 202
    const v2, 0x10401a0

    invoke-virtual {p0, v2}, Landroid/content/Context;->getText(I)Ljava/lang/CharSequence;

    move-result-object v2

    invoke-virtual {v1, v2}, Landroid/app/ProgressDialog;->setMessage(Ljava/lang/CharSequence;)V

    goto :cond_21  #この行から追加

    :cond_20
    const-string v2, "com.android.externalres"

    const/4 v3, 0x4

    invoke-virtual {p0, v2, v3}, Landroid/content/Context;->createPackageContext(Ljava/lang/String;I)Landroid/content/Context;

    move-result-object v0

    const v2, 0x7f030003

    invoke-virtual {v0, v2}, Landroid/content/Context;->getText(I)Ljava/lang/CharSequence;

    move-result-object v2

    invoke-virtual {v1, v2}, Landroid/app/ProgressDialog;->setTitle(Ljava/lang/CharSequence;)V

    const v2, 0x7f030005

    invoke-virtual {v0, v2}, Landroid/content/Context;->getText(I)Ljava/lang/CharSequence;

    move-result-object v2

    invoke-virtual {v1, v2}, Landroid/app/ProgressDialog;->setMessage(Ljava/lang/CharSequence;)V  #この行まで追加

    .line 203
    :cond_21  #追加
    invoke-virtual {v1, v5}, Landroid/app/ProgressDialog;->setIndeterminate(Z)V

    .line 204
    invoke-virtual {v1, v4}, Landroid/app/ProgressDialog;->setCancelable(Z)V

ここはシャットダウン中のメッセージを生成する部分です。「mReboot」に再起動かどうかのフラグが入っているので、それによってテキストの取得元を変えています。2か所ある「0x7f03xxxx」がもちろんexternal-res.apkで追加したタイトルとメッセージのIDになります。
【注】ビルド番号 9.0.G.1.76 では、このあたりのコードが結構変更されており、レジスタ名がずれているのでご注意ください。後半の追加部分(「:cond_20」~「:cond_21」あたり)の中のレジスタ名を「v1」→「v2」に、「v2」→「v3」に、「v3」→「v4」に読み替えてください。「v0」はそのままでOKです。

次に「.method public static shutdown(Landroid/content/Context;Z)V」を検索。
その108行くらい下の「const v4, 0x104019c」の周辺に、以下のように処理を追加します。

    .line 134
    :cond_4a
    new-instance v3, Landroid/app/AlertDialog$Builder;

    const/4 v4, 0x4

    invoke-direct {v3, p0, v4}, Landroid/app/AlertDialog$Builder;-><init>(Landroid/content/Context;I)V

    sget-boolean v4, Lcom/android/internal/app/ShutdownThread;->mReboot:Z  #追加

    if-nez v4, :cond_50  #追加

    const v4, 0x104019c

    invoke-virtual {v3, v4}, Landroid/app/AlertDialog$Builder;->setTitle(I)Landroid/app/AlertDialog$Builder;

    move-result-object v3

    invoke-virtual {v3, v2}, Landroid/app/AlertDialog$Builder;->setMessage(I)Landroid/app/AlertDialog$Builder;

    move-result-object v3

    goto :cond_51  #この行から追加

    :cond_50
    const-string v4, "com.android.externalres"

    const/4 v5, 0x4

    invoke-virtual {p0, v4, v5}, Landroid/content/Context;->createPackageContext(Ljava/lang/String;I)Landroid/content/Context;

    move-result-object v4

    const v5, 0x7f030003

    invoke-virtual {v4, v5}, Landroid/content/Context;->getText(I)Ljava/lang/CharSequence;

    move-result-object v5

    invoke-virtual {v3, v5}, Landroid/app/AlertDialog$Builder;->setTitle(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;

    move-result-object v3

    const v5, 0x7f030004

    invoke-virtual {v4, v5}, Landroid/content/Context;->getText(I)Ljava/lang/CharSequence;

    move-result-object v5

    invoke-virtual {v3, v5}, Landroid/app/AlertDialog$Builder;->setMessage(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;

    move-result-object v3

    :cond_51  #この行まで追加
    const v4, 0x1040013

    new-instance v5, Lcom/android/internal/app/ShutdownThread$1;

    invoke-direct {v5, p0}, Lcom/android/internal/app/ShutdownThread$1;-><init>(Landroid/content/Context;)V

    invoke-virtual {v3, v4, v5}, Landroid/app/AlertDialog$Builder;->setPositiveButton(ILandroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;

前後しますが、ここはシャットダウンの確認ダイアログを生成している部分です。先ほどと似たような感じで、「mReboot」のフラグによって処理を変えています。やはり「0x7f03xxxx」がタイトルやメッセージのリソースIDになっています。

■仕上げ
上記変更後、/system/frameworkのexternal-res.apkとframework.odexを置き換えてください。
電源メニューで「再起動」をタップした後のメッセージが再起動のものに変化していることを確認してください。

12 件のコメント:

  1. こんにちは、素早い再起動ダイアログへの対応ありがとうございます。今回もまるごとコピペしただけですが、TXに導入させていただきました。気持ちよく?再起動出来るようになりました。
    今後も期待しておりますので、よろしくお願いします。

    返信削除
    返信
    1. いえいえ、いつかは対応させないとと思っていたので、順序が早まっただけです。
      それにしてもTX、ほとんどソース一緒なんですね。
      今後もご期待に添えるイジリが出来るかどうか分かりませんが、頑張ってみます。

      削除
  2. 素晴らしいカスタム参考にさせて頂いてます。
    apk作成ではまってまして教えて頂ければ。
    C:\system\apkwork>aapt package -S external-res\res -M external-res\AndroidManife
    st.xml -f -v -F new\u_external-res.apk
    Locale/Vendor pairs:
    /
    ja/

    Files:
    values\public.xml
    Src: external-res\res\values\public.xml
    values\strings.xml
    Src: external-res\res\values\strings.xml
    values-ja\strings.xml
    Src: external-res\res\values-ja\strings.xml
    AndroidManifest.xml
    Src: external-res\AndroidManifest.xml
    applyFileOverlay for drawable
    applyFileOverlay for layout
    applyFileOverlay for anim
    applyFileOverlay for animator
    applyFileOverlay for interpolator
    applyFileOverlay for xml
    applyFileOverlay for raw
    applyFileOverlay for color
    applyFileOverlay for menu
    applyFileOverlay for mipmap
    と流れてaapt.exeは動作を停止しましたと出て手詰まりです。
    何かアドバイスを頂けませんか?

    返信削除
    返信
    1. まずaaptの表示がうちと若干異なるのが気になりますが、aaptのバージョンが違うだけだろうと類推して…。

      私の場合、aaptが止まったのはリソースIDの振り方がまずかった時でした。
      表示を見る限り、stringだけのリソースのようですが、IDは0x7f020000から連番で振っておられるでしょうか。
      0x7f020000で始まってなくても、IDが途中で飛んでもaaptは止まります。

      あとこれは最終手段ですが、実はpublic.xmlを作らずにaaptすると、勝手にIDを振ってくれます。
      出来たapkをapktoolで展開し直すと、ちゃんとpublic.xmlが出来ています。
      (展開し直しが面倒であれば、「aapt l -a apkファイル名」してもIDは分かりますが、リソースの量が多くなってくると多分大変です。)

      ご健闘をお祈りします。

      削除
    2. 質問を書く記事の場所が間違ってましたね(汗)
      早速の返信ありがとうございます。
      0x7020000からだったんですね。ずばりそこ直したらさくっと出来ました!
      ありがとうございました!!!

      削除
    3. いえいえ、上手くいったようで良かったです。
      もし今後リソースの種類を増やして上手くいかなかった場合は、public.xml作らずにリソース自動振り作戦を決行してみてください。私も最初はそれでID振りの法則を知りました。

      削除
  3. 以前はお世話になりました。
    SO-03Dですが、external-res.apk とoverlayを(wikiの管理人さまのお陰で)導入しています。
    この記事のようにCWMリカバリのメッセージも専用のものにしてみたいのですが、
    どう追加したらがわかりません。external-res.apkにはリソースは追加済みです。

    返信削除
    返信
    1. 「CWMリカバリのメッセージ」というのは、電源オプションメニューの文字列ではなく、「再起動中…」とかのことですよね。
      もしそうであれば…実は実装するのが面倒なので敢えて触れていなかったのは内緒です。

      やるとすれば、rebootOrShutdownメソッド内でp1が「recovery」であれば、そのフラグをフィールドに移しておき、この記事でやってるカスタム部分でそのフラグを読んで処理を振り分ける…というのが考えられますが、私自身考えただけで面倒です…。

      削除
    2. レスありがとうございます。やはり面倒なんですね(^_^;)
      20うん年前にCOBOLを仕事にしてましたが、Javaを勉強しなきゃ。
      でもsmaliはわかりづらいですね。
      完璧に自己満足の世界なので、また質問させて頂く事があるかもしれませんが、
      その時は宜しくお願いします。

      ちなみに現在はしがない長距離トラッカーだったりしますので、趣味でいじくってるキューブキューブさんとは同年代の(オーバーフォーティーですが)Xperiaファンです。

      削除
    3. COBOLはちょっとしか知らないですが、他の言語と随分違うなーと思ったことがあります。
      Javaとsmaliは構造は一緒なのですが、細かい部分でいろいろ癖があっていまだに苦しめられています。
      smaliの記事はいつか書かないとなーと思っているところです。我流ですけども…。
      また当ブログ見に来てやってくださいませ。

      私はXperia arc入手してから、Xperiaにぞっこんです。あ、ぞっこんって単語もこの世代ならではですかね…。

      削除
    4. ぞっこんLoveって歌ありませんでした?( ´∀`)
      それはともかく私もarc持ってます…というかarcがスマホデビューでした。
      メモリ不足をどうかしたくて行き着いたのがroot取得(root化って言い方、慣れてはきましたが、やはり違和感あって…)でしたね、私の場合は。
      arcの形状と液晶は逸品だと思います。

      削除
    5. 私はアーク形状でないと物足りなくなり、AXを買うに至りました。arcと比べたらメモリは十分なので、当分はこれでやっていくことと思います。
      ゾッコンloveはシブガキ隊のようですね。確かにリアルタイム…。

      削除