Commits

Michael Knight  committed d0018aa Merge

Merge branch 'background-service'

  • Participants
  • Parent commits c8dcd16, e9c3f6e
  • Tags 0.2

Comments (0)

Files changed (4)

File AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.miknight.bameter"
-    android:versionCode="1"
-    android:versionName="0.1" >
+    android:versionCode="2"
+    android:versionName="0.2" >
 
     <uses-sdk android:minSdkVersion="15" />
 
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <service
+            android:name=".BameterService"
+            android:exported="false"
+            android:icon="@drawable/icon"
+            android:label="@string/app_name"
+            android:process=":background_process" >
+            <intent-filter>
+                <action android:name=".BameterService" />
+            </intent-filter>
+        </service>
     </application>
 
-</manifest>
+</manifest>

File res/values/strings.xml

 
     <string name="app_name">BaMeter</string>
     <string name="hello">Bandwidth meter:</string>
-    <string name="placeholder">Error: Unable to detect bandwidth.</string>
+    <string name="placeholder">Detecting bandwidth&#8230;</string>
     <string name="instructions">Stats will continue to be reported as an ongoing notification while you use your device. Exit the application to clear the notification. (Open this app to bring it back.)</string>
     <string name="exit_button">Exit</string>
 
-</resources>
+</resources>

File src/com/miknight/bameter/BameterActivity.java

 package com.miknight.bameter;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
 import android.app.Activity;
-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.res.Resources;
+import android.content.IntentFilter;
 import android.os.Bundle;
-import android.os.Handler;
 import android.view.View;
 import android.widget.TextView;
 
 public class BameterActivity extends Activity {
 
 	private TextView ptext;
-	private Handler handler;
-	private long downloaded = 0, uploaded = 0;
 
-	/** Called when the activity is first created. */
+	private BroadcastReceiver networkStatsReceiver = new BroadcastReceiver() {
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			String message = intent.getStringExtra("message");
+			setMeterText(message);
+		}
+	};
+
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
 		super.onCreate(savedInstanceState);
 		setContentView(R.layout.main);
-		handler = new Handler();
-		startRepeatingTask();
+		Intent start = new Intent(".BameterService");
+		this.startService(start);
 	}
 
-	private void generateNotification(String txt) {
-		Resources res = getResources();
-		int icon = R.drawable.notify_icon;
-		String appName = res.getString(R.string.app_name);
-
-		Context context = getApplicationContext();
-		String ns = Context.NOTIFICATION_SERVICE;
-
-		Intent notificationIntent = new Intent(context, BameterActivity.class);
-		PendingIntent contentIntent = PendingIntent.getActivity(context, 1,
-				notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
-
-		NotificationManager nm = (NotificationManager) getSystemService(ns);
-		Notification notification = new Notification.Builder(context)
-				.setContentTitle(appName).setContentText(txt)
-				.setContentIntent(contentIntent).setOngoing(true)
-				.setSmallIcon(icon).getNotification();
-
-		nm.notify(1, notification);
-	}
-
-	Runnable pingRunner = new Runnable() {
-		public void run() {
-			pingNetworkStats("eth0");
-			handler.postDelayed(pingRunner, 1000);
-		}
-	};
-
-	void startRepeatingTask() {
-		pingRunner.run();
-	}
-
-	void stopRepeatingTask() {
-		handler.removeCallbacks(pingRunner);
+	@Override
+	protected void onResume() {
+		super.onResume();
+		registerReceiver(networkStatsReceiver, new IntentFilter("ping-network-stats"));
 	}
 
-	private void pingNetworkStats(String device) {
-		Process p;
-		String downloadOutput = "";
-		String uploadOutput = "";
-		String debug = "";
-		long newDownloaded = 0;
-		long newUploaded = 0;
-		try {
-			p = Runtime.getRuntime().exec("cat /proc/net/dev");
-			BufferedReader istream = new BufferedReader(new InputStreamReader(
-					p.getInputStream()));
-			String line;
-			while ((line = istream.readLine()) != null) {
-				debug += line + "\n";
-				line = line.trim();
-				// if (line.matches(".*" + device + ":.*") ||
-				// line.matches(".*rmnet0.*")) {
-				// Collect I/O from all devices.
-				// TODO: Exclude loopback.
-				if (line.matches("^[a-z0-9]+:.*") && !line.matches("^lo:.*")) {
-					downloadOutput = line.split("\\s+")[1];
-					uploadOutput = line.split("\\s+")[9];
-					newDownloaded += Long.parseLong(downloadOutput);
-					newUploaded += Long.parseLong(uploadOutput);
-				}
-			}
-		} catch (IOException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-			return;
-		}
-		String output = "";
-		if (downloaded == 0) {
-			downloaded = newDownloaded;
-		}
-		if (uploaded == 0) {
-			uploaded = newUploaded;
-		}
-		if (downloadOutput.isEmpty() || uploadOutput.isEmpty()) {
-			output = debug;
-		} else {
-			long d_diff = (newDownloaded - downloaded);
-			long u_diff = (newUploaded - uploaded);
-			output = d_diff / 1024 + " KB/s down,\n" + u_diff / 1024
-					+ " KB/s up.\n";
-			downloaded = newDownloaded;
-			uploaded = newUploaded;
-		}
-		setMeterText(output);
-		generateNotification(output);
+	@Override
+	protected void onPause() {
+		unregisterReceiver(networkStatsReceiver);
+		super.onPause();
 	}
 
 	private void setMeterText(String s) {
 	}
 
 	public void exitApplication(View view) {
-		NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
-		nm.cancelAll();
+		// Stop background service.
+		Intent stop = new Intent(".BameterService");
+		this.stopService(stop);
+		// Return to the home screen.
 		Intent startMain = new Intent(Intent.ACTION_MAIN);
 		startMain.addCategory(Intent.CATEGORY_HOME);
 		startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 		startActivity(startMain);
+		// Destroy this activity.
 		this.finish();
 		android.os.Process.killProcess(android.os.Process.myPid());
-		// System.exit(0);
 	}
 }

File src/com/miknight/bameter/BameterService.java

+package com.miknight.bameter;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.IBinder;
+
+public class BameterService extends Service {
+
+	private boolean isRunning = true;
+	private long downloaded = 0, uploaded = 0;
+	private Thread backgroundThread = null;
+
+	@Override
+	public IBinder onBind(Intent intent) {
+		return null;
+	}
+
+	@Override
+	public void onCreate() {
+		super.onCreate();
+	}
+
+	@Override
+	// This is run every time startService() is called on it, even if it's already running.
+	public int onStartCommand(Intent intent, int flags, int startId) {
+		super.onStartCommand(intent, flags, startId);
+		if (backgroundThread == null || !backgroundThread.isAlive()) {
+			backgroundThread = new Thread(new BackgroundThread());
+			backgroundThread.start();
+			isRunning = true;
+		}
+		return START_STICKY;
+	}
+
+	@Override
+	public void onDestroy() {
+		super.onDestroy();
+		// Clear notification.
+		NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+		nm.cancelAll();
+		isRunning = false;
+	}
+
+	private void generateNotification(String txt) {
+		Resources res = getResources();
+		int icon = R.drawable.notify_icon;
+		String appName = res.getString(R.string.app_name);
+
+		Context context = getApplicationContext();
+		String ns = Context.NOTIFICATION_SERVICE;
+
+		Intent notificationIntent = new Intent(context, BameterActivity.class);
+		PendingIntent contentIntent = PendingIntent.getActivity(context, 1,
+				notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+		NotificationManager nm = (NotificationManager) getSystemService(ns);
+		Notification notification = new Notification.Builder(context)
+				.setContentTitle(appName).setContentText(txt)
+				.setContentIntent(contentIntent).setOngoing(true)
+				.setSmallIcon(icon).getNotification();
+
+		nm.notify(1, notification);
+	}
+
+	private void pingNetworkStats(String device) {
+		Process p;
+		String downloadOutput = "";
+		String uploadOutput = "";
+		String debug = "";
+		long newDownloaded = 0;
+		long newUploaded = 0;
+		try {
+			p = Runtime.getRuntime().exec("cat /proc/net/dev");
+			BufferedReader istream = new BufferedReader(new InputStreamReader(
+					p.getInputStream()));
+			String line;
+			while ((line = istream.readLine()) != null) {
+				debug += line + "\n";
+				line = line.trim();
+				// Collect I/O from all devices.
+				if (line.matches("^[a-z0-9]+:.*") && !line.matches("^lo:.*")) {
+					downloadOutput = line.split("\\s+")[1];
+					uploadOutput = line.split("\\s+")[9];
+					newDownloaded += Long.parseLong(downloadOutput);
+					newUploaded += Long.parseLong(uploadOutput);
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			return;
+		}
+		String output = "";
+		if (downloaded == 0) {
+			downloaded = newDownloaded;
+		}
+		if (uploaded == 0) {
+			uploaded = newUploaded;
+		}
+		if (downloadOutput.isEmpty() || uploadOutput.isEmpty()) {
+			output = debug;
+		} else {
+			long d_diff = (newDownloaded - downloaded);
+			long u_diff = (newUploaded - uploaded);
+			output = d_diff / 1024 + " KB/s down,\n" + u_diff / 1024
+					+ " KB/s up.\n";
+			downloaded = newDownloaded;
+			uploaded = newUploaded;
+		}
+		Intent intent = new Intent("ping-network-stats");
+		intent.putExtra("message", output);
+		sendBroadcast(intent);
+		generateNotification(output);
+	}
+
+	private class BackgroundThread implements Runnable {
+		public void run() {
+			try {
+				while (isRunning) {
+					pingNetworkStats("eth0");
+					Thread.sleep(1000);
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+	}
+}