From 6d8a143adc28c7b9c1434b117f21c147667e4f26 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Thu, 31 Jan 2013 17:45:21 +0100 Subject: Allow finer control of notification messages --- src/de/blinkt/openvpn/OpenVPN.java | 53 ++++++++--- src/de/blinkt/openvpn/OpenVpnManagementThread.java | 16 +--- src/de/blinkt/openvpn/OpenVpnService.java | 104 +++++++++++++++------ 3 files changed, 117 insertions(+), 56 deletions(-) (limited to 'src/de') diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index 8d6cb4c8..9cfaf1e8 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -15,18 +15,23 @@ public class OpenVPN { private static Vector logListener; private static Vector stateListener; + private static Vector byteCountListener; + private static String[] mBconfig; - private static String mLaststatemsg; + private static String mLaststatemsg=""; - private static String mLaststate; + private static String mLaststate = "NOPROCESS"; private static int mLastStateresid=R.string.state_noprocess; + + private static long mlastByteCount[]={0,0,0,0}; static { logbuffer = new LinkedList(); logListener = new Vector(); stateListener = new Vector(); + byteCountListener = new Vector(); logInformation(); } @@ -83,7 +88,7 @@ public class OpenVPN { String str = String.format(Locale.ENGLISH,"Log (no context) resid %d", mRessourceId); if(mArgs !=null) for(Object o:mArgs) - str += "|" + o.toString(); + str += "|" + o.toString(); return str; } } @@ -107,6 +112,10 @@ public class OpenVPN { public interface StateListener { void updateState(String state, String logmessage, int localizedResId); } + + public interface ByteCountListener { + void updateByteCount(long in, long out, long diffin, long diffout); + } synchronized static void logMessage(int level,String prefix, String message) { @@ -131,14 +140,25 @@ public class OpenVPN { public synchronized static void removeLogListener(LogListener ll) { logListener.remove(ll); } + + public static void addByteCountListener(ByteCountListener bcl) { + bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]); + byteCountListener.add(bcl); + } + + public static void removeByteCountListener(ByteCountListener bcl) { + byteCountListener.remove(bcl); + } public synchronized static void addStateListener(StateListener sl){ - stateListener.add(sl); - if(mLaststate!=null) - sl.updateState(mLaststate, mLaststatemsg, mLastStateresid); + if(!stateListener.contains(sl)){ + stateListener.add(sl); + if(mLaststate!=null) + sl.updateState(mLaststate, mLaststatemsg, mLastStateresid); + } } - + private static int getLocalizedState(String state){ if (state.equals("CONNECTING")) return R.string.state_connecting; @@ -199,12 +219,10 @@ public class OpenVPN { } public synchronized static void updateStateString(String state, String msg, int resid) { - if (! "BYTECOUNT".equals(state)) { - mLaststate= state; - mLaststatemsg = msg; - mLastStateresid = resid; - } - + mLaststate= state; + mLaststatemsg = msg; + mLastStateresid = resid; + for (StateListener sl : stateListener) { sl.updateState(state,msg,resid); } @@ -240,4 +258,13 @@ public class OpenVPN { newlogItem(new LogItem(LogItem.ERROR, ressourceId,args)); } + public static void updateByteCount(long in, long out, long diffin, long diffout) { + mlastByteCount = new long[] {in,out,diffin,diffout}; + for(ByteCountListener bcl:byteCountListener){ + bcl.updateByteCount(in, out, diffin,diffout); + } + } + + + } diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index 3d68d943..dd3708cf 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -290,24 +290,12 @@ public class OpenVpnManagementThread implements Runnable { mLastIn=in; mLastOut=out; - String netstat = String.format("In: %8s, %8s/s Out %8s, %8s/s", - humanReadableByteCount(in, false), - humanReadableByteCount(diffin, false), - humanReadableByteCount(out, false), - humanReadableByteCount(diffout, false)); - OpenVPN.updateStateString("BYTECOUNT",netstat); + OpenVPN.updateByteCount(in,out,diffin, diffout); } - // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java - public static String humanReadableByteCount(long bytes, boolean si) { - int unit = si ? 1000 : 1024; - if (bytes < unit) return bytes + " B"; - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i"); - return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); - } + private void processNeedCommand(String argument) { int p1 =argument.indexOf('\''); diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java index 53ae80b1..0ac57406 100644 --- a/src/de/blinkt/openvpn/OpenVpnService.java +++ b/src/de/blinkt/openvpn/OpenVpnService.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package de.blinkt.openvpn; - -import java.io.IOException; +package de.blinkt.openvpn;import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Vector; @@ -34,16 +32,19 @@ import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.net.VpnService; import android.os.Binder; -import android.os.Handler; -import android.os.Handler.Callback; import android.os.Build; +import android.os.Handler.Callback; import android.os.IBinder; import android.os.Message; import android.os.ParcelFileDescriptor; + import de.blinkt.openvpn.OpenVPN.StateListener; public class OpenVpnService extends VpnService implements StateListener, Callback { public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE"; + public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY"; + public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE"; + private Thread mProcessThread=null; @@ -76,15 +77,22 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac public static final int PROTECT_FD = 0; + + private static final int LEVEL_OFFLINE = 0; + private static final int LEVEL_NOTCONNECTED = 1; + private static final int LEVEL_CONNECTED = 2; + + private static boolean mNotificationalwaysVisible=false; + private final IBinder mBinder = new LocalBinder(); - + public class LocalBinder extends Binder { public OpenVpnService getService() { - // Return this instance of LocalService so clients can call public methods - return OpenVpnService.this; - } - } - + // Return this instance of LocalService so clients can call public methods + return OpenVpnService.this; + } + } + @Override public IBinder onBind(Intent intent) { String action = intent.getAction(); @@ -93,7 +101,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac else return super.onBind(intent); } - + @Override public void onRevoke() { OpenVpnManagementThread.stopOpenVPN(); @@ -115,27 +123,31 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac } } - private void showNotification(String msg, String tickerText, boolean lowpriority, long when) { + private void showNotification(String msg, String tickerText, boolean lowpriority, long when, int level) { String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); - int icon = R.drawable.ic_stat_vpn; + int icon = R.drawable.notification_icon; android.app.Notification.Builder nbuilder = new Notification.Builder(this); - nbuilder.setContentTitle(getString(R.string.notifcation_title,mProfile.mName)); + if(mProfile!=null) + nbuilder.setContentTitle(getString(R.string.notifcation_title,mProfile.mName)); + else + nbuilder.setContentTitle(getString(R.string.notifcation_title_notconnect)); + nbuilder.setContentText(msg); nbuilder.setOnlyAlertOnce(true); nbuilder.setOngoing(true); nbuilder.setContentIntent(getLogPendingIntent()); - nbuilder.setSmallIcon(icon); + nbuilder.setSmallIcon(icon,level); if(when !=0) nbuilder.setWhen(when); // Try to set the priority available since API 16 (Jellybean) jbNotificationExtras(lowpriority, nbuilder); - if(tickerText!=null) + if(tickerText!=null && !tickerText.equals("")) nbuilder.setTicker(tickerText); @SuppressWarnings("deprecation") @@ -220,11 +232,19 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac @Override - public int onStartCommand(Intent intent, int flags, int startId) { - + public int onStartCommand(Intent intent, int flags, int startId) { + + if(intent != null && intent.getBooleanExtra(ALWAYS_SHOW_NOTIFICATION, false)) + mNotificationalwaysVisible=true; + + OpenVPN.addStateListener(this); + if(intent != null && intent.getAction() !=null &&intent.getAction().equals(START_SERVICE)) return START_NOT_STICKY; - + if(intent != null && intent.getAction() !=null &&intent.getAction().equals(START_SERVICE_STICKY)) { + return START_REDELIVER_INTENT; + } + // Extract information from the intent. String prefix = getPackageName(); @@ -234,10 +254,9 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac mProfile = ProfileManager.get(profileUUID); - showNotification("Starting VPN " + mProfile.mName,"Starting VPN " + mProfile.mName, false,0); + showNotification("Starting VPN " + mProfile.mName,"Starting VPN " + mProfile.mName, false,0,LEVEL_NOTCONNECTED); - OpenVPN.addStateListener(this); // Set a flag that we are starting a new VPN mStarting=true; @@ -469,20 +488,23 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac public void updateState(String state,String logmessage, int resid) { // If the process is not running, ignore any state, // Notification should be invisible in this state - if(mProcessThread==null) + if(mProcessThread==null && !mNotificationalwaysVisible) return; // Display byte count only after being connected - if("BYTECOUNT".equals(state)) { - if(mDisplayBytecount) { - showNotification(logmessage,null,true,mConnecttime); - } - } else { + { + int level; if("CONNECTED".equals(state)) { mDisplayBytecount = true; mConnecttime = System.currentTimeMillis(); + level = LEVEL_CONNECTED; } else { + if ("NONETWORK".equals(state)) { + level = LEVEL_OFFLINE; + } else { + level = LEVEL_NOTCONNECTED; + } mDisplayBytecount = false; } @@ -490,11 +512,35 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac // This also mean we are no longer connected, ignore bytecount messages until next // CONNECTED String ticker = getString(resid); - showNotification(getString(resid) +" " + logmessage,ticker,false,0); + showNotification(getString(resid) +" " + logmessage,ticker,false,0, level); } } + + public void updateByteCount(long in, long out, long diffin, long diffout) { + if(mDisplayBytecount) { + String netstat = String.format(getString(R.string.statusline_bytecount), + humanReadableByteCount(in, false), + humanReadableByteCount(diffin, false), + humanReadableByteCount(out, false), + humanReadableByteCount(diffout, false)); + + boolean lowpriority = !mNotificationalwaysVisible; + showNotification(netstat,null,lowpriority,mConnecttime, LEVEL_CONNECTED); + } + + } + + // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java + public static String humanReadableByteCount(long bytes, boolean si) { + int unit = si ? 1000 : 1024; + if (bytes < unit) return bytes + " B"; + int exp = (int) (Math.log(bytes) / Math.log(unit)); + String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i"); + return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); + } + @Override public boolean handleMessage(Message msg) { Runnable r = msg.getCallback(); -- cgit v1.2.3