com.ideateam.plugin.Version.java Source code

Java tutorial

Introduction

Here is the source code for com.ideateam.plugin.Version.java

Source

/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at
    
  http://www.apache.org/licenses/LICENSE-2.0
    
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/

package com.ideateam.plugin;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaActivity;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.os.StrictMode;
import android.util.Log;

import com.ideaintech.app.UAR2015;

/**
* This class exposes methods in Cordova that can be called from JavaScript.
*/
public class Version extends CordovaPlugin {
    public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
    public String url = "http://uart.universityathlete.com/update/android2015/";
    public String remoteVersion;
    public String urlVersion;
    public String currentVersion;
    private String remoteChecksum;
    private String updateChecksum;
    private String updateNote;
    private String zipChecksum;
    public UAR2015 activity;
    final private String TAG = "CordovaPlugin";
    private CallbackContext callbackContext;

    private ProgressDialog mProgressDialog;

    /**
    * Executes the request and returns PluginResult.
    *
    * @param action            The action to execute.
    * @param args              JSONArry of arguments for the plugin.
    * @param callbackContext   The callback context from which we were invoked.
    */
    @SuppressLint("NewApi")
    public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext)
            throws JSONException {
        this.callbackContext = callbackContext;
        if (action.equals("updateTo")) {
            remoteVersion = updateChecksum = updateNote = null;
            //args ['0.22-234','http://domain/update/android/','0WE34DEYJRYBVXR4521DSFHTRHf44r4rCDVHERG']

            getRemoteVersion();

            this.activity = (UAR2015) this.cordova.getActivity();

            if (remoteVersion == null)
                return false;
            else
                updateToVersion("");

            // FIXME succes callback  
            //  callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, args.getString(0)));
        } else if (action.equals("echo")) {
            this.activity = (UAR2015) this.cordova.getActivity();
            //if we get response try sync, else - build is not work
            if (System.currentTimeMillis() - activity.timestamp < 1000) {

                activity.sendJavascript("UART.system.Helper.syncBeforeUpdate()");

            } else {
                updateToVersion("");
            }
        } else if (action.equals("isUpdate")) {
            remoteVersion = updateChecksum = updateNote = null;
            getRemoteVersion();
            getVersion(false);
        } else if (action.equals("writeToFile")) {
            this.activity = (UAR2015) this.cordova.getActivity();
            JSONObject obj = new JSONObject(args.getString(0));

            final String fileName = obj.getString("fileName");
            final String msg = obj.getString("msg");

            if (fileName != null && fileName.length() > 0 && msg != null && msg.length() > 0) {

                cordova.getThreadPool().execute(new Runnable() {
                    public void run() {
                        writeLocaleToFile(fileName, msg);
                    }
                });
                return true;
            }

        } else {
            return false;
        }
        return true;
    }

    @Override
    public void onResume(boolean multitasking) {
        // TODO Auto-generated method stub
        super.onResume(multitasking);

        getVersion(true);

    }

    DownloadFileAsync myTask;
    Boolean isCanceled = false;

    public void updateToVersion(String urlV) {

        Log.d(TAG, "..! url Scheme: " + urlV);

        if (urlV != "") {
            remoteVersion = urlV;
        }

        activity.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                myTask = new DownloadFileAsync();
                myTask.execute(url, remoteVersion);
            }
        });

    }

    void CancelHandelr() {
        myTask.cancel(false);
        callbackContext.success("db imported");
        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "Canceled"));
    }

    class DownloadFileAsync extends AsyncTask<String, String, String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            isCanceled = false;
            mProgressDialog = new ProgressDialog(activity);
            mProgressDialog.setMessage("Downloading file...");
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.setCancelable(false);
            mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // TODO Auto-generated method stub
                            Log.d(TAG, "!!! Cancel dialog");
                            isCanceled = true;
                            mProgressDialog.dismiss();
                            CancelHandelr();
                        }
                    });
            mProgressDialog.show();

        }

        @Override
        protected String doInBackground(String... aurl) {
            int count;

            try {

                if (isCanceled == true) {
                    CancelHandelr();
                    return null;
                }

                URL url = new URL(aurl[0] + aurl[1]);

                Log.d(TAG, "..! url Scheme url: " + url);

                URLConnection conexion = url.openConnection();

                conexion.connect();

                int lenghtOfFile = conexion.getContentLength();

                if (lenghtOfFile > 0)
                    mProgressDialog.setMax(lenghtOfFile / 1024);

                InputStream input = new BufferedInputStream(url.openStream());
                FileOutputStream output = activity.openFileOutput(String.format("%s.zip", remoteVersion),
                        Context.MODE_PRIVATE);

                byte data[] = new byte[1024];

                long total = 0;

                while ((count = input.read(data)) != -1) {
                    total += count;
                    publishProgress("" + (int) (total / 1024));
                    output.write(data, 0, count);
                }

                output.flush();
                output.close();
                input.close();

            } catch (Exception e) {
            }

            return null;

        }

        protected void onProgressUpdate(String... progress) {

            mProgressDialog.setProgress(Integer.parseInt(progress[0]));
        }

        @Override
        protected void onPostExecute(String unused) {
            mProgressDialog.dismiss();

            if (isCanceled == true) {
                CancelHandelr();
                return;
            }

            UnzipUtility unzipper = new UnzipUtility();
            try {

                String zipFile = String.format("%s/%s", activity.getFilesDir(), remoteVersion);

                zipChecksum = getSHA1FromFileContent(zipFile + ".zip").toUpperCase();

                if (zipChecksum != null && remoteChecksum != null && !zipChecksum.equals(remoteChecksum)) {
                    showAlertDialogCheckSum();
                    File f = new File(zipFile + ".zip");
                    f.delete();
                    zipChecksum = null;
                    return;

                }

                unzipper.unzip(zipFile + ".zip", zipFile);
                File f = new File(zipFile + ".zip");

                reloadAppFromZip(remoteVersion);

                //f.delete();

                File[] all = activity.getFilesDir().listFiles();
                for (int i = 0; i < all.length; i++) {
                    boolean isDeleted = false;

                    if (!all[i].getName().equals(remoteVersion))
                        isDeleted = DeleteRecursive(all[i]);

                }

            } catch (Exception ex) {
                // some errors occurred
                ex.printStackTrace();
            }
        }

        private void reloadAppFromZip(String version) {
            // TODO Auto-generated method stub

            ((CordovaActivity) activity)
                    .loadUrl(String.format("file:///%s/%s/index.html", activity.getFilesDir(), version));
        }

        private boolean DeleteRecursive(File fileOrDirectory) {

            if (fileOrDirectory.isDirectory())
                for (File child : fileOrDirectory.listFiles())
                    DeleteRecursive(child);

            return fileOrDirectory.delete();
        }
    }

    public class UnzipUtility {
        /**
         * Size of the buffer to read/write data
         */
        private static final int BUFFER_SIZE = 4096;

        /**
         * Extracts a zip file specified by the zipFilePath to a directory specified by
         * destDirectory (will be created if does not exists)
         * @param zipFilePath
         * @param destDirectory
         * @throws IOException
         */
        public void unzip(String zipFilePath, String destDirectory) throws IOException {
            File destDir = new File(destDirectory);
            if (!destDir.exists()) {
                destDir.mkdir();
            }
            ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
            ZipEntry entry = zipIn.getNextEntry();
            // iterates over entries in the zip file
            while (entry != null) {
                String filePath = destDirectory + File.separator + entry.getName();
                if (!entry.isDirectory()) {
                    // if the entry is a file, extracts it
                    extractFile(zipIn, filePath);
                } else {
                    // if the entry is a directory, make the directory
                    File dir = new File(filePath);
                    dir.mkdir();
                }
                zipIn.closeEntry();
                entry = zipIn.getNextEntry();
            }
            zipIn.close();
        }

        /**
         * Extracts a zip entry (file entry)
         * @param zipIn
         * @param filePath
         * @throws IOException
         */
        private void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
            byte[] bytesIn = new byte[BUFFER_SIZE];
            int read = 0;
            while ((read = zipIn.read(bytesIn)) != -1) {
                bos.write(bytesIn, 0, read);
            }
            bos.close();
        }
    }

    private File loadFromWwwOrZip() {
        // TODO Auto-generated method stub

        File[] f = activity.getFilesDir().listFiles();

        File wwwFolder = null;

        if (f != null && f.length > 0) {

            for (int i = 0; i < f.length; i++) {
                if (wwwFolder == null && !f[i].getName().equals("Documents") && !f[i].getName().equals("rList")
                        && f[i].getName().length() < 10) {
                    wwwFolder = f[i];
                    continue;
                }

                if (wwwFolder != null && wwwFolder.lastModified() < f[i].lastModified()) {
                    wwwFolder = f[i];
                }
            }
        }
        return wwwFolder;
    }

    private String getCurrentVersionZip(File wwwFolder) {
        String version = null;

        File indexFile = new File(wwwFolder.getAbsoluteFile() + "/index.html");

        try {
            FileInputStream fin = new FileInputStream(wwwFolder.getAbsoluteFile() + "/index.html");
            BufferedReader r = new BufferedReader(new InputStreamReader(fin));

            String line;
            while ((line = r.readLine()) != null) {
                if (line.indexOf("src=\"app.js?") != -1) {
                    int start = line.indexOf("?");
                    int end = line.lastIndexOf("-");

                    version = line.substring(start + 1, end);

                    break;
                }
            }

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //   BufferedReader r = new BufferedReader(new InputStreamReader(openFileInput(wwwFolder.getName()+"/index.html") ));
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return version;
    }

    private String getCurrentVersionWWW() {
        AssetManager am = activity.getAssets();
        InputStream reader = null;
        String version = "";

        //Get version from APK's assets folder
        //zip with updates not founded 

        try {
            reader = am.open("www/index.html");
            BufferedReader r = new BufferedReader(new InputStreamReader(reader));

            String line;
            while ((line = r.readLine()) != null) {
                if (line.indexOf("src=\"app.js?") != -1) {
                    int start = line.indexOf("?");
                    int end = line.lastIndexOf("-");

                    version = line.substring(start + 1, end);

                    break;
                }
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        return version;
    }

    public static String getSHA1FromFileContent(String filename) throws NoSuchAlgorithmException, IOException {

        final MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");

        InputStream is = new BufferedInputStream(new FileInputStream(filename));
        final byte[] buffer = new byte[1024];

        for (int read = 0; (read = is.read(buffer)) != -1;) {
            messageDigest.update(buffer, 0, read);
        }

        is.close();

        // Convert the byte to hex format
        Formatter formatter = new Formatter();

        for (final byte b : messageDigest.digest()) {
            formatter.format("%02x", b);
        }

        String res = formatter.toString();

        formatter.close();

        return res;
    }

    private void showAlertDialogCheckSum() {

        new AlertDialog.Builder(activity).setTitle("Checksum does not match")
                .setMessage(
                        String.format("Waiting for SHA-1: %s\nGet Zip with SHA-1: %s", remoteChecksum, zipChecksum))
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //startDownload(baseUrl + remoteVersion);
                    }

                })
                //.setNegativeButton("Cancel", null)
                .show();
    }

    public void checkForUpdates() {

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //activity.sendJavascript("UART.system.Helper.fromNative()");
                getVersion(true);
            }
        }, 10000);

    }

    public void getVersion(Boolean isBackground) {

        if (isOnline()) {

            File zipUpdateFile = loadFromWwwOrZip();

            if (zipUpdateFile != null)
                currentVersion = getCurrentVersionZip(zipUpdateFile);
            else
                currentVersion = getCurrentVersionWWW();

            getRemoteVersion();

            if (remoteVersion != null && !currentVersion.equals(remoteVersion)) {

                ((UAR2015) activity).showConfirmDialogForUpdate(updateNote, currentVersion, remoteVersion);
            } else if (!isBackground) {
                if (remoteVersion != null)
                    ((UAR2015) activity).showConfirmDialogForUpdate("You have latest app version", null, null);
                else
                    ((UAR2015) activity).showConfirmDialogForUpdate("Can not get remote version", null, null);
            }

        } else {

        }
    }

    public boolean isOnline() {

        if (this.activity == null)
            this.activity = (UAR2015) this.cordova.getActivity();

        ConnectivityManager cm = (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnectedOrConnecting()) {
            return true;
        }
        return false;
    }

    private void getRemoteVersion() {

        try {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
            URL url = new URL(this.url + "version.txt");

            HttpURLConnection con = (HttpURLConnection) url.openConnection();

            readRemoteVersion(con.getInputStream());

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private String readRemoteVersion(InputStream in) {
        BufferedReader reader = null;
        String version = "";
        try {
            String line = "";
            reader = new BufferedReader(new InputStreamReader(in));

            while ((line = reader.readLine()) != null) {
                version += line;
            }

            version = version.replace("|", ";");
            String[] arr = version.split(";");

            if (arr.length == 3 || arr.length == 4) //fix for not free WiFi
            {
                remoteVersion = arr[0];
                updateChecksum = arr[2].toUpperCase();
                updateNote = arr[3];
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return version;
    }

    public void syncBeforeUpdate() {
        activity.timestamp = System.currentTimeMillis();
        activity.sendJavascript("UART.system.Helper.echo()");

    }

    public void writeLocaleToFile(String fileName, String msg) {

        try {
            String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/UAR2015/" + fileName;

            File file = new File(path);

            if (!file.exists()) {
                File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/UAR2015/");
                f.mkdirs();
                file.createNewFile();

            }

            BufferedWriter buf = new BufferedWriter(new FileWriter(file, true));
            buf.append(msg);
            buf.newLine();
            buf.close();
            // callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "writed to file"));
            Log.d(TAG, "..callBackPlugin");
            activity.sendJavascript("UART.system.Helper.callBackPlugin('ok')");

        } catch (IOException e) {
            Log.d(TAG, e.getMessage());
        }

    }

}