40
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

apkの新しいインストールプロセス

Posted at

Lollipopで実装された新しいapkのインストール形式

5.0からinstall sessionという新しいインストール方法が実装されている。

どういうものかというと、

  • apkインストール時に一時コピーはつくらずに、フラッシュでバイスに直接書き込む
  • その結果、いろいろ効率的になって良い

InstallSessionとかいうらしい。
詳細は別ポストで書く予定。とりあえず試し方。

簡単な試し方

pmコマンド

pmコマンドもすでに対応していて、pm install hogehoge.apkではなくて以下のようにする。

やってることは、

  • セッションをつくって、
  • インスコしたいapk登録して、
  • セッションコミット!

の3段階。簡単。

コマンドの例は以下。

$ pm install-create -i ringo
Success: created install session [1914420212]

$ pm install-write 1914420212 gorira <インスコしたいapkのパス>
Success: streamed 279430 bytes

$ pm install-commit 1914420212
Success

Successと出たらインスコ成功。

あと、$ pm install-abandon セッションID でセッションの破棄。
詳細はpmコマンドのソース見ればわかると思います。

API

ちなみにinstallsessionは公開APIです。
https://developer.android.com/reference/android/content/pm/PackageInstaller.html

ただしandroid.permission.INSTALL_PACKAGES(signature|system)が必要っぽいので、以下試される方は、priv-appにつっこんでくらはい。
以下スニペットです。

private int createSession() {
    final PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
    params.setInstallLocation(PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);

    int sessionId = -1;
    try {
        sessionId = packageInstaller.createSession(params);
    } catch (IOException e) {}

    PackageInstaller.SessionCallback sessionCallback = new
            PackageInstaller.SessionCallback() {
                @Override
                public void onCreated(int i) {
                    Log.v("hoge", "SessionCallback#onCreate : " + i);
                }

                @Override
                public void onBadgingChanged(int i) {
                    Log.v("hoge", "SessionCallback#onBadgingChanged : " + i);
                }

                @Override
                public void onActiveChanged(int i, boolean b) {
                    Log.v("hoge", "SessionCallback#onActiveChanged : "
                            + i + ", boolean :" + b);
                }

                @Override
                public void onProgressChanged(int i, float v) {
                    Log.v("hoge", "SessionCallback#onProgressChanged :" + i + ", " + v);
                }

                @Override
                public void onFinished(int i, boolean b) {
                    Log.v("hoge", "SessionCallback#onFinished : " + i + ", boolean :" + b);
                }
            };

    packageInstaller.registerSessionCallback(sessionCallback);

    return sessionId;
}

private int writeSession(final int sessionId) {
    long sizeBytes = -1;
    final String splitName = 適当な文字列;
    final String apkPath = インスコしたいapkのパス;

    final File file = new File(apkPath);
    if (file.isFile()) {
        sizeBytes = file.length();
    }
    Log.v("hoge", "apk size :" + sizeBytes);

    PackageInstaller.Session session = null;
    InputStream in = null;
    OutputStream out = null;
    try {
        try {
            session = packageInstaller.openSession(sessionId);
            in = new FileInputStream(apkPath);
            out = session.openWrite(splitName, 0, sizeBytes);
            int total = 0;
            byte[] buffer = new byte[65536];
            int c;
            while ((c = in.read(buffer)) != -1) {
                total += c;
                out.write(buffer, 0, c);
            }
            session.fsync(out);
        } catch (IOException e) {
        }

        return 0;
    } finally {

        try {
            out.close();
            in.close();
            session.close();
        } catch (IOException e) {}
    }
}

private void commitSession(final int sessionId) {
    PackageInstaller.Session session = null;
    try {
        try {
            session = packageInstaller.openSession(sessionId);
        } catch (IOException e) {
        }
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent sender = PendingIntent.getActivity(this, 0, intent, 0);
        session.commit(sender.getIntentSender());
    } finally {
        session.close();
    }
}
40
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?