Creare app Android nativa di un sito web – parte 3

Di | 7 gennaio 2017

In questa terza ed ultima parte del tutorial vediamo come mettere mano al codice del progetto della WebView ed adattarlo.

File AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.digitalking.webview" >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

        <service
            android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
    </application>

</manifest>

Nella parte precedente del tutorial avevamo cambiato il nome del package alla riga 3.
In questo file vengono definiti i permessi necessari all’app (riga 5 e 6). INTERNET per far funzionare il componente WebView e ACCESS_NETWORK_STATE per controllare lo stato della connessione Internet, vedremo il codice Java successivamente.
Dentro il tag application viene definita l’icona dell’app, tema, etichetta dell’app (vedi App Bar) e la dichiarazione dell’activity MainActivity, tralasciamo il servizio Firebase (che si occupa dell’invio notifiche push) non oggetto di questo tutorial.

Sotto resdrawable sono presenti le varie risorse grafiche, possiamo personalizzare l’icona di lancio ic_launcher.png utilizzando il servizio online Android Asset Studio, verranno create le icone per tutte le dimensioni ed infine scaricare lo .zip da decomprimere dentro il nostro progetto C:ProgettoAndroidWebViewappsrcmainres.
E’ presente anche il file progress_drawable.xml che permette di personalizzare la barra di progressione del caricamento della pagina web.

Sotto layout c’è il file activity_main.xml dove troviamo tutte le proprietà della webview (dimensione del layout, ecc…)

Sotto menu c’è il file menu_turn_on_server.xml dove ci sono le proprietà del menù dell’App Bar.

Sotto values troviamo i seguenti files:

– color.xml: è possibile personalizzare i colori dell’App Bar, sfondo, testo.
– dimens.xml: sono definiti i margini (padding) dell’activity della WebView.
– strings.xml: è possibile personalizzare il testo relativo al nome dell’app e del menù delle Impostazioni.
– styles.xml: viene definito lo stile, il tema dell’app.

Apriamo ora il file relativo alla classe Java MainActivity, è molto lungo.

package com.android.digitalking.webview;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {

    private WebView myWeb;
    public ProgressBar progress;
    AlertDialog.Builder builder;
    AlertDialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        setContentView(com.android.digitalking.webview.R.layout.activity_main);

        if(!isOnline()) {
            showDialog();
            return;
        }
        progress = (ProgressBar) findViewById(com.android.digitalking.webview.R.id.progressBar);
        progress.setProgress(0);

        myWeb = (WebView) findViewById(com.android.digitalking.webview.R.id.webview);
        myWeb.getSettings().setJavaScriptEnabled(true);
        myWeb.getSettings().setLoadWithOverviewMode(true);
        myWeb.getSettings().setUseWideViewPort(true);
        myWeb.getSettings().setBuiltInZoomControls(true);
        myWeb.getSettings().setDisplayZoomControls(false);
        myWeb.setWebViewClient(new WebClient());
        myWeb.loadUrl("http://google.com");

        myWeb.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                progress.setProgress(newProgress);
            }
        });


    }

    private boolean isOnline()
    {
        ConnectivityManager cm =
                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null &&
                activeNetwork.isConnectedOrConnecting();
    }

   public class WebClient extends WebViewClient{

        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String url) {

            webView.loadUrl(url);
            return true;
        }

       @Override
       public void onPageStarted(WebView view, String url, Bitmap favicon) {
           progress.setVisibility(View.VISIBLE);
           super.onPageStarted(view, url, favicon);
       }

       @Override
       public void onPageFinished(WebView view, String url) {
           progress.setVisibility(View.GONE);
           super.onPageFinished(view, url);
       }
   }


    @Override
    public void onBackPressed() {

        if (myWeb.canGoBack())
        {
            myWeb.goBack();
        }
        else
        {
            DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    switch (which){
                        case DialogInterface.BUTTON_POSITIVE:
                            //Yes button clicked
                            finish();
                            break;

                        case DialogInterface.BUTTON_NEGATIVE:
                            //No button clicked

                            break;
                    }
                }
            };
            builder = new AlertDialog.Builder(this);
            builder.setPositiveButton("Yes", dialogClickListener).setTitle("Are you sure?").setIcon(com.android.digitalking.webview.R.drawable.icon1)
                    .setNegativeButton("No", dialogClickListener).show();
        }

    }

    private void showDialog()
    {
        dialog = new AlertDialog.Builder(this).create();
        dialog.setTitle("Check your internet settings");
        dialog.setMessage("Please make sure internet is turned on and click refresh");
        dialog.setIcon(com.android.digitalking.webview.R.drawable.connection_error);
        dialog.setButton(AlertDialog.BUTTON_POSITIVE,"Refresh", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // Write your code here to execute after dialog closed
               refresh();
            }
        });
        dialog.show();
    }

    public void refresh() {
        if (!isOnline()) showDialog();
        else {
            dialog.dismiss();
            recreate();
        }
    }
}

Probabilmente Android Studio segnalerà un warning alla riga 25 dicendo di utilizzare AppCompatActivity, questo perché ActionBarActivity risulta deprecato.
E’ sufficiente sostituire ActionBarActivity con AppCompatActivity, AndroidStudio darà errore: cannot resolve symbol appcompatactivity.
Questo perché occorre aggiungere una nuova riga sulle import (espandere la riga 3 in Android Studio):

import android.support.v7.app.AppCompatActivity;

Alla riga 55 scriviamo l’indirizzo web che vogliamo venga caricato.

Alle righe 125-126 è possibile personalizzare il testo dell’alert con i bottoni per uscire dall’applicazione quando viene premuto il tasto indietro (se l’app non può tornare più indietro nelle pagine navigate).

Alle righe 134-135 è possibile personalizzare il testo dell’alert relativo alla connessione Internet.

Infatti se non ci fosse il codice che controlla lo stato della connessione Internet (righe 67-74) anziché visualizzare il messaggio di alert vi ritroverete con la pagina di errore come quando cercate di aprire un indirizzo internet tramite browser e non si è connessi

Proviamo ora la nostra applicazione.
Compiliamo per verificare che non ci siano errori (Build -> Rebuild project).
Quindi dalla toolbar di Android Studio premiamo il simbolo di Run oppure dal menù Run o premendo Maiusc+F10.
Nella finestra successiva Select Deployment Target è possibile configurare un nuovo dispositivo virtuale (ne avevamo accennato nella prima parte del tutorial) oppure far girare l’app in un dispositivo connesso.
Ecco come si presenta l’app con la homepage di DigiTalking caricata:

Terminate tutte le modifiche che vogliamo (icone, testi delle finestre di dialogo degli alert, App Bar, colori) possiamo generare l’APK (Build -> Build APK).
Troverete l’APK pronto per essere installato in C:ProgettoAndroidWebViewappbuildoutputsapk con il nome app-debug.apk (perché l’applicazione è stata compilata in modalità Debug).
Per compilare in modalità Release deve essere configurata la build variant nel file build.gradle relativo a Module:app, quindi dal menù Build -> Select Build Variant, infine generare l’APK.

Iscriviti al gruppo Telegram Italian Spaghetti Geeks

https://t.me/ItalianSpaghettiGeeks

Novità tecnologiche, giveaways esclusivi prodotti tech e molto altro ancora!

Rispondi

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.