アプリを自動更新させたい

4,277 views
Skip to first unread message

karamu

unread,
Oct 1, 2013, 9:02:29 AM10/1/13
to android-g...@googlegroups.com
karamuといいます。よろしくおねがいします。
 
自作アプリを自動で更新させたいと思い、Web上で勉強させていただいております。
 
String fileName = Environment.getExternalStorageDirectory() + "/myApp.apk";
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
startActivity(intent);
 
上記の手順で、SDカードなどに保存したapkをアプリから更新可能であることは確認できたのですが、
確認画面を出さずに更新は不可能なのでしょうか。
「android.permission.INSTALL_PACKAGES」というパーミッションがあるようなのですが、
これはたとえばプリインされているようなアプリにのみ有効?ということなのでしょうか。
 

Hirokazu Fukami

unread,
Oct 1, 2013, 10:34:20 AM10/1/13
to android-g...@googlegroups.com
こんばんはfkmです。

アプリのインストール/更新を確認画面なしで行うのは
セキュリティの面から不可能だと思います。

悪意をもったアプリを、確認なしにインストール/更新できてしまうのは
まずいですよね?

2013/10/1 karamu <karamuk...@gmail.com>:
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループから退会し、メールの受信を停止するには、android-group-j...@googlegroups.com
> にメールを送信します。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> http://groups.google.com/group/android-group-japan からこのグループにアクセスしてください。
> その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。



--
-------------------------------------------------------------
深見 浩和(Hirokazu Fukami)

URI:http://www.fkmsoft.jp
email: f...@fkmsoft.jp

kacodama

unread,
Oct 1, 2013, 10:02:11 PM10/1/13
to android-g...@googlegroups.com
メーカーのシステム署名が必要となりますので、基本的には不可能となります。

2013年10月1日火曜日 22時02分29秒 UTC+9 karamu:

masa

unread,
Oct 2, 2013, 3:33:50 AM10/2/13
to android-g...@googlegroups.com
私も以前、そのことを調査をしましたが、結論は無理でした。
karamuさん同様にapkファイルを一時的にダウンロードし、パッケージインストールのintentを投げることにより再インストールを行う感じで実装を行いました。

android.permission.INSTALL_PACKAGES”はキャリアのマーケットアプリのみに適用されるみたいですね。


2013年10月1日火曜日 22時02分29秒 UTC+9 karamu:

karamu

unread,
Oct 2, 2013, 4:38:46 AM10/2/13
to android-g...@googlegroups.com

みなさま、ありがとうございます。
下記のリンク先をみますと、
android:protectionLevel "signature"の箇所に
「アプリケーションが許可を宣言したのと同じ証明書で署名されたアプリケーションを要求した場合のみ、システムが付与する許可です。証明書が合致したとき、システムはユーザに通知しないで、またはユーザの明示的な受入れを求めることなく、自動的に許可を付与します。 」
のような記載があり、署名つきapkの場合は確認画面がでないのかな?と考えた次第です。
#署名についてはほぼ知識がないので、今から手探りしていく予定です…。
 
 
 
「android.permission.INSTALL_PACKAGES」はキャリア向けのパーミッションなのですね。
うーむ。もしキャリアのプリインアプリのようなものでしたら、
このパーミッションを付加したら、質問に書いていますコードで
確認画面出さずにインストールされるのかなぁ…。
 

kacodama

unread,
Oct 3, 2013, 12:34:34 AM10/3/13
to android-g...@googlegroups.com
そのインテントは、「インストーラーを起動する」インテントですので、システム署名が付いていても、
インストーラーの確認画面が表示されます。

PackagetManagerのinstallPackage/deletePackageのAPIをリフレクションで呼ぶ必要があります。
ただし、システム署名がないと、最終的に呼び出しに失敗します。

英語がほとんどになりますが一応API名等はぐぐればサンプルコードは出てきます。

繰り返しになりますが、システム署名は、端末メーカーやキャリアにお願いして付与してもらう必要があります。

以上ご参考までに。


2013年10月2日水曜日 17時38分46秒 UTC+9 karamu:

kacodama

unread,
Oct 3, 2013, 12:36:30 AM10/3/13
to android-g...@googlegroups.com
補足

インストーラーの確認画面を出さずにインストールするためには、
>PackagetManagerのinstallPackage/deletePackageのAPIをリフレクションで呼ぶ必要があります。

です。

2013年10月3日木曜日 13時34分34秒 UTC+9 kacodama:

karamu

unread,
Oct 3, 2013, 5:03:26 AM10/3/13
to android-g...@googlegroups.com
kacodamaさま
ありがとうございます。
 
確かに
startActivity(intent);
しているので確認画面はでてしまいますね。失念しておりました。
残念ながら挙動の確認はできませんがずいぶんとすっきりしました。
ありがとうございます。

