How to Create an Android App From a Static Website in 10 Minutes
Pressed for time and need to make a static website quickly? Today we are going to run through a quick set up process to get you started in no time.
Join the DZone community and get the full member experience.
Join For FreeI welcome you to my first post on DZone. This one will be about creating an Android application out of a static website. Let's not waste time and start coding!
First of all, you need to create a new Android project. I don't want to go too deep into this part so if you need help on how to do this please look up Google's support site regarding android projects. After the project is done it's time to change up a few stuff. Because we are working on a game called Daggers & Sorcery, I'll use that as an example in this article. First of all, I want to make it a fullscreen app. After that, I want to add a new WebView to our main activity.
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
This WebView will hold all the app content.
After adding the WebView I created an asset folder and copied the game's assets into it. Fortunately, our game has a lot of static assets and this way the app will be able to load these assets from the assets folder instead of the web so the load of the site will be faster and we will use less bandwidth too. We were lucky enough to fully separate the static assets of the game from the backend so we can easily reuse them for the mobile app. I'll write a full article about this setup later.
After setting up the assets we can finally move into coding. I created tree methods in my main activity's onCreate method.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupGlobalCookieStorage();
setupContentContainer();
setupWebView();
}
The first method setupGlobalCookieStorage is responsible for setting up the cookie storage for our app. This is necessary because we will have a login form in the app and without proper cookie management it would not work.
private void setupGlobalCookieStorage() {
CookieManager.setAcceptFileSchemeCookies(true);
CookieManager.getInstance().setAcceptCookie(true);
}
The setAcceptFileSchemeCookies is only required when you plan on loading your static assets from file. It's disabled by default because it poses a security risk. file: URLs can reference JavaScript code and that JavaScript code could set cookies, which other file: JS code (even if from a different file) can access, due to them being considered the "same origin". This will however not going to be a problem as long as you not syncing the cookies or someone not manipulates your app.
The next method setupContentContainer is responsible for setting up the WebView as the main content in our app and transform it to be a full-screen app.
private void setupContentContainer() {
setContentView(R.layout.activity_web_view);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
The setupWebView will set up the WebView, our main component.
private void setupWebView() {
final WebView webView = locateIndexWebView();
setupWebViewCookieStorage(webView);
setupWebViewSettings(webView);
setupWebViewContent(webView);
}
private WebView locateIndexWebView() {
return (WebView) findViewById(R.id.webview);
}
private void setupWebViewCookieStorage(final WebView webView) {
if (Build.VERSION.SDK_INT >= 21) {
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
}
}
private void setupWebViewSettings(final WebView webView) {
final WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setSupportZoom(false);
}
private void setupWebViewContent(final WebView webView) {
webView.loadDataWithBaseURL("file:///android_asset/", getIndexHtml(), "text/html", "utf-8", "about:blank");
}
private String getIndexHtml() {
final InputStream is = getResources().openRawResource(R.raw.index);
try {
return IOUtils.toString(is);
} catch (IOException e) {
Log.e("IndexHtmlLoader", "Failed to load the index html.", e);
throw new RuntimeException("Failed to load the index html.");
} finally {
IOUtils.closeQuietly(is);
}
}
This is a bunch of code so let me explain. I split setupWebView into tree separate methods because it started to be a little bit confusing. I could even split this code into multiple classes but because I have never set up a DI framework in android I try to avoid this step as long as possible. (Probably I should add one after finishing this tutorial. :) )
The locateIndexWebView method will locate our WebView.
The setupWebViewCookieStorage will set up the CookieManager to accept cookies from 3rd-parties.
private void setupWebViewCookieStorage(final WebView webView) {
if (Build.VERSION.SDK_INT >= 21) {
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
}
}
This was necessary for us because our app has two domains. One used for serving the frontend assets (www.daggersandsorcery.com) while the other one is used for the backend server (api.daggersandsorcery.com). In the app, it's a little bit more difficult because the frontend domain will be replaced with file:. If your site uses one domain only you don't need to set this up. (Be careful, however! If you are using google analytics or similar scripts you will need to set setAcceptThirdPartyCookies to true otherwise they will also not going to work.)
In setupWebViewSettings, we set up the settings of the WebView.
private void setupWebViewSettings(final WebView webView) {
final WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setSupportZoom(false);
}
We do some very basic stuff like enabling javascript and the dom-storage and disabling zoom (to make it more app-like).
In setupWebViewContent we load the content of the WebView. Note that this is done after setting up everything.
private void setupWebViewContent(final WebView webView) {
webView.loadDataWithBaseURL("file:///android_asset/", getIndexHtml(), "text/html", "utf-8", "about:blank");
}
We are using loadDataWithBaseURL because we want to load our own static assets from the asset directory. You can simply use loadData if you want to load a resource/website from the internet. The first argument sets up the base URL of the rendered site. This will set up where to load all relative assets/resources. Because we added every image/js/CSS etc files to the asset directory (to lower bandwidth usage and loading speed) setting up the asset directory as a base is required. The getIndexHtml loads the content of the index HTML and places it into the second argument. If your index code is small enough you can place it directly to the java source. In our case, the index HTML is dynamically generated by webpack after every frontend update so it's bundled to the app in a file form. The other arguments are the mime type, encoding, and the history URL.
The only thing left for us now is giving permission to the app to use the internet. This can be done in the AndroidManifest.xml file by pasting an uses-permission entry into the end of the XML:
<uses-permission android:name="android.permission.INTERNET" />
If you set up everything correctly your app will render your site on startup. This setup is very good when you don't want to invest too much extra time into your mobile application and it enables to you to double your frontend productivity. Every time you will fix a mobile related thing in your website it will be fixed in your mobile app too and vice versa.
The full source code of the final application are available in my GitHub repository.
Have fun and keep coding! ;)
Published at DZone with permission of Gyula Lakatos. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Transactional Outbox Patterns Step by Step With Spring and Kotlin
-
How To Integrate Microsoft Team With Cypress Cloud
-
Structured Logging
-
Scaling Site Reliability Engineering (SRE) Teams the Right Way
Comments