アプリケーション上からapkをインストールする


AndroidアプリケーションはAndroidマーケットからのみではなく、それ以外の手段でも
インストールすることが可能です。たとえば、SDカードなどの領域に保存しているapkを
アプリケーション上からインストールすることができます。

これによりたとえば、Androidマーケットに公開できないアプリ(アップロード上限を超えてしまうサイズのアプリのような)を公開したい場合や、独自のマーケットで公開したい場合などに利用することが可能です。

詳しい解説は続きからどうぞ。

MIME typeを指定する

apkのインストールはMIME typeに
application/vnd.android.package-archiveを指定したIntentを発行するだけです。

たとえばSDカード上に保存されているapkをインストールしたい場合には以下のようにします。

1
2
3
4
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);

2行目でIntentを生成し、3行目でapkファイルとMIME typeを指定しています。
4行目でIntentを発行するとアプリケーションのインストール画面が表示され、
ユーザにインストールの確認を行います。

Webサーバ上のapkをインストールする

ここで、サンプルコードとしてWebサーバ上に公開しているapkを自動で
ダウンロード・インストールする方法についてご紹介します。

アプリケーション上のボタンを押すとWebサーバ(ここでは例としてhttp://hogehoge.com/myApp.apk)から
apkをダウンロードしインストールを開始します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class InstallAPKActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        // パフォーマンス低下を検出する機能を無効にしておく
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
 
        Button button = (Button) findViewById(R.id.button1);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ダウンロード・インストール開始
                download("http://hogehoge.com/myApp.apk");
            }
        });
    }
 
    /**
      ダウンロード・インストールメソッド
    */
    public void download(String apkurl) {
        try {
            // URL設定
            URL url = new URL(apkurl);
 
            // HTTP接続開始
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            c.setRequestMethod("GET");
            c.connect();
 
            // SDカードの設定
            String PATH = Environment.getExternalStorageDirectory() + "/download/";
            File file = new File(PATH);
            file.mkdirs();
 
            // テンポラリファイルの設定
            File outputFile = new File(file, "app.apk");
            FileOutputStream fos = new FileOutputStream(outputFile);
 
            // ダウンロード開始
            InputStream is = c.getInputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            fos.close();
            is.close();
 
            // Intent生成
            Intent intent = new Intent(Intent.ACTION_VIEW);
            // MIME type設定
            intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")), "application/vnd.android.package-archive");
            // Intent発行
            startActivity(intent);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

8行目で、StrictModeと呼ばれるパフォーマンス低下を検出する機能を無効にする命令を記述しています。
今回のテーマと直接は関係ないですが、Android 3.0以降メインスレッドから
ネットワーク通信を行うとStrictModeによってandroid.os.Networkonmainthreadexception例外に
なってしまいます。
本来はダウンロード処理は別スレッドにするべきですが、
今回はサンプルということでStrictModeを無効にすることで回避しています。

次にボタンが押されたときにダウンロード・インストールするように16行目で
後述するdownloadメソッドを呼び出しています。

24行目からdownloadメソッドを定義しています。
29行目〜32行目でHttpURLConnectionクラスを使ってHTTP接続を開始します。
(HttpURLConnectionクラスを利用したHTTP通信については「HttpURLConnectionを使用してHTTP通信を行う」を参考にして下さい)

34行目〜41行目にかけて、apkのダウンロード先となるSDカードのパスを設定します。

44行目でapkをダウンロードします。
そして53行目〜58行目でMIME typeを設定したIntentを発行し、ダウンロードしたapkのインストールを行います。