karamu

unread,
Oct 7, 2013, 2:01:56 AM10/7/13
to android-g...@googlegroups.com

kacodamaさまのアドバイスからお試しですが、
MainActivity.javaでボタンを押してinstallPackageを実施するようにしてみました

★箇所でセキュリティで怒られちゃいましたが、
リフレクションで実施しようと試みるところまで作れました。
残念ながら権限がないのでアップデートは行えませんが、
勉強になりました。ありがとうございました。

java.lang.reflect.InvocationTargetException
 at java.lang.reflect.Method.invokeNative(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:511)
 at com.example.test.MainActivity$3.onClick(MainActivity.java:145)
 at android.view.View.performClick(View.java:4084)
 at android.view.View$PerformClick.run(View.java:16966)
 at android.os.Handler.handleCallback(Handler.java:615)
 at android.os.Handler.dispatchMessage(Handler.java:92)
 at android.os.Looper.loop(Looper.java:137)
 at android.app.ActivityThread.main(ActivityThread.java:4745)
 at java.lang.reflect.Method.invokeNative(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:511)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
 at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.SecurityException: Neither user xxxxx nor current process has android.permission.INSTALL_PACKAGES.★
 at android.os.Parcel.readException(Parcel.java:1425)
 at android.os.Parcel.readException(Parcel.java:1379)
 at android.content.pm.IPackageManager$Stub$Proxy.installPackage(IPackageManager.java:2297)
 at android.app.ApplicationPackageManager.installPackage(ApplicationPackageManager.java:968)
 14 more

Kuchinashi

unread,
Oct 7, 2013, 2:47:02 AM10/7/13
to android-g...@googlegroups.com
Kuchinashiと申します.

プラットフォーム署名が無くてもrootとsuがあれば,直接pmコマンドを呼び出すことでインストールさせることができる気がします

try {
    p = Runtime.getRuntime().exec("su");

    InputStream es = p.getErrorStream();
    DataOutputStream os = new DataOutputStream(p.getOutputStream());
    os.writeBytes("pm install -r " + {filePath} + "\n");
    os.writeBytes("exit\n");
    os.flush();
    int read;
    byte[] buffer = new byte[1024];
    final StringBuilder log = new StringBuilder();
    while ((read = es.read(buffer)) > 0) {
        log.append(new String(buffer, 0, read));
    }
    Log.i("Log", log.toString());
    p.waitFor();
} catch (IOException e) {
    throw new RuntimeException(e);
}

実際に試してないので,本当に行けるかは分かりませんが…参考になれば

2013年10月1日火曜日 22時02分29秒 UTC+9 karamu:

karamu

unread,
Oct 8, 2013, 8:17:19 PM10/8/13
to android-g...@googlegroups.com
Kuchinashiさま
 
ありがとうございます。
rootですか・・・
お恥ずかしながらroot化等に詳しくなく、まだ怖くて行ったことがありません。
Android端末も実際に使っている携帯しかもっていないので・・・
しかし興味はあります。
root化した場合ですと、単純にsystem/appとかに直接apkをコピーしてあげたらだめなのでしょうか。
該当のapk実施中だとまずい気もします。
#なんだか気になってきました。新しい端末ほしいなぁ。

北爪繭子

unread,
Oct 8, 2013, 8:30:08 PM10/8/13
to android-g...@googlegroups.com
2013/10/02 11:02 "kacodama" <le.s....@gmail.com>:
--

nagamatu

unread,
Oct 8, 2013, 8:41:24 PM10/8/13
to android-g...@googlegroups.com
Androidの facebookアプリケーションのログを見ていると、こっそりと面白い更新をしています。
secondary dexという Javaのクラスを動的に読み込み更新出来るようになっているようです。

