| Index: src/org/adblockplus/android/updater/AlarmReceiver.java |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/src/org/adblockplus/android/updater/AlarmReceiver.java |
| @@ -0,0 +1,190 @@ |
| +package org.adblockplus.android.updater; |
| + |
| +import java.io.IOException; |
| +import java.io.StringReader; |
| + |
| +import javax.xml.parsers.DocumentBuilder; |
| +import javax.xml.parsers.DocumentBuilderFactory; |
| +import javax.xml.parsers.ParserConfigurationException; |
| + |
| +import org.adblockplus.android.AdblockPlus; |
| +import org.adblockplus.android.R; |
| +import org.apache.http.HttpEntity; |
| +import org.apache.http.HttpResponse; |
| +import org.apache.http.client.methods.HttpGet; |
| +import org.apache.http.impl.client.DefaultHttpClient; |
| +import org.apache.http.util.EntityUtils; |
| +import org.w3c.dom.Document; |
| +import org.w3c.dom.Element; |
| +import org.w3c.dom.NodeList; |
| +import org.xml.sax.InputSource; |
| +import org.xml.sax.SAXException; |
| + |
| +import android.app.Notification; |
| +import android.app.NotificationManager; |
| +import android.app.PendingIntent; |
| +import android.content.BroadcastReceiver; |
| +import android.content.Context; |
| +import android.content.Intent; |
| +import android.content.pm.PackageManager.NameNotFoundException; |
| +import android.net.ConnectivityManager; |
| +import android.net.NetworkInfo; |
| +import android.util.Log; |
| + |
| +/** |
| + * Processes Alarm event to check for update availability. |
| + */ |
| +public class AlarmReceiver extends BroadcastReceiver |
| +{ |
| + |
| + private static final String TAG = "AlarmReceiver"; |
| + private static final int NOTIFICATION_ID = R.string.app_name + 1; |
| + |
| + @Override |
| + public void onReceive(final Context context, final Intent intent) |
| + { |
| + Log.i(TAG, "Alarm; requesting updater service"); |
| + |
| + final AdblockPlus application = AdblockPlus.getApplication(); |
| + |
| + // Indicates manual (immediate) update check which requires response to user. |
| + final boolean notify = intent.getBooleanExtra("notifynoupdate", false); |
| + |
| + // Check network availability |
| + boolean connected = false; |
| + ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); |
| + NetworkInfo networkInfo = null; |
| + if (connectivityManager != null) |
| + { |
| + networkInfo = connectivityManager.getActiveNetworkInfo(); |
| + connected = networkInfo == null ? false : networkInfo.isConnected(); |
| + } |
| + |
| + // Prepare notification |
| + final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); |
| + final Notification notification = new Notification(); |
| + notification.icon = R.drawable.ic_stat_warning; |
| + notification.when = System.currentTimeMillis(); |
| + notification.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONLY_ALERT_ONCE; |
| + if (notify) |
| + notification.flags |= Notification.DEFAULT_SOUND; |
| + final PendingIntent emptyIntent = PendingIntent.getActivity(context, 0, new Intent(), 0); |
| + |
| + // Get update info |
| + if (application.checkWriteExternalPermission() && connected) |
| + { |
| + Thread thread = new Thread(new Runnable() { |
| + @Override |
| + public void run() |
| + { |
| + boolean success = false; |
| + try |
| + { |
| + // Read updates manifest |
| + DefaultHttpClient httpClient = new DefaultHttpClient(); |
| + HttpGet httpGet = new HttpGet(context.getString(R.string.update_url)); |
| + |
| + HttpResponse httpResponse = httpClient.execute(httpGet); |
| + HttpEntity httpEntity = httpResponse.getEntity(); |
| + String xml = EntityUtils.toString(httpEntity); |
| + |
| + // Parse XML |
| + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
| + DocumentBuilder db = dbf.newDocumentBuilder(); |
| + |
| + InputSource is = new InputSource(); |
| + is.setCharacterStream(new StringReader(xml)); |
| + Document doc = db.parse(is); |
| + |
| + // Find best match |
| + NodeList nl = doc.getElementsByTagName("updatecheck"); |
| + int newBuild = -1; |
| + int newApi = -1; |
| + String newUrl = null; |
| + for (int i = 0; i < nl.getLength(); i++) |
| + { |
| + Element e = (Element) nl.item(i); |
| + String url = e.getAttribute("package"); |
| + int build = Integer.parseInt(e.getAttribute("build")); |
| + int api = Integer.parseInt(e.getAttribute("api")); |
| + if (api > android.os.Build.VERSION.SDK_INT) |
| + continue; |
| + if ((build > newBuild) || (build == newBuild && api > newApi)) |
| + { |
| + newBuild = build; |
| + newApi = api; |
| + newUrl = url; |
| + } |
| + } |
| + |
| + int thisBuild = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode; |
| + |
| + // Notify user if newer update was found |
| + if (thisBuild < newBuild) |
| + { |
| + notification.icon = R.drawable.ic_stat_download; |
| + Intent intent = new Intent(context, UpdaterActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| + intent.setAction("download"); |
| + intent.putExtra("url", newUrl); |
| + intent.putExtra("build", newBuild); |
| + PendingIntent updateIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); |
| + notification.setLatestEventInfo(context, context.getText(R.string.app_name), context.getString(R.string.msg_update_available), updateIntent); |
| + notificationManager.notify(NOTIFICATION_ID, notification); |
| + } |
| + // Notify user that no update was found |
| + else if (notify) |
| + { |
| + notification.setLatestEventInfo(context, context.getText(R.string.app_name), context.getString(R.string.msg_update_missing), emptyIntent); |
| + notificationManager.notify(NOTIFICATION_ID, notification); |
| + } |
| + success = true; |
| + // Schedule next check |
| + application.scheduleUpdater(0); |
| + } |
| + catch (IOException e) |
| + { |
| + } |
| + catch (NumberFormatException e) |
| + { |
| + } |
| + catch (NameNotFoundException e) |
| + { |
| + } |
| + catch (ParserConfigurationException e) |
| + { |
| + } |
| + catch (SAXException e) |
| + { |
| + Log.e(TAG, "Error", e); |
| + } |
| + finally |
| + { |
| + if (!success) |
| + { |
| + // Notify user about failure |
| + if (notify) |
| + { |
| + notification.setLatestEventInfo(context, context.getText(R.string.app_name), context.getString(R.string.msg_update_fail), emptyIntent); |
| + notificationManager.notify(NOTIFICATION_ID, notification); |
| + } |
| + // Schedule retry in 1 hour - this is most probably problem on server |
| + application.scheduleUpdater(60); |
| + } |
| + } |
| + } |
| + }); |
| + thread.start(); |
| + } |
| + else |
| + { |
| + // Notify user about failure |
| + if (notify) |
| + { |
| + notification.setLatestEventInfo(context, context.getText(R.string.app_name), context.getString(R.string.msg_update_fail), emptyIntent); |
| + notificationManager.notify(NOTIFICATION_ID, notification); |
| + } |
| + // Schedule retry in 30 minutes - there is no connection available at this time |
| + application.scheduleUpdater(30); |
| + } |
| + } |
| +} |