title: WebView JavaScript Interface only seems to work through the Android Studio's Instant-Run, but not when compiled through regular gradle
body: <h1>The Setup</h1>
  
  <p>I have a simple fragment that hosts a WebView component. During the initialization of this fragment, I register a few JavaScript interface methods to my app:</p>
  
  <pre><code>mJavaScriptHooks = new JavaScriptHooks();
  ...
  mWebView.getSettings().setJavaScriptEnabled(true);
  mWebView.addJavascriptInterface(mJavaScriptHooks, "Android");
  </code></pre>
  
  <p>My JavaScript hooks are nothing spectacular, and all are declared in the following manner:</p>
  
  <pre><code>public class JavaScriptHooks {
      @JavascriptInterface
      public void someMethod() {
         ...
      }
      ...
  }
  </code></pre>
  
  <p>In order to make sure that these methods are not obfuscated or optimized away into oblivion, I've added the following the my <a href="https://stackoverflow.com/questions/17629507/how-to-configure-proguard-for-javascript-interface">ProGuard configuration</a>:</p>
  
  <pre><code>-keepattributes JavascriptInterface
  -keepclassmembers class * {
      @android.webkit.JavascriptInterface &lt;methods&gt;;
  }
  </code></pre>
  
  <h1>The Problem</h1>
  
  <p><strong>Everything works as expected.</strong> The web page successfully invokes the methods through the provided "Android" object, the methods are called and perform their corresponding task. <strong>However</strong>, it only works when I run the app using the APK that was generated through the Android Studio's <a href="https://medium.com/google-developers/instant-run-how-does-it-work-294a1633367f#.fplg64q5p" rel="nofollow noreferrer">Instant-Run</a> feature.</p>
  
  <p>It doesn't matter if the APK is installed through Android Studio or if I install it through the command-line using <code>adb install</code></p>
  
  <p>If I compile my APK through regular gradle (or if I disable Instant-Run), then the JavaScript interface stops working.</p>
  
  <h1>Debugging</h1>
  
  <p>First off, I've ensured that <strong>ProGuard</strong> is <strong>disabled</strong>. Even if ProGuard was somehow ✨ magically ✨ enabled, my ProGuard configuration should ensure that my JS methods are left alone.</p>
  
  <p>I've also disassembled the APK to <strong>make sure</strong> that the methods being exposed through the JS Interface have not somehow become mangled (or removed). They're not. They seem to be present, as declared, in the DEX file.</p>
  
  <p>When I run the APK that was generated with Instant-Run enabled, I can inspect (through Chrome) that the page loaded in the WebView and see that my "Android" object is available and all the methods I've exposed are there (and invokable):</p>
  
  <pre><code>&gt; Android
  Object
      someMethod()
      __proto__
  </code></pre>
  
  <p>However, when I run the APK with Instant-Run disabled (i.e. vanilla gradle), the "Android" object is available, but none of my methods are there. It's just an empty object.</p>
  
  <pre><code>&gt; Android
  Object
      __proto__
  </code></pre>
  
  <p>The page I'm loading in WebView lives on a publicly-visible server that I control. The same page is loaded in both APK builds, and the methods are invoked in the same manner. Only the APK built with the Instant-Run feature seems to work.</p>
  
  <p>I've been digging around all day, but I couldn't find anything really helpful. Most suggestions point to a ProGuard configuration problem or to old bugs (i.e Gingerbread-era) in WebView.</p>