10-08 19:51:14.903 I/ActivityManager(  546): Start proc com.facebook.katana:dash for broadcast com.facebook.katana/com.facebook.dash.receivers.DashPackageUninstallReceiver: pid=15510 uid=10085 gids={50085, 1006, 1015, 3003, 1028}
10-08 19:51:15.103 D/CatchMeIfYouCan(15510): Process (dash) ca: '/data/data/com.facebook.katana/app_cmiyc/0C66B38F48468E96F8008B6D5A2AE33B4A60265E01'
10-08 19:51:15.103 D/CatchMeIfYouCan(15510): Process (dash) fc: '/data/data/com.facebook.katana/app_cmiyc/0C66B38F48468E96F8008B6D5A2AE33B4A60265E02'
10-08 19:51:15.103 D/CatchMeIfYouCan(15510): Process (dash) cp: '('dash', 6, 60000, silent [true], restart [true], logout [true])'
10-08 19:51:15.103 D/ACRA    (15510): ACRA is enabled for com.facebook.katana, intializing...
10-08 19:51:15.113 D/ACRA    (15510): Looking for error files in /data/data/com.facebook.katana/app_acra-reports
10-08 19:51:15.113 D/ACRA    (15510): Looking for error files in /data/data/com.facebook.katana/app_minidumps
10-08 19:51:15.113 D/dalvikvm(15510): Trying to load lib /data/app-lib/com.facebook.katana-1/libfb_stl_shared.so 0x41e5d7a0
10-08 19:51:15.113 D/dalvikvm(15510): Added shared lib /data/app-lib/com.facebook.katana-1/libfb_stl_shared.so 0x41e5d7a0
10-08 19:51:15.113 D/dalvikvm(15510): No JNI_OnLoad found in /data/app-lib/com.facebook.katana-1/libfb_stl_shared.so 0x41e5d7a0, skipping init
10-08 19:51:15.113 D/dalvikvm(15510): Trying to load lib /data/app-lib/com.facebook.katana-1/libfb_breakpad_client.so 0x41e5d7a0
10-08 19:51:15.113 D/dalvikvm(15510): Added shared lib /data/app-lib/com.facebook.katana-1/libfb_breakpad_client.so 0x41e5d7a0
10-08 19:51:15.123 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/guava-10.0.1-fork.dex.0.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/guava-10.0.1-fork.dex.1.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-core-2.0.5.dex.0.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-core-2.0.5.dex.1.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-core-2.0.5.dex.2.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-databind-2.0.5.dex.0.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-databind-2.0.5.dex.1.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-databind-2.0.5.dex.2.jar
10-08 19:51:15.133 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-databind-2.0.5.dex.3.jar
10-08 19:51:15.143 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-datatype-guava-2.0.4.dex.0.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-datatype-guava-2.0.4.dex.1.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/jackson-datatype-guava-2.0.4.dex.2.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/diffutils-1.2.1.dex.0.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/diffutils-1.2.1.dex.1.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/nine_old_androids.dex.0.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/nine_old_androids.dex.1.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/nine_old_androids.dex.2.jar
10-08 19:51:15.153 D/DexLibLoader(15510): Deleting old version: /data/data/com.facebook.katana/app_dex/nine_old_androids.dex.3.jar
10-08 19:51:15.153 V/DexLibLoader(15510): Dex already copied
10-08 19:51:15.153 V/DexLibLoader(15510): Creating class loader
10-08 19:51:15.163 V/DexLibLoader(15510): Finished creating class loader
10-08 19:51:15.163 V/DexLibLoader(15510): Preparing secondary program dexes.
10-08 19:51:15.163 V/DexLibLoader(15510): Loaded 3 raw lines of metadata.
10-08 19:51:15.163 V/DexLibLoader(15510): Secondary program dex metadata: secondary-1.dex.jar.xz c0ee4a681e3a40d17df851fb6ef5a80691032872 secondary.dex01.Canary
10-08 19:51:15.163 V/DexLibLoader(15510): Secondary program dex metadata: secondary-2.dex.jar.xz cba14b81f7e741108eb8718540871503eaff5ae1 secondary.dex02.Canary
10-08 19:51:15.163 V/DexLibLoader(15510): Secondary program dex metadata: secondary-3.dex.jar.xz 2347a1ffec03d26b0a7367737faff046b1b6c23e secondary.dex03.Canary
10-08 19:51:15.163 W/DexLibLoader(15510): Unexpected file in program dex directory: /data/data/com.facebook.katana/app_secondary_program_dex/temp_dex_lock
10-08 19:51:15.163 V/DexLibLoader(15510): Preparing to extract secondary-1.dex.jar.xz to /data/data/com.facebook.katana/app_secondary_program_dex/program-c0ee4a681e3a40d17df851fb6ef5a806910328729512848d.dex.jar
10-08 19:51:15.163 V/DexLibLoader(15510): Dex already copied
10-08 19:51:15.163 V/DexLibLoader(15510): Creating class loader
10-08 19:51:15.163 V/DexLibLoader(15510): Finished creating class loader
10-08 19:51:15.163 V/DexLibLoader(15510): Preparing to extract secondary-2.dex.jar.xz to /data/data/com.facebook.katana/app_secondary_program_dex/program-cba14b81f7e741108eb8718540871503eaff5ae19512848d.dex.jar
10-08 19:51:15.163 V/DexLibLoader(15510): Dex already copied
10-08 19:51:15.163 V/DexLibLoader(15510): Creating class loader
10-08 19:51:15.163 V/DexLibLoader(15510): Finished creating class loader
10-08 19:51:15.163 V/DexLibLoader(15510): Preparing to extract secondary-3.dex.jar.xz to /data/data/com.facebook.katana/app_secondary_program_dex/program-2347a1ffec03d26b0a7367737faff046b1b6c23e9512848d.dex.jar
10-08 19:51:15.163 V/DexLibLoader(15510): Dex already copied
10-08 19:51:15.163 V/DexLibLoader(15510): Creating class loader
10-08 19:51:15.163 V/DexLibLoader(15510): Finished creating class loader
10-08 19:51:15.173 V/DexLibLoader(15510): Verifying classes from secondary dexes.
10-08 19:51:15.173 D/DexLibLoader(15510): DexLibLoader.ensureDexLoaded took 46 ms

--


2013年10月1日火曜日 22時02分29秒 UTC+9 karamu:

Kyash

unread,
Oct 8, 2013, 9:38:50 PM10/8/13
to android-g...@googlegroups.com
Kyashです.
 
私もアプリ更新について調べていたことがあって
にたどり着き,/data/appに直接書き込めばよいことがわかりました.
 
私もroot化は怖かったので,エミュレータがroot権限で動作していることを思い出し,
DDMSからpullしたapkファイルを直接/data/appにコピーしてみたら
対話にならずに直接アップデートすることができました.
 
アプリから直接/data/appへのファイル保存を試したわけではないのですが,ご参考まで.
 
試すなら,実機を購入する前に,とりあえずエミュレータで試すとよいと思います.
 
以上です.

2013年10月9日水曜日 9時17分19秒 UTC+9 karamu:

karamu

unread,
Oct 9, 2013, 4:52:48 AM10/9/13
to android-g...@googlegroups.com
Kyash さま
versionCodeとversionNameをトースト表示するだけのAPKを作成して確認しました。
以下、手順になります。
・エミュレータ起動(APKインストール)
・/data/appから、該当のパッケージ名-1.apk削除
・ランチャーからアイコンが削除される
・/data/appにAKPをPUSH
 →ランチャーにアイコンが表示
・アイコンクリック
→Exceptionが発生しました
E/Trace(9589): error opening trace file: No such file or directory (2)
W/asset(9589): Asset path /data/app/com.example.hello-2.apk is neither a directory nor file (type=1).
W/asset(9589): Asset path /data/app/com.example.hello-2.apk is neither a directory nor file (type=1).
Shutting down VM
threadid=1: thread exiting with uncaught exception (group=0x40a13300)
E/AndroidRuntime(9589): FATAL EXCEPTION: main
E/AndroidRuntime(9589): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.hello/com.example.hello.MainActivity}: java.lang.ClassNotFoundException: com.example.hello.MainActivity
Kyashさまの行った手順と異なりますでしょうか?

Kyash

unread,
Oct 9, 2013, 9:10:12 PM10/9/13
to android-g...@googlegroups.com
Kyashです.

私もPUSHで書き込みましたが,/data/appにインストールされたままの状態での書き込みでした.
(アップデートができるか,できないかを確認していましたので...)
最初にインストールした版とアップデート版で異なった文字列を表示するようにしていたので,
PUSHした後に起動して,文字列が変わっていることを確認した覚えがあります.

もしかすると,インストールとアップデートでは違った動作をするのかもしれません.
時間があるときにでも,ちょっと実験してみます.

以上です.とりあえずのご返信まで.

2013年10月9日水曜日 17時52分48秒 UTC+9 karamu:

karamu

unread,
Oct 10, 2013, 2:13:52 AM10/10/13
to android-g...@googlegroups.com
Kyashさま
エミュレータ起動によるAPKインストールをやめて
インストールしていない状態(/data/app/に該当のapkがない状態)で、
/data/app/にAPKをPUSHするようにしました。
versionCode1のものとversionCode2のものを交互にPUSHすると
値が変わることで更新されていることを確認できました。
あらかじめ
/data/app/に該当のパッケージ名-1.apk
があると、それを削除→APKをPUSHする手順では、やはりexceptionが発生してしまいましたが…。

次に、アプリ内でファイルコピーするように変更しました。
なんとなく起動中のアプリのAPKを書き換えるのは…と思い、
ボタン押すと、別のアプリを起動させ、その中でAPKを書き換えるようにしました。
その際、更新したいAPKのアプリを終了させています。(というかKILLしてます)
 
/data/appにコピーされたAPKとコピーしたAPKを比べると同一ファイルでしたが、
何故か、ランチャーからアイコンが消え、設定からアプリは確認できたのですが
古いバージョンのままでした。
しかし、書き換え用のアプリの中で2回書き換えると更新されました。。。
タイミングの問題でしょうか。。。
 
アプリのインストール、アンインストールをReceiverで受けれたような気がするので、
/data/appに直接コピーした場合も受け取れるのか試してみたいと思います。
 
 
 
 
みなさま、
長々とお付き合いいただきまして、本当にありがとうございました。
Reply all
Reply to author
Forward
0 new messages