title: setURLStreamHandlerFactory and "java.lang.Error: Factory already set"
body: <p>I've come across an unexpected error caused by calling <code>URL.setURLStreamHandlerFactory(factory);</code> in an Android application that is being updated.</p>
  
  <pre><code>public class ApplicationRoot extends Application {
  
      static {
          /* Add application support for custom URI protocols. */
          final URLStreamHandlerFactory factory = new URLStreamHandlerFactory() {
              @Override
              public URLStreamHandler createURLStreamHandler(final String protocol) {
                  if (ExternalProtocol.PROTOCOL.equals(protocol)) {
                      return new ExternalProtocol();
                  }
                  if (ArchiveProtocol.PROTOCOL.equals(protocol)) {
                      return new ArchiveProtocol();
                  }
                  return null;
              }
          };
          URL.setURLStreamHandlerFactory(factory);
      }
  
  }
  </code></pre>
  
  <p><strong>Intro:</strong></p>
  
  <p>Here is my situation: I'm maintaining a non-market application used in an enterprise fashion.  My business sells tablets with pre-installed applications that are developed and maintained by the business.  These pre-installed applications are not part of the ROM; they are installed as typical <em>Unknown Source</em> applications.  We do not perform updates through the Play Store or any other market.  Rather, application updates are controlled by a custom <em>Update Manager</em> application, which communicates directly with our servers to perform OTA updates.</p>
  
  <p><strong>Problem:</strong></p>
  
  <p>This <em>Update Manager</em> application, which I am maintaining, occasionally needs to update itself.  Immediately after the application updates itself, it restarts by way of the <code>android.intent.action.PACKAGE_REPLACED</code> broadcast, which I register for in the AndroidManifest.  However, upon restart of the application immediately after the update, I <em>occasionally</em> receive this <code>Error</code></p>
  
  <pre><code>java.lang.Error: Factory already set
      at java.net.URL.setURLStreamHandlerFactory(URL.java:112)
      at com.xxx.xxx.ApplicationRoot.&lt;clinit&gt;(ApplicationRoot.java:37)
      at java.lang.Class.newInstanceImpl(Native Method)
      at java.lang.Class.newInstance(Class.java:1208)
      at android.app.Instrumentation.newApplication(Instrumentation.java:996)
      at android.app.Instrumentation.newApplication(Instrumentation.java:981)
      at android.app.LoadedApk.makeApplication(LoadedApk.java:511)
      at android.app.ActivityThread.handleReceiver(ActivityThread.java:2625)
      at android.app.ActivityThread.access$1800(ActivityThread.java:172)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1384)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:146)
      at android.app.ActivityThread.main(ActivityThread.java:5653)
      at java.lang.reflect.Method.invokeNative(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:515)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
      at dalvik.system.NativeStart.main(Native Method)
  </code></pre>
  
  <p>Note that the majority of the time, the application restarts properly.  However, every once in a while, I get the above error.  I'm perplexed because the <em>only</em> place I call <code>setURLStreamHandlerFactory</code> is here, and it is done in a <code>static</code> block, which I presume - although correct me if I'm wrong - is only called once, when the <code>ApplicationRoot</code> class if first loaded.  However, it would seem that it is getting called <em>twice</em>, resulting in the above error.</p>
  
  <p><strong>Question:</strong></p>
  
  <p>What in the <em>blazing sams</em> is going on?  My only guess at this point is that the VM/process for the <em>updated</em> application is the same as the <em>previously installed</em> application that is being updated, so when the <code>static</code> block for the <em>new</em> <code>ApplicationRoot</code> gets called, the <code>URLStreamHandlerFactory</code> set by the <em>old</em> <code>ApplicationRoot</code> is still "active".  Is this possible?  How can I avoid this situation?  Seeing that it doesn't always happen, it seems to be a race condition of some sort; maybe within Android's APK installation routine? Thanks,</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>Additional code as requested.  Here is the manifest portion dealing with the Broadcast</p>
  
  <pre><code>&lt;receiver android:name=".OnSelfUpdate" &gt;
      &lt;intent-filter&gt;
          &lt;action android:name="android.intent.action.PACKAGE_REPLACED" /&gt;
          &lt;data android:scheme="package" /&gt;
      &lt;/intent-filter&gt;
  &lt;/receiver&gt;
  </code></pre>
  
  <p>And the <code>BroadcastReceiver</code> itself</p>
  
  <pre><code>public class OnSelfUpdate extends BroadcastReceiver {
  
      @Override
      public void onReceive(final Context context, final Intent intent) {
          /* Get the application(s) updated. */
          final int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
          final PackageManager packageManager = context.getPackageManager();
          final String[] packages = packageManager.getPackagesForUid(uid);
  
          if (packages != null) {
              final String thisPackage = context.getPackageName();
              for (final String pkg : packages) {
                  /* Check to see if this application was updated. */
                  if (pkg.equals(thisPackage)) {
                      final Intent intent = new Intent(context, MainActivity.class);
                      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                      context.startActivity(intent);
                      break;
                  }
              }
          }
      }
  
  }
  </code></pre>