    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Simple Android programming with WebKit</title>
        <link>https://members.accu.org/index.php/journals/2078</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">CVu Journal Vol 27, #1 - March 2015 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c347/">271</a>
                    (11)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c347-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c347+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Simple Android programming with WebKit</h1>
<p><strong>Author:</strong>&nbsp;Martin Moene</p>
<p>
<strong>Date:</strong> 05 March 2015 21:06:26 +00:00 or Thu, 05 March 2015 21:06:26 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Silas S. Brown shares his trials with developing for mobile devices.</p>
<p><strong>Body:</strong>&nbsp;<p>I donâ€™t like modern smartphones. It seems the manufacturers are trying to trick people into thinking that the lack of real buttons is some kind of progress, as a lame excuse for their having become too lazy to make keyboards. Nowadays if you want a keyboard you are expected to buy it as a separate add-on and perform a juggling act on the streets.</p>

<p>Iâ€™m still waiting for the great keyboard revival, but meanwhile other people are asking me to develop for touch devices and I reluctantly bought a Sony Xperia Z Ultra for a project. Much to my annoyance, within one month of purchase it started registering false screen-presses by detecting moisture from my breath: they obviously didnâ€™t realise people with limited eyesight might hold it close.  And needless to say I can hardly type on the thing (an application called â€˜Hackerâ€™s Keyboardâ€™ with its good Dvorak layout helped a bit, but itâ€™s still not as good as a real keyboard); the pocket Bluetooth keyboard I ordered never turned up.</p>

<p>Anyway, the canonical way to program these things is to download the Android Developer Tools (ADT) <a href="#[1]">[1]</a>.  The Eclipse-based ADT is a bit â€“ how should I put this? â€“ â€˜wobblyâ€™.  Not every version installs OK.  One version I downloaded ended up not being able to create new projects (well, it could create new projects, but the empty project wouldnâ€™t build, although it could still open projects created with an earlier version of ADT).  Sometimes when using ADT you have to wait for it to finish its background operations before itâ€™ll do what you want without errors, because the code thatâ€™s supposed to do this automatically doesnâ€™t always work.  Sometimes there are other timing-related bugs, so you generally have to act nice and slowly as if not to confuse the poor computer.  Sometimes you have to press F5 on the Package Explorer to force a refresh, although thatâ€™s supposed to happen by itself when necessary but it doesnâ€™t always work.  And every version of the ADT is different, so if I tell you what to do in one version then the instructions likely wonâ€™t work in another.  Bring back the command line!</p>

<p>If you do manage to create a project that builds, Iâ€™d suggest the first thing you should do is to create a WebView and write some HTML for it.  That way you can get an application up and running quite quickly.  The HTML can include Javascript that calls back into the Java code (and, as it turns out, C code: more on this later), or you could just write a Javascript-based Web application and use ADT to package it into an â€˜appâ€™ as a convenience for offline use (but please donâ€™t write an app that just browses an online site with no additional functionality: apps like that are generally annoying, as users tend to think â€˜I can browse the web myself thank you very muchâ€™; to justify a dedicated app, it either has to include its own offline content or else apply some kind of offline processing to the pages it retrieves so itâ€™s not just a poor imitation of the general Web browser).</p>

<p>The projectâ€™s <span class="filename">res/layout/activity_main.xml</span> file should look like Listing 1, and the code itself should be something like Listing 2.  Then you can place the HTML into the <span class="filename">assets</span> folder, the main file being <span class="filename">index.html</span>: I would suggest making it â€˜mobile friendlyâ€™ as in Listing 3.  Then refresh the ADT (highlight the Package Explorer and press F5), wait, and try it out with Run / Run As / Android application.  ADT will use a real device if connected, otherwise it will start an emulator, and either way, if it works, youâ€™ll be left with an APK file in the <span class="filename">bin</span> directory which you can distribute to others if they have â€˜Unknown sourcesâ€™ enabled in their â€˜Application settingsâ€™ or â€˜Securityâ€™.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout
   xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
   android:layout_height=&quot;fill_parent&quot;
   android:layout_width=&quot;fill_parent&quot;
   android:orientation=&quot;vertical&quot;&gt;
  &lt;TextView
    android:layout_height=&quot;wrap_content&quot;
    android:layout_width=&quot;fill_parent&quot; /&gt;
  &lt;WebView
    android:id=&quot;@+id/browser&quot;
    android:layout_height=&quot;fill_parent&quot;
    android:layout_width=&quot;fill_parent&quot; /&gt;
&lt;/LinearLayout&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
import android.webkit.WebView;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
  WebView browser;
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    browser = (WebView)findViewById(R.id.browser);
    browser.getSettings().setJavaScriptEnabled(true);
    int size=Math.round(16*getResources().getConfiguration()
                 .fontScale);
    browser.getSettings().setDefaultFontSize(size);
    browser.getSettings().setDefaultFixedFontSize(size);
    browser.getSettings().setDefaultTextEncodingName(&quot;utf-8&quot;);
    browser.loadUrl(&quot;file:///android_asset/index.html&quot;);
  }
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
&lt;html&gt;
  &lt;head&gt;
    &lt;meta name=&quot;mobileoptimized&quot; content=&quot;0&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width&quot;&gt;
  &lt;/head&gt;
  &lt;body&gt;
    You should not have to zoom in to see this.
  &lt;/body&gt;
&lt;/html&gt;
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 3</td>
	</tr>
</table>

<p>Notice Listing 2 has three â€˜sizeâ€™ lines to set the font size according to the systemâ€™s font size setting.  Iâ€™m putting this in â€˜right off the batâ€™ because I believe getting it right is important (some people need big print, and, if you donâ€™t, you probably will when youâ€™re older).  Itâ€™s a pity Google didnâ€™t make this the default behaviour with their WebView component.</p>

<p>There are quite a few things missing from our application: the Back button wonâ€™t work, â€˜pinch to zoomâ€™ wonâ€™t work, Javascript alerts wonâ€™t work, local storage wonâ€™t work, the page state is reset when you rotate your device, and there is so far no way to specify that certain links should open in the â€˜realâ€™ browser rather than our app.  All of these can be fixed by adding more code to â€˜switch things onâ€™, and it gets tedious, so if youâ€™re interested Iâ€™ll refer you to my â€˜html2apkâ€™ code <a href="#[2]">[2]</a>, which addresses all of these issues and also adds a Javascript object for clipboard interaction.</p>

<h2>Adding Java and C functionality</h2>

<p>You can provide extra Javascript objects implemented in Java by writing something like Listing 4.  Then you can call these from the Javascript in your web pages, e.g. <code>document.write(myObject.test('hi'));</code></p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
class MyObject {
  public MyObject() {}
  @android.webkit.JavascriptInterface
  public String test(String in) {
    return &quot;You called test with &quot;+in;
  }
}
browser.addJavascriptInterface(new MyObject(),
                              &quot;myObject&quot;);
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 4</td>
	</tr>
</table>


<p>To write in C, youâ€™ll additionally need to download the Android NDK (Native Development Kit?) <a href="#[3]">[3]</a>.  Youâ€™ll then need a JNI directory, containing an <span class="filename">Android.mk</span> file like Listing 5:</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
LOCAL_PATH:= $(call my-dir)
LOCAL_SRC_FILES := my_program.c
LOCAL_MODULE := MyProgram
LOCAL_MODULE_FILENAME := MyProgram
include $(BUILD_SHARED_LIBRARY)
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 5</td>
	</tr>
</table>

<p>and an <span class="filename">Application.mk</span> file like this:</p>

<pre class="programlisting">
  APP_PLATFORM := android-1
  APP_ABI := armeabi</pre>
  
<p>Then your <span class="filename">my_program.c</span> should start with <code>#include &lt;jni.h&gt;</code> and should incorporate functions like Listing 6.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
JNIEXPORT jstring JNICALL
Java_your_package_name_here_MainActivity_jniMyFunc
  (JNIEnv *env, jclass theClass, jstring jIn) {
    char *i=(char*)(*env)-&gt;GetStringUTFChars(env,jIn,NULL);
    char *o=malloc(strlen(s) + 20);
    // TODO: check o != NULL
    strcpy(o, &quot;You wrote &quot;);
    strcat(o, i);
    (*env)-&gt;ReleaseStringUTFChars(env,jIn,startPtr);
    jstring ret=(*env)-&gt;NewStringUTF(env,o);
    free(o); return ret;
}		
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 6</td>
	</tr>
</table>

<p>Then back in <span class="filename">MainActivity.java</span> youâ€™ll need something like this to make your C function available to Java:</p>
  
<pre class="programlisting">
  static { System.loadLibrary(&quot;MyProgram&quot;); }
  static synchronized native String jniMyFunc
    (String in);</pre>

<p>After that, you can make it available to your Javascript by changing Listing 4 to call your newly-available C function.  Iâ€™d suggest not bothering with C on Android unless you have either a lot of existing C code or a dire need for speed: Java or even JavaScript is enough for most simple purposes and involves less setup on this platform.</p>

<h2>Publishing</h2>

<p>When youâ€™re ready to ship your â€˜appâ€™ (I tend to use the full word â€˜applicationâ€™, but these 4-syllable words are hard I know) on the so-called â€˜Play Storeâ€™ (are we all children now? are all Android versions named after sweets as a childish rebellion against some other company using healthy fruit?), youâ€™ll have to use File / Export / Export Android Application (it lets you create a keystore and private signing key), then pay for your Play Store account (I really think it should be free to upload if youâ€™re doing the platform a favour by contributing a completely free and no-adverts app for the benefit of the community, but at least the payment is only a one-off; Apple have a higher payment and they make you renew every year, which is why they wonâ€™t be getting any iOS apps off me anytime soon), and finally upload the APK and wait for it to be published on the Store.  You could just skip all this and have your users download the APK file from your own site with â€˜Unknown Sourcesâ€™ enabled, and you might wish to do it this way for a private app that you donâ€™t want the entire public to see, but having your app on the Play Store is a significant convenience for many users.</p>

<p>When uploading future versions, youâ€™ll need to increase the version number in the <span class="filename">AndroidManifest.xml</span> file (otherwise Play Store wonâ€™t accept it), and Iâ€™d suggest mirroring that change in the second copy of AndroidManifest thatâ€™s in the <span class="filename">bin</span> directory (the mirroring is supposed to be automatic, but due to general â€˜wobblinessâ€™ it seems that doesnâ€™t always happen).  Iâ€™d also suggest using the Play Store â€˜beta testâ€™ facility just to double-check your app did not somehow get corrupted during the upload process as one of mine did.  I donâ€™t see how, as theyâ€™re cryptographically signed, but somehow an app which worked perfectly well for me didnâ€™t work after my friend had uploaded it to his account on the Store: the Javascript-to-Java callback wouldnâ€™t run.  By that time we had over 1000 users, most of whom had automatic updates enabled on their devices, so I got several phone calls, making me feel like Star Trekâ€™s engineer Scottie having to fix the engines quickly before the ship explodes, and all I did was to increase the version number one more time and ask my friend to re-upload, after which the problem mysteriously disappeared.  But not before several users had turned off automatic updates on their devices (which is a worry: I hope their devices will still get the security-critical updates).  After that we decided, no matter how well an APK file works for us, weâ€™ll always use the Play Storeâ€™s own Beta Test facility to double-check nothing bad somehow happened during the upload process.  I still donâ€™t know what happened (do Google servers introduce bit-flips sometimes?) â€“ everything about this platform seems to be â€˜wobblyâ€™.  Please donâ€™t run anything safety critical on it.</p>

<h2>References:</h2>

<p class="bibliomixed"><a id="[1]"></a>[1]	<a href="http://developer.android.com/sdk/">http://developer.android.com/sdk/</a></p>

<p class="bibliomixed"><a id="[2]"></a>[2]	<a href="http://people.ds.cam.ac.uk/ssb22/gradint/html2apk.html">http://people.ds.cam.ac.uk/ssb22/gradint/html2apk.html</a></p>

<p class="bibliomixed"><a href="https://developer.android.com/tools/sdk/ndk/">[3] https://developer.android.com/tools/sdk/ndk/</a><a id="[3]"></a></p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
