Java tutorial
/* * Copyright 2013 Inderjit Gill * * Licensed 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 io.indy.drone.service; import android.app.IntentService; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; import de.greenrobot.event.EventBus; import io.indy.drone.AppConfig; import io.indy.drone.R; import io.indy.drone.activity.StrikeDetailActivity; import io.indy.drone.activity.StrikeListActivity; import io.indy.drone.event.UpdatedDatabaseEvent; import io.indy.drone.model.SQLDatabase; import io.indy.drone.model.Strike; import io.indy.drone.utils.DateFormatHelper; public class ScheduledService extends IntentService { private static final String TAG = "ScheduledService"; private static final boolean D = true; static void ifd(final String message) { if (AppConfig.DEBUG && D) Log.d(TAG, message); } public static final String PREFS_FILENAME = "MyPrefsFile"; public static final String ALARM_SET_AT = "alarm_set_at"; private final String SERVER_URL = "http://indy.io/drone/cache/"; private SQLDatabase mDatabase; public ScheduledService() { super("ScheduledService"); } @Override protected void onHandleIntent(Intent intent) { ifd("onHandleIntent"); boolean isPullToRefresh = intent.getBooleanExtra(StrikeListActivity.ResponseReceiver.IS_PTR, false); if (isPullToRefresh) { ifd("invoked service via pull to refresh"); } mDatabase = new SQLDatabase(this); // called by a repeating alarm so update sharedpreferences with the current time updateAlarmTime(); try { int serverCount = fetchStrikesCount(); int localCount = mDatabase.getNumStrikes(); if (localCount == 0) { ifd("localCount == 0"); return; } if (localCount < serverCount) { // there's new strike data in the server ifd("new strike data found on server"); JSONArray jsonStrikes = fetchNewStrikes(localCount); if (jsonStrikes == null) { ifd("fetching new strike data returned null"); return; } ifd("adding strike data to local db"); addStrikes(jsonStrikes); // event to inform list that new strike data is in the db EventBus.getDefault().post(new UpdatedDatabaseEvent()); // create a notification if (!isPullToRefresh) { createNotification(); } } else { ifd("serverCount (" + serverCount + ") not greater than localCount (" + localCount + ")"); } if (isPullToRefresh) { Intent broadcastIntent = new Intent(); broadcastIntent.setAction(StrikeListActivity.ResponseReceiver.ACTION_RESP); broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); int diff = serverCount - localCount; broadcastIntent.putExtra(StrikeListActivity.ResponseReceiver.STRIKE_DIFF, diff); sendBroadcast(broadcastIntent); } } catch (Exception e) { e.printStackTrace(); } } private void updateAlarmTime() { Context ctx = getApplicationContext(); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(ctx); Date today = new Date(); SharedPreferences.Editor editor = settings.edit(); editor.putString(ScheduledService.ALARM_SET_AT, DateFormatHelper.dateToSQLite(today)); editor.commit(); } private String httpGet(String path) throws IOException { BufferedReader reader = null; try { URL url = new URL(path); HttpURLConnection c = (HttpURLConnection) url.openConnection(); c.setRequestMethod("GET"); c.setReadTimeout(15000); c.connect(); reader = new BufferedReader(new InputStreamReader(c.getInputStream())); StringBuilder buf = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { buf.append(line + "\n"); } return buf.toString(); } finally { if (reader != null) { reader.close(); } } } private int fetchStrikesCount() throws Exception { try { String data = httpGet(SERVER_URL + "/strikes-count.json"); return Integer.parseInt(data.replaceAll("\\s+", "")); // strip whitespace } catch (IOException e) { e.printStackTrace(); throw (e); } catch (NumberFormatException e) { e.printStackTrace(); throw (e); } } private JSONArray fetchNewStrikes(int localCount) { final String STRIKE = "strike"; try { String url = SERVER_URL + "/strikes-id-" + localCount + ".json"; String data = httpGet(url); JSONObject json = new JSONObject(data); // TODO: check that status == "OK" return json.getJSONArray(STRIKE); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return null; } private void addStrikes(JSONArray jsonStrikes) { try { int len = jsonStrikes.length(); Strike strike; // list will show newest strikes first, // so populate the db in newest->oldest order for (int i = len - 1; i >= 0; i--) { strike = Strike.fromJson(jsonStrikes.getJSONObject(i)); mDatabase.addStrike(strike); } } catch (JSONException e) { e.printStackTrace(); } } public void createNotification() { // get the id of the latest strike String region = SQLDatabase.regionFromIndex(0); // worldwide String id = mDatabase.getRecentStrikeIdInRegion(region); Strike strike = mDatabase.getStrike(id); String title = getString(R.string.notification_preface) + " " + strike.getCountry(); String droneSummary = strike.getDroneSummary(); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_notification).setContentTitle(title).setContentText(droneSummary) .setAutoCancel(true); // Creates an explicit intent for an Activity in your app Intent resultIntent = new Intent(this, StrikeDetailActivity.class); resultIntent.putExtra(SQLDatabase.KEY_ID, id); resultIntent.putExtra(SQLDatabase.REGION, region); // The stack builder object will contain an artificial back stack for the // started Activity. // This ensures that navigating backward from the Activity leads out of // your application to the Home screen. TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); // Adds the back stack for the Intent (but not the Intent itself) stackBuilder.addParentStack(StrikeDetailActivity.class); // Adds the Intent that starts the Activity to the top of the stack stackBuilder.addNextIntent(resultIntent); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); bigTextStyle.setBigContentTitle(title); bigTextStyle.bigText(strike.getBijSummaryShort()); bigTextStyle.setSummaryText(droneSummary); // Moves the big view style object into the notification object. mBuilder.setStyle(bigTextStyle); } mBuilder.setContentIntent(resultPendingIntent); NotificationManager mNotificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE); // mId allows you to update the notification later on. mNotificationManager.notify(33, mBuilder.build()); } }