title: Install APK as system app with INSTALL_PACKAGES
body: <p>I have developed an app that is running with system permissions (it is built into the image of AOSP) and has the INSTALL_PACKAGES permission.</p>
  
  <p>My goal is to install a APK silently in the background without user interaction. I read different approaches on stackoverflow, but most of them were either outdated or simply didn't work.</p>
  
  <p>For example if I try to use the PackageManager (either via reflection or via running as a shell command from within my app) I get the following error and that's where I got stuck currently.</p>
  
  <pre><code>11-20 19:06:10.999  4965  4965 D AndroidRuntime: &gt;&gt;&gt;&gt;&gt;&gt; START 
  
  com.android.internal.os.RuntimeInit uid 10039 &lt;&lt;&lt;&lt;&lt;&lt;
  11-20 19:06:11.199  4965  4965 D AndroidRuntime: Calling main entry com.android.commands.pm.Pm
  11-20 19:06:11.268  4965  4965 E Pm      : Error
  11-20 19:06:11.268  4965  4965 E Pm      : java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.AppOpsManager.checkPackage(int, java.lang.String)' on a null object reference
  11-20 19:06:11.268  4965  4965 E Pm      :  at android.os.Parcel.readException(Parcel.java:2010)
  11-20 19:06:11.268  4965  4965 E Pm      :  at android.os.Parcel.readException(Parcel.java:1950)
  11-20 19:06:11.268  4965  4965 E Pm      :  at android.content.pm.IPackageInstaller$Stub$Proxy.createSession(IPackageInstaller.java:254)
  11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.doCreateSession(Pm.java:607)
  11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.runInstall(Pm.java:431)
  11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.run(Pm.java:150)
  11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.main(Pm.java:107)
  11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
  11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:285)
  11-20 19:06:11.270  4965  4965 I app_process: System.exit called, status: 1
  11-20 19:06:11.270  4965  4965 I AndroidRuntime: VM exiting with result code 1.
  </code></pre>
  
  <p>Can anybody tell me why this error is occurring or alternatively other solutions or the "modern" way to install APKS silently with INSTALL_PACKAGES?</p>
  
  <p>Any help appreciated.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>To the guy who marked this as a duplicate of nullpointer exception - how do you make the connection that would be a duplicate? I am specifically asking for the reasons behind it and not about the nullpointer exception itself. Your duplicate suggestion makes no sense <strong>at all</strong>.</p>
  
  <p><strong>EDIT 2:</strong></p>
  
  <p>My code that tries to install the APK (copied from the package installer app of AOSP sources):</p>
  
  <pre><code>public boolean install(Context context) {
  
      Log.d(TAG, "Start Installation");
  
      String packageName = "com.spotify.music";
      String apkPath = Environment.getExternalStorageDirectory().toString() + "/APKs/spotify.apk";
  
      PackageInstaller.Session session;
      int sessionId;
      PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
      params.setAppPackageName(packageName);
  
      try {
          sessionId = context.getPackageManager().getPackageInstaller().createSession(params);
          session = context.getPackageManager().getPackageInstaller().openSession(sessionId);
      } catch (IOException e) {
          Log.w(TAG, "Error creating/opening the installing session", e);
          return false;
      }
  
      try {
          File file = new File(apkPath);
  
          try (InputStream in = new FileInputStream(file)) {
              long sizeBytes = file.length();
              try (OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes)) {
                  byte[] buffer = new byte[1024 * 1024];
                  while (true) {
  
                      int numRead = in.read(buffer);
  
                      if (numRead == -1) {
                          session.fsync(out);
                          break;
                      }
  
                      out.write(buffer, 0, numRead);
                      if (sizeBytes &gt; 0) {
                          float fraction = ((float) numRead / (float) sizeBytes);
                          Log.d(TAG, "Install progress: " + fraction);
                      }
                  }
              }
          }
  
          Log.d(TAG, "Install finished");
          session.commit(PendingIntent.getBroadcast(context, sessionId, new Intent("android.intent.action.MAIN"), 0).getIntentSender());
  
          return true;
      } catch (IOException | SecurityException e) {
          Log.e(TAG, "Could not write package", e);
  
          session.close();
  
          return false;
      }
  }
  </code></pre>