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


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

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

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

MIME typeを指定する

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

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

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をダウンロードしインストールを開始します。

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のインストールを行います。