Check twice daily for GitHub updates

Fixes #349
This commit is contained in:
M66B 2016-02-29 10:07:04 +01:00
parent f62cb96d1f
commit 7135e241d2
3 changed files with 158 additions and 8 deletions

View File

@ -30,7 +30,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
@ -42,6 +41,7 @@ import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.TrafficStats;
import android.net.Uri;
import android.net.VpnService;
import android.os.Build;
import android.os.Handler;
@ -70,15 +70,22 @@ import android.util.Log;
import android.util.TypedValue;
import android.widget.RemoteViews;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@ -88,6 +95,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.net.ssl.HttpsURLConnection;
public class SinkholeService extends VpnService implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "NetGuard.Service";
@ -125,6 +134,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
private static final int NOTIFY_EXIT = 5;
private static final int NOTIFY_ERROR = 6;
private static final int NOTIFY_TRAFFIC = 7;
private static final int NOTIFY_UPDATE = 8;
public static final String EXTRA_COMMAND = "Command";
private static final String EXTRA_REASON = "Reason";
@ -143,7 +153,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
private enum State {none, waiting, enforcing, stats}
public enum Command {run, start, reload, stop, stats, set}
public enum Command {run, start, reload, stop, stats, set, householding}
private static volatile PowerManager.WakeLock wlInstance = null;
@ -302,7 +312,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
case reload:
reload();
cleanupDNS();
break;
case stop:
@ -318,6 +327,10 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
set(intent);
break;
case householding:
householding(intent);
break;
default:
Log.e(TAG, "Unknown command=" + cmd);
}
@ -504,6 +517,62 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
Intent ruleset = new Intent(ActivityMain.ACTION_RULES_CHANGED);
LocalBroadcastManager.getInstance(SinkholeService.this).sendBroadcast(ruleset);
}
private void householding(Intent intent) {
// Keep DNS records for a week
DatabaseHelper.getInstance(SinkholeService.this).cleanupDns(new Date().getTime() - 7 * 24 * 3600 * 1000L);
// Check for update
if (!Util.isPlayStoreInstall(SinkholeService.this))
checkUpdate();
}
private void checkUpdate() {
StringBuilder json = new StringBuilder();
HttpsURLConnection urlConnection = null;
try {
URL url = new URL("https://api.github.com/repos/M66B/NetGuard/releases/latest");
urlConnection = (HttpsURLConnection) url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line = br.readLine()) != null)
json.append(line);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
try {
JSONObject jroot = new JSONObject(json.toString());
if (jroot.has("tag_name") && jroot.has("assets")) {
JSONArray jassets = jroot.getJSONArray("assets");
if (jassets.length() > 0) {
JSONObject jasset = jassets.getJSONObject(0);
if (jasset.has("name") && jasset.has("browser_download_url")) {
String version = jroot.getString("tag_name");
String name = jasset.getString("name");
String url = jasset.getString("browser_download_url");
Log.i(TAG, "Tag " + version + " name " + name + " url " + url);
Version current = new Version(Util.getSelfVersionName(SinkholeService.this));
Version available = new Version(version);
if (current.compareTo(available) < 0) {
Log.i(TAG, "Update available from " + current + " to " + available);
showUpdateNotification(name, url);
} else
Log.i(TAG, "Up-to-date current version " + current);
}
}
}
} catch (JSONException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
}
private final class LogHandler extends Handler {
@ -1219,11 +1288,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
mapNoNotify.put(rule.info.applicationInfo.uid, true);
}
private void cleanupDNS() {
// Keep records for a week
DatabaseHelper.getInstance(SinkholeService.this).cleanupDns(new Date().getTime() - 7 * 24 * 3600 * 1000L);
}
private List<Rule> getAllowedRules(List<Rule> listRule) {
List<Rule> listAllowed = new ArrayList<>();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
@ -1655,6 +1719,14 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
ifPackage.addAction(Intent.ACTION_PACKAGE_ADDED);
ifPackage.addDataScheme("package");
registerReceiver(packageAddedReceiver, ifPackage);
// Setup house holding
Intent alarmIntent = new Intent(this, SinkholeService.class);
alarmIntent.putExtra(EXTRA_COMMAND, Command.householding);
PendingIntent pi = PendingIntent.getService(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.setInexactRepeating(AlarmManager.RTC, SystemClock.elapsedRealtime() + 60 * 1000, AlarmManager.INTERVAL_HALF_DAY, pi);
}
@Override
@ -2008,6 +2080,33 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
NotificationManagerCompat.from(this).notify(uid + 10000, notification.build());
}
private void showUpdateNotification(String name, String url) {
Intent download = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
PendingIntent pi = PendingIntent.getActivity(this, 0, download, PendingIntent.FLAG_UPDATE_CURRENT);
TypedValue tv = new TypedValue();
getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_security_white_24dp)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.msg_update))
.setContentIntent(pi)
.setColor(tv.data)
.setOngoing(false)
.setAutoCancel(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setCategory(Notification.CATEGORY_STATUS)
.setVisibility(Notification.VISIBILITY_SECRET);
}
NotificationCompat.BigTextStyle notification = new NotificationCompat.BigTextStyle(builder);
notification.bigText(getString(R.string.msg_update));
notification.setSummaryText(name);
NotificationManagerCompat.from(this).notify(NOTIFY_UPDATE, notification.build());
}
private void removeWarningNotifications() {
NotificationManagerCompat.from(this).cancel(NOTIFY_DISABLED);
NotificationManagerCompat.from(this).cancel(NOTIFY_ERROR);

View File

@ -0,0 +1,50 @@
package eu.faircode.netguard;
/*
This file is part of NetGuard.
NetGuard 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 3 of the License, or
(at your option) any later version.
NetGuard 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 NetGuard. If not, see <http://www.gnu.org/licenses/>.
Copyright 2015-2016 by Marcel Bokhorst (M66B)
*/
public class Version implements Comparable<Version> {
private String version;
public Version(String version) {
this.version = version.replace("-beta", "");
}
@Override
public int compareTo(Version other) {
String[] lhs = this.version.split("\\.");
String[] rhs = other.version.split("\\.");
int length = Math.max(lhs.length, rhs.length);
for (int i = 0; i < length; i++) {
int vLhs = (i < lhs.length ? Integer.parseInt(lhs[i]) : 0);
int vRhs = (i < rhs.length ? Integer.parseInt(rhs[i]) : 0);
if (vLhs < vRhs)
return -1;
if (vLhs > vRhs)
return 1;
}
return 0;
}
@Override
public String toString() {
return version;
}
}

View File

@ -164,6 +164,7 @@ Your internet traffic is not being sent to a remote VPN server.</string>
<string name="msg_stop_forward">Stop forwarding of %1$s port %2$d?</string>
<string name="msg_metered">Network is metered</string>
<string name="msg_queue">NetGuard is busy</string>
<string name="msg_update">Update available, tap to download</string>
<string name="title_unmetered_allowed">Unmetered traffic is allowed</string>
<string name="title_unmetered_blocked">Unmetered traffic is blocked</string>