android APP version detection and upgrade

Keywords: Session Android xml JSON

1. This time, the server uses HTTP Servlet to return json data

First, build a Java Web project and create a Servlet class. The code is implemented in doGet

/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		// response.getWriter().append("Served at:
		// ").append(request.getContextPath());	
		HttpSession session = request.getSession();
		String str = request.getParameter("function");
		if (str == null) {
			str = "main";
		}
		// Judge whether the session is newly created to reduce the frequency of reading xml
		if (session.isNew()) {
			//System.out.println("session created successfully, session id is:" + session.getId());
		} else {
			//System.out.println("the server already has the session, and the session id is:" + session.getId());
			String function = session.getAttribute("function").toString();
			//Judge whether the functions are consistent
			if (function.equals(str)) {
				String data = session.getAttribute("data").toString();
				response.setCharacterEncoding("utf-8");
				response.getWriter().append(data);
				return;
			}			
		}
		session.setAttribute("function", str.toString());
		if (str != null && str.equals("Your APP alias")) {//function represents your APP, supports multiple APP version updates, and puts them in different xml
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = null;
			try {
				db = dbf.newDocumentBuilder();
			} catch (ParserConfigurationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			String path = this.getServletContext().getRealPath("version2.xml");
			File file = new File(path);
			InputStream is = new FileInputStream(file);

			org.w3c.dom.Document doc = null;
			try {
				doc = db.parse(is);
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			Element elem = ((org.w3c.dom.Document) doc).getDocumentElement();
			JSONObject jsonObjectRoot = new JSONObject();
			NodeList appversion = elem.getChildNodes();
			if (appversion != null) {
				JSONObject jsonObjectUpdate = new JSONObject();
				int n = 0;// Update entries
				for (int i = 0; i < appversion.getLength(); i++) {
					Node app = appversion.item(i);
					for (Node node = app.getFirstChild(); node != null; node = node.getNextSibling()) {
						if (app.getNodeName().equals("version")) {
							String ver = app.getFirstChild().getNodeValue();
							jsonObjectRoot.put("version", ver);
						}
						if (app.getNodeName().equals("date")) {
							String da = app.getFirstChild().getNodeValue();
							jsonObjectRoot.put("date", da);
						}
						if (app.getNodeName().equals("update")) {
							n++;
							String ud = app.getFirstChild().getNodeValue();
							jsonObjectUpdate.put(n + "", ud);
						}
						if (app.getNodeName().equals("address")) {
							String addr = app.getFirstChild().getNodeValue();
							jsonObjectRoot.put("address", addr);
						}
					}
				}
				jsonObjectRoot.put("update", jsonObjectUpdate);
			}
			response.setCharacterEncoding("utf-8");
			response.getWriter().append(jsonObjectRoot.toString());
			session.setAttribute("data", jsonObjectRoot.toString());
		} else {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = null;
			try {
				db = dbf.newDocumentBuilder();
			} catch (ParserConfigurationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			String path = this.getServletContext().getRealPath("version.xml");
			File file = new File(path);
			InputStream is = new FileInputStream(file);

			org.w3c.dom.Document doc = null;
			try {
				doc = db.parse(is);
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			Element elem = ((org.w3c.dom.Document) doc).getDocumentElement();
			JSONObject jsonObjectRoot = new JSONObject();
			NodeList appversion = elem.getChildNodes();
			if (appversion != null) {
				JSONObject jsonObjectUpdate = new JSONObject();
				int n = 0;// Update entries
				for (int i = 0; i < appversion.getLength(); i++) {
					Node app = appversion.item(i);
					for (Node node = app.getFirstChild(); node != null; node = node.getNextSibling()) {
						if (app.getNodeName().equals("version")) {
							String ver = app.getFirstChild().getNodeValue();
							jsonObjectRoot.put("version", ver);
						}
						if (app.getNodeName().equals("date")) {
							String da = app.getFirstChild().getNodeValue();
							jsonObjectRoot.put("date", da);
						}
						if (app.getNodeName().equals("update")) {
							n++;
							String ud = app.getFirstChild().getNodeValue();
							jsonObjectUpdate.put(n + "", ud);
						}
						if (app.getNodeName().equals("address")) {
							String addr = app.getFirstChild().getNodeValue();
							jsonObjectRoot.put("address", addr);
						}
					}
				}
				jsonObjectRoot.put("update", jsonObjectUpdate);
			}
			response.setCharacterEncoding("utf-8");
			response.getWriter().append(jsonObjectRoot.toString());
			session.setAttribute("data", jsonObjectRoot.toString());
		}
	}
Put the XML file in the WebContent directory and define the structure by yourself. For example, my version.xml is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<appupdate>
	<title>XX system</title>
	<version>1.1.0</version>
	<date>2018.02.04</date>
	<update>1:XXX optimization</update>
	<update>2:XXX modify</update>
	<update>3:XXX increase</update>
	<update>4:XXX Other</update>	
	<address>http://1.1.1.1: 8888 / download / yourapp. APK < / address > <! -- download address of your updated APP -- >
</appupdate>
You can put the APP download address in a virtual download directory of tamcat server, search tomcat to build a file download server, which is very simple to configure.

In this way, you can access the address http://1.1.1.1:8888/YourWebName/YourServletName?function = your APP alias to get a json string, for example, my following:
{"version":"1.1.0","date":"2018.02.04","address":"http://1.1.1.1:8888/download/YourApp.apk","update":{"1":"1:XXX optimization", "2":"2:XXX modification", "3":"3:XXX increase", "4":"4:XXX others"}}}}
Now that the web server has been completed, write android

2. android client 1. Create a version update class, as follows
public class AppVersion extends AsyncTask<String, integer, StringBuffer> {
    private Handler handle;

    public String getVersion() {
        return version;
    }

    private String version = "";

    public String getUpdate() {
        return update;
    }

    private String update = "";

    private String updateURL = "";

    static private String updateAPKname = "";

    static public String getAPKname() {
        return updateAPKname;
    }
    private boolean bAuto = true;

    public AppVersion(Handler handle, boolean bAuto/*Automatically check for updates, manually check for updates*/) {
        this.handle = handle;
        this.bAuto = bAuto;
    }

    @Override
    protected StringBuffer doInBackground(String... params) {
        String html = "";
        try {
            //HTTP GET request
            URL url = null;
            url = new URL(params[0]);        
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(2000);
            conn.setReadTimeout(1000);
            InputStream inStream = conn.getInputStream();
            byte[] data = readInputStream(inStream);
            html = new String(data, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new StringBuffer(html);
    }

    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        inStream.close();
        return outStream.toByteArray();
    }

    @Override
    protected void onPostExecute(StringBuffer result) {
        String Html = new String(result);
        if (!Html.equals("")) {
            try {
                JSONObject jsonObjectRoot = new JSONObject(Html);
                version = jsonObjectRoot.getString("version");
                JSONObject jsonObjectUpdate = jsonObjectRoot.getJSONObject("update");
                Iterator<String> keys = jsonObjectUpdate.keys();
                while (keys.hasNext()) {
                    String key = (String) keys.next();
                    update = update + jsonObjectUpdate.getString(key) + "\r\n\r\n";
                }
                updateURL = jsonObjectRoot.getString("address");
                updateAPKname = updateURL.substring(updateURL.lastIndexOf("/") + 1);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            handle.sendEmptyMessage(4);
        } else {
            if (!bAuto)
                Toast.makeText(SearchApplication.getInstance(), "Unable to get update, please check whether the network is unblocked", Toast.LENGTH_LONG).show();
        }
        super.onPostExecute(result);
    }

    public String getUpdateURL() {
        return updateURL;
    }

    public boolean isbAuto() {
        return bAuto;
    }

    public void setbAuto(boolean bAuto) {
        this.bAuto = bAuto;
    }
}
Two. Call in the onCreate method of MainActivity.

     

private String path = "http://1.1.1.1:8888/YourWebName/YourServletName?function = your APP alias ";
private AppVersion appVersion
private MyHandler myHandler;
appVersion = new AppVersion(myHandler, true);
appVersion.execute(path);
public class MyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {              
            case 4://Query update return
                try {
                    if (compareVersion(appVersion.getVersion(), getVersion()) > 0) {
                        //After obtaining the last version, if the server version > the current version, the update content will only be prompted once, and then it will be displayed in the menu once
                        String csTipUpdate = sp.getString(Constant.csTipUpdate, "0");//Get whether prompted
                        //Display update pop-up if not prompted or manually updated
                        if (csTipUpdate.equals("0") || !appVersion.isbAuto()) {
                            showUpdateDialog(true);//Show updated pop ups
                            sp.edit().putString(Constant.csTipUpdate, "1").apply();
                        }
                        bUpdate = true;//Menu flag bit
                        btnDowloadMap.setImageResource(R.mipmap.set1);
                    } else {
                        Log.d("version:", "No updated version!");
                        sp.edit().putString(Constant.csTipUpdate, "0").apply();
                        //After obtaining the last version, if it is inconsistent with the current version, the updated content will be displayed
                        String csVersion = sp.getString(Constant.csVersion, "");
                        if (csVersion.equals("") || !csVersion.equals(appVersion.getVersion())) {
                            showUpdateDialog(false);//show contents
                        }
                        sp.edit().putString(Constant.csVersion, appVersion.getVersion()).apply();
                        if (!appVersion.isbAuto())
                            Toast.makeText(MainActivity.this, "No updates available", Toast.LENGTH_LONG).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;  
            case 8://Download progress
            double percent = queryDownloadStatus();
            if (progressBar_download != null)
                progressBar_download.setProgress((int) percent);
            if (percent >= 100)
                progressBar_download.setVisibility(View.INVISIBLE);
            break;          
        }
    }
}
/**
* Compare the size of version number. If the former is large, it will return a positive number; if the latter is large, it will return a negative number; if it is equal, it will return 0
*
* @param version1
* @param version2
*/
public static int compareVersion(String version1, String version2) throws Exception {
    if (version1 == null || version2 == null) {
        throw new Exception("compareVersion error:illegal params.");
    }
    String[] versionArray1 = version1.split("\\.");//Note that this is a regular match and cannot be used;
    String[] versionArray2 = version2.split("\\.");
    int idx = 0;
    int minLength = Math.min(versionArray1.length, versionArray2.length);//Take the minimum length value
    int diff = 0;
    while (idx < minLength
            && (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0//Compare length first
            && (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {//Compare characters again
        ++idx;
    }
    //If the size has been allocated, it will be returned directly. If the size has not been allocated, then the number of digits will be compared again. If there is a sub version, it will be larger;
    diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length;
    return diff;
}
 
/**
* Author:
* CreateTime: 2017/11/15 11:09
* Comment: Get software version number
* Param:
*/
public String getVersion() {
    try {
        PackageManager manager = this.getPackageManager();
        PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
        String version = info.versionName;
        return version;
    } catch (Exception e) {
        String s = e.toString();
        e.printStackTrace();
        return "";
    }
}

3, android download APK installation

private DownloadManager downloadManager;//Download management class
private long lastDownloadId;
/**
* Author: 
* CreateTime: 2018/1/3 15:39
* Comment: update windows
* Param:
*/

private void showUpdateDialog(boolean b) {
    if (b) {
        LayoutInflater inflater = LayoutInflater.from(this);
        View layout = inflater.inflate(R.layout.pop_needupdate, null);//Resource file is not posted
        final Dialog dialog = new Dialog(MainActivity.this, R.style.dialogstyle);
        TextView tv = (TextView) layout.findViewById(R.id.tvupdate);//File controls for displaying content
        final TextView tvdownload = (TextView) layout.findViewById(R.id.btn_download);//Download button
        TextView tvclose = (TextView) layout.findViewById(R.id.btn_close);//Pop up close button
        tvclose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        tvdownload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                Uri uri = Uri.parse(appVersion.getUpdateURL());//Update the APK URL obtained by the class
                DownloadManager.Request request = new DownloadManager.Request(uri);
                request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
                request.setVisibleInDownloadsUi(false);
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
                File rootFile = new File(Environment.getExternalStorageDirectory().getPath() + "/YourAPP/download/");//Create a download directory
                if (!rootFile.exists()) {
                    rootFile.mkdirs();
                }
                request.setDestinationInExternalPublicDir("/YourAPP/download/", getAPKname());//Set download path
                lastDownloadId = downloadManager.enqueue(request);
                app.setLastDownloadId(lastDownloadId);
                progressBar_download.setVisibility(View.VISIBLE);//Download progress bar on pop-up window
                tvdownload.setText("Downloading");
                tvdownload.setClickable(false);
                final Timer timer = new Timer();
                TimerTask task = new TimerTask() {
                    @Override
                    public void run() {
                        double percent = queryDownloadStatus();
                        myHandler.sendEmptyMessage(8);
                        if (percent >= 100) {
                            timer.cancel();
                        }
                    }
                };
                timer.schedule(task, 100, 500);
            }
        });
        progressBar_download = (CustomLoading) layout.findViewById(R.id.progressBar_download);
        String update = appVersion.getUpdate();
        tv.setText(update);
        dialog.setCancelable(false);
        dialog.setContentView(layout);
        dialog.show();

        Window window = dialog.getWindow();
        WindowManager manager = window.getWindowManager();
        Display d = manager.getDefaultDisplay();
        WindowManager.LayoutParams params = window.getAttributes();
        params.width = (int) (d.getWidth() * 0.4);
        params.height = LinearLayout.LayoutParams.WRAP_CONTENT;
        dialog.getWindow().setAttributes(params);
    } else {
        LayoutInflater inflater = LayoutInflater.from(this);
        View layout = inflater.inflate(R.layout.pop_update, null);//After the update, the software enters the pop-up window to display the updated content for the first time
        final Dialog dialog = new Dialog(MainActivity.this, R.style.dialogstyle);
        TextView tv = (TextView) layout.findViewById(R.id.tvupdate);
        String update = appVersion.getUpdate();
        tv.setText(update);
        dialog.setCancelable(true);
        dialog.setContentView(layout);
        dialog.show();
        Window window = dialog.getWindow();
        WindowManager manager = window.getWindowManager();
        Display d = manager.getDefaultDisplay();
        WindowManager.LayoutParams params = window.getAttributes();
        params.width = (int) (d.getWidth() * 0.4);
        params.height = LinearLayout.LayoutParams.WRAP_CONTENT;
        dialog.getWindow().setAttributes(params);
    }
}
//Add code to your Application
public static YourApplication app;

private long lastDownloadId;

public static YourApplication getInstance() {
    return app;
}

public long getLastDownloadId() {
    return lastDownloadId;
}

public void setLastDownloadId(long lastDownloadId) {
    this.lastDownloadId = lastDownloadId;
}
//Query download progress
private int queryDownloadStatus() {
    DownloadManager.Query query = new DownloadManager.Query();
    query.setFilterById(lastDownloadId);
    Cursor c = downloadManager.query(query);
    if (c != null && c.moveToFirst()) {
        int fileSizeIdx = c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
        int bytesDLIdx = c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
        int fileSize = c.getInt(fileSizeIdx);
        int bytesDL = c.getInt(bytesDLIdx);
        double percent = bytesDL * 100.0 / fileSize;
        return (int) percent;
    }
    return 0;
}
4, Join a broadcast and install it after downloading
Add the following code to Android manifest.xml

<! -- other network permissions will not be posted if they are not displayed in the notice bar when downloading updates -- >
    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />

    </application>
        <receiver android:name=".BroadcastReceiver.CompleteReceiver">
            <intent-filter>
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            </intent-filter>
        </receiver>
    </application>
Broadcasting class

public class CompleteReceiver extends BroadcastReceiver {

    private DownloadManager downloadManager;
    private long downloadId;

    @Override
    public void onReceive(Context context, Intent intent) {

        String action = intent.getAction();
        if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
            downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            installApk(context, downloadId);
        }
    }

    private void installApk(Context context, long downloadId) {
        DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        if (app.getLastDownloadId() == downloadId) {
            Uri downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId);
            if (getAPKname() != null && !getAPKname().equals("")) {
                try {
                    if (downloadFileUri != null) {
                        Intent install = new Intent(Intent.ACTION_VIEW);
                        install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
                        install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(install);
                    }
                } catch (Exception e) {
                    Toast.makeText(context, "install APP Problems arise", Toast.LENGTH_LONG).show();
                }
            } else {
                Toast.makeText(context, "install APP Problems arise", Toast.LENGTH_LONG).show();
            }
        }
    }
}
OK, it's over here. I've been learning Android for several months. Sorry for any mistakes!

Posted by chiefrokka on Fri, 17 Apr 2020 09:01:40 -0700