Home | History | Annotate | Download | only in content
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.apis.content;
     18 
     19 // Need the following import to get access to the app resources, since this
     20 // class is in a sub-package.
     21 import com.example.android.apis.R;
     22 
     23 import android.app.Activity;
     24 import android.app.PendingIntent;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentSender;
     28 import android.content.pm.PackageInstaller;
     29 import android.os.Bundle;
     30 import android.view.View;
     31 import android.view.View.OnClickListener;
     32 import android.widget.Button;
     33 import android.widget.Toast;
     34 
     35 import java.io.IOException;
     36 import java.io.InputStream;
     37 import java.io.OutputStream;
     38 
     39 
     40 /**
     41  * Demonstration of package installation and uninstallation using the package installer Session
     42  * API.
     43  *
     44  * @see InstallApk for a demo of the original (non-Session) API.
     45  */
     46 public class InstallApkSessionApi extends Activity {
     47     private static final String PACKAGE_INSTALLED_ACTION =
     48             "com.example.android.apis.content.SESSION_API_PACKAGE_INSTALLED";
     49 
     50     @Override
     51     protected void onCreate(Bundle savedInstanceState) {
     52         super.onCreate(savedInstanceState);
     53 
     54         setContentView(R.layout.install_apk_session_api);
     55 
     56         // Watch for button clicks.
     57         Button button = (Button) findViewById(R.id.install);
     58         button.setOnClickListener(new OnClickListener() {
     59             public void onClick(View v) {
     60                 PackageInstaller.Session session = null;
     61                 try {
     62                     PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
     63                     PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
     64                             PackageInstaller.SessionParams.MODE_FULL_INSTALL);
     65                     int sessionId = packageInstaller.createSession(params);
     66                     session = packageInstaller.openSession(sessionId);
     67 
     68                     addApkToInstallSession("HelloActivity.apk", session);
     69 
     70                     // Create an install status receiver.
     71                     Context context = InstallApkSessionApi.this;
     72                     Intent intent = new Intent(context, InstallApkSessionApi.class);
     73                     intent.setAction(PACKAGE_INSTALLED_ACTION);
     74                     PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
     75                     IntentSender statusReceiver = pendingIntent.getIntentSender();
     76 
     77                     // Commit the session (this will start the installation workflow).
     78                     session.commit(statusReceiver);
     79                 } catch (IOException e) {
     80                     throw new RuntimeException("Couldn't install package", e);
     81                 } catch (RuntimeException e) {
     82                     if (session != null) {
     83                         session.abandon();
     84                     }
     85                     throw e;
     86                 }
     87             }
     88         });
     89     }
     90 
     91     private void addApkToInstallSession(String assetName, PackageInstaller.Session session)
     92             throws IOException {
     93         // It's recommended to pass the file size to openWrite(). Otherwise installation may fail
     94         // if the disk is almost full.
     95         try (OutputStream packageInSession = session.openWrite("package", 0, -1);
     96              InputStream is = getAssets().open(assetName)) {
     97             byte[] buffer = new byte[16384];
     98             int n;
     99             while ((n = is.read(buffer)) >= 0) {
    100                 packageInSession.write(buffer, 0, n);
    101             }
    102         }
    103     }
    104 
    105     // Note: this Activity must run in singleTop launchMode for it to be able to receive the intent
    106     // in onNewIntent().
    107     @Override
    108     protected void onNewIntent(Intent intent) {
    109         Bundle extras = intent.getExtras();
    110         if (PACKAGE_INSTALLED_ACTION.equals(intent.getAction())) {
    111             int status = extras.getInt(PackageInstaller.EXTRA_STATUS);
    112             String message = extras.getString(PackageInstaller.EXTRA_STATUS_MESSAGE);
    113 
    114             switch (status) {
    115                 case PackageInstaller.STATUS_PENDING_USER_ACTION:
    116                     // This test app isn't privileged, so the user has to confirm the install.
    117                     Intent confirmIntent = (Intent) extras.get(Intent.EXTRA_INTENT);
    118                     startActivity(confirmIntent);
    119                     break;
    120 
    121                 case PackageInstaller.STATUS_SUCCESS:
    122                     Toast.makeText(this, "Install succeeded!", Toast.LENGTH_SHORT).show();
    123                     break;
    124 
    125                 case PackageInstaller.STATUS_FAILURE:
    126                 case PackageInstaller.STATUS_FAILURE_ABORTED:
    127                 case PackageInstaller.STATUS_FAILURE_BLOCKED:
    128                 case PackageInstaller.STATUS_FAILURE_CONFLICT:
    129                 case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
    130                 case PackageInstaller.STATUS_FAILURE_INVALID:
    131                 case PackageInstaller.STATUS_FAILURE_STORAGE:
    132                     Toast.makeText(this, "Install failed! " + status + ", " + message,
    133                             Toast.LENGTH_SHORT).show();
    134                     break;
    135                 default:
    136                     Toast.makeText(this, "Unrecognized status received from installer: " + status,
    137                             Toast.LENGTH_SHORT).show();
    138             }
    139         }
    140     }
    141 }
    142