Java tutorial
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */ /* * Copyright 2012 by Eric House (xwords@eehouse.org). All rights * reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package com.oliversride.wordryo; import java.io.File; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONObject; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.os.AsyncTask; import android.os.SystemClock; public class UpdateCheckReceiver extends BroadcastReceiver { public static final String NEW_DICT_URL = "NEW_DICT_URL"; public static final String NEW_DICT_LOC = "NEW_DICT_LOC"; // weekly private static final long INTERVAL_ONEDAY = 1000 * 60 * 60 * 24; private static final long INTERVAL_NDAYS = 7; // constants that are also used in info.py private static final String k_NAME = "name"; private static final String k_AVERS = "avers"; private static final String k_GVERS = "gvers"; private static final String k_INSTALLER = "installer"; private static final String k_DEVOK = "devOK"; private static final String k_APP = "app"; private static final String k_DICTS = "dicts"; private static final String k_LANG = "lang"; private static final String k_MD5SUM = "md5sum"; private static final String k_INDEX = "index"; private static final String k_URL = "url"; private static final String k_PARAMS = "params"; private static final String k_DEVID = "did"; @Override public void onReceive(Context context, Intent intent) { if (null != intent && null != intent.getAction() && intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { restartTimer(context); } else { checkVersions(context, false); restartTimer(context); } } public static void restartTimer(Context context) { AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, UpdateCheckReceiver.class); PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0); am.cancel(pi); long interval_millis = INTERVAL_ONEDAY; if (!devOK(context)) { interval_millis *= INTERVAL_NDAYS; } interval_millis = (interval_millis / 2) + Math.abs(Utils.nextRandomInt() % interval_millis); am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + interval_millis, interval_millis, pi); } public static void checkVersions(Context context, boolean fromUI) { JSONObject params = new JSONObject(); PackageManager pm = context.getPackageManager(); String packageName = context.getPackageName(); String installer = pm.getInstallerPackageName(packageName); if ("com.google.android.feedback".equals(installer) || "com.android.vending".equals(installer)) { // Do nothing; it's a Market app } else { try { int versionCode = pm.getPackageInfo(packageName, 0).versionCode; JSONObject appParams = new JSONObject(); appParams.put(k_NAME, packageName); appParams.put(k_AVERS, versionCode); appParams.put(k_GVERS, GitVersion.VERS); appParams.put(k_INSTALLER, installer); if (devOK(context)) { appParams.put(k_DEVOK, true); } params.put(k_APP, appParams); params.put(k_DEVID, XWPrefs.getDevID(context)); } catch (PackageManager.NameNotFoundException nnfe) { DbgUtils.loge(nnfe); } catch (org.json.JSONException jse) { DbgUtils.loge(jse); } } JSONArray dictParams = new JSONArray(); DictUtils.DictAndLoc[] dals = DictUtils.dictList(context); for (int ii = 0; ii < dals.length; ++ii) { DictUtils.DictAndLoc dal = dals[ii]; switch (dal.loc) { // case DOWNLOAD: case EXTERNAL: case INTERNAL: dictParams.put(makeDictParams(context, dal, ii)); } } if (0 < dictParams.length()) { try { params.put(k_DICTS, dictParams); params.put(k_DEVID, XWPrefs.getDevID(context)); } catch (org.json.JSONException jse) { DbgUtils.loge(jse); } } if (0 < params.length()) { new UpdateQueryTask(context, params, fromUI, pm, packageName, dals).execute(); } } private static HttpPost makePost(Context context, String proc) { String url = String.format("%s/%s", XWPrefs.getDefaultUpdateUrl(context), proc); return new HttpPost(url); } private static String runPost(HttpPost post, JSONObject params) { String result = null; try { String jsonStr = params.toString(); List<NameValuePair> nvp = new ArrayList<NameValuePair>(); nvp.add(new BasicNameValuePair(k_PARAMS, jsonStr)); post.setEntity(new UrlEncodedFormEntity(nvp)); // Execute HTTP Post Request HttpClient httpclient = new DefaultHttpClient(); HttpResponse response = httpclient.execute(post); HttpEntity entity = response.getEntity(); if (null != entity) { result = EntityUtils.toString(entity); if (0 == result.length()) { result = null; } } } catch (java.io.UnsupportedEncodingException uee) { DbgUtils.loge(uee); } catch (java.io.IOException ioe) { DbgUtils.loge(ioe); } return result; } private static JSONObject makeDictParams(Context context, DictUtils.DictAndLoc dal, int index) { JSONObject params = new JSONObject(); int lang = DictLangCache.getDictLangCode(context, dal); String langStr = DictLangCache.getLangName(context, lang); String sum = DictLangCache.getDictMD5Sum(context, dal.name); try { params.put(k_NAME, dal.name); params.put(k_LANG, langStr); params.put(k_MD5SUM, sum); params.put(k_INDEX, index); } catch (org.json.JSONException jse) { DbgUtils.loge(jse); } return params; } private static boolean devOK(Context context) { return XWPrefs.getPrefsBoolean(context, R.string.key_update_prerel, false); } private static class UpdateQueryTask extends AsyncTask<Void, Void, String> { private Context m_context; private JSONObject m_params; private boolean m_fromUI; private PackageManager m_pm; private String m_packageName; private DictUtils.DictAndLoc[] m_dals; public UpdateQueryTask(Context context, JSONObject params, boolean fromUI, PackageManager pm, String packageName, DictUtils.DictAndLoc[] dals) { m_context = context; m_params = params; m_fromUI = fromUI; m_pm = pm; m_packageName = packageName; m_dals = dals; } @Override protected String doInBackground(Void... unused) { HttpPost post = makePost(m_context, "getUpdates"); String json = runPost(post, m_params); return json; } @Override protected void onPostExecute(String json) { if (null != json) { makeNotificationsIf(json); } } private void makeNotificationsIf(String jstr) { boolean gotOne = false; try { JSONObject jobj = new JSONObject(jstr); if (null != jobj) { if (jobj.has(k_APP)) { JSONObject app = jobj.getJSONObject(k_APP); if (app.has(k_URL)) { ApplicationInfo ai = m_pm.getApplicationInfo(m_packageName, 0); String label = m_pm.getApplicationLabel(ai).toString(); // If there's a download dir AND an installer // app, handle this ourselves. Otherwise just // launch the browser boolean useBrowser; File downloads = DictUtils.getDownloadDir(m_context); if (null == downloads) { useBrowser = true; } else { File tmp = new File(downloads, "xx" + XWConstants.APK_EXTN); useBrowser = !Utils.canInstall(m_context, tmp); } Intent intent; String url = app.getString(k_URL); if (useBrowser) { intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); } else { intent = DictImportActivity.makeAppDownloadIntent(m_context, url); } String title = Utils.format(m_context, R.string.new_app_availf, label); String body = m_context.getString(R.string.new_app_avail); Utils.postNotification(m_context, intent, title, body, url.hashCode()); gotOne = true; } } if (jobj.has(k_DICTS)) { JSONArray dicts = jobj.getJSONArray(k_DICTS); for (int ii = 0; ii < dicts.length(); ++ii) { JSONObject dict = dicts.getJSONObject(ii); if (dict.has(k_URL) && dict.has(k_INDEX)) { String url = dict.getString(k_URL); int index = dict.getInt(k_INDEX); DictUtils.DictAndLoc dal = m_dals[index]; Intent intent = new Intent(m_context, DictsActivity.class); intent.putExtra(NEW_DICT_URL, url); intent.putExtra(NEW_DICT_LOC, dal.loc.ordinal()); String body = Utils.format(m_context, R.string.new_dict_availf, dal.name); Utils.postNotification(m_context, intent, R.string.new_dict_avail, body, url.hashCode()); gotOne = true; } } } } } catch (org.json.JSONException jse) { DbgUtils.loge(jse); } catch (PackageManager.NameNotFoundException nnfe) { DbgUtils.loge(nnfe); } if (!gotOne && m_fromUI) { Utils.showToast(m_context, R.string.checkupdates_none_found); } } } }