Removed usage data sharing

This commit is contained in:
M66B 2016-07-19 07:10:07 +02:00
parent 33881b92f1
commit 58c5750599
33 changed files with 19 additions and 592 deletions

27
FAQ.md
View File

@ -363,33 +363,6 @@ On most devices, NetGuard will keep running in the background with its foregroun
On some devices (in particular some Samsung models), where there are lots of applications competing for memory, Android may still stop NetGuard as a last resort.
Unfortunately this cannot be fixed from NetGuard, and can be considered a shortcoming of the device and/or as a bug in Android.
<a name="FAQ39"></a>
**(39) Which usage data will be shared?**
On Android version 5.0 or newer, NetGuard will share anonymized usage data to help improve how NetGuard protects you,
by understanding how end users work with NetGuard.
The following data will be shared when changing application settings:
* The [SHA256](https://en.wikipedia.org/wiki/SHA-2) hashed [Android ID](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID) (needed to prevent multiple records of the same setting)
* The [device name](https://developer.android.com/reference/android/os/Build.html#DEVICE) *
* The [Android version](https://developer.android.com/reference/android/os/Build.VERSION_CODES.html) *
* The [country](https://developer.android.com/reference/java/util/Locale.html#getCountry()) configured when initializing Android *
* The application name, version and [installer](https://developer.android.com/reference/android/content/pm/PackageManager.html#getInstallerPackageName(java.lang.String)) and whether an application is a user installed or a system bundled application
* Whether Wi-Fi and mobile connections will be blocked or allowed and which conditions apply (when screen on, roaming, notify on access, addresses, etc)
This data cannot be used to identify you, so your privacy is guaranteed.
Data marked with an asterix (*) is being shared by Google in the [Google Play developer console](https://developer.android.com/distribute/googleplay/developer-console.html) as well.
Usage data will be queued for sending over an unmetered connection (mostly Wi-Fi) when settings are being changed.
Usage data will be anonynized before sending.
Sending usage data can optionally be disabled per application.
You can see the aggregated data [here](https://crowd.netguard.me).
<br />
**If you didn't find the answer to your question, you can ask your questions [in this forum](http://forum.xda-developers.com/showthread.php?t=3233012) or contact me directly [by e-mail](mailto:marcel+netguard@faircode.eu)**.
If you want to request a new feature or want to report a bug, please [create an issue on GitHub](https://github.com/M66B/NetGuard/issues/new).

View File

@ -16,7 +16,8 @@ Features:
* Simple to use
* No root required
* 100% open source
* No tracking and user profiling
* No calling home
* No tracking or analytics
* No advertisements
* Actively developed and supported
* Android 4.0 and later supported
@ -183,9 +184,6 @@ Frequently Asked Questions (FAQ)
<a name="FAQ38"></a>
[**(38) Why did NetGuard stop running?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ38)
<a name="FAQ39"></a>
[**(39) Which usage data will be shared?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ39)
Permissions
-----------

View File

@ -104,14 +104,6 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/renderscript" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/renderscript" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
@ -120,6 +112,14 @@
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/renderscript" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/renderscript" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/binaries" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />

View File

@ -117,11 +117,6 @@
</intent-filter>
</service>
<service
android:name=".ServiceJob"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:name=".ServiceTile"
android:icon="@drawable/ic_security_white_24dp"

View File

@ -331,16 +331,13 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
registerReceiver(packageChangedReceiver, intentFilter);
// First use
boolean submitting = prefs.getBoolean("submitting", false);
if (!initialized || !submitting) {
if (!initialized) {
// Create view
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.first, null, false);
TextView tvFirst = (TextView) view.findViewById(R.id.tvFirst);
TextView tvSubmit = (TextView) view.findViewById(R.id.tvSubmit);
tvFirst.setMovementMethod(LinkMovementMethod.getInstance());
tvSubmit.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? View.VISIBLE : View.GONE);
// Show dialog
dialogFirst = new AlertDialog.Builder(this)
@ -349,10 +346,8 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
.setPositiveButton(R.string.app_agree, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (running) {
if (running)
prefs.edit().putBoolean("initialized", true).apply();
prefs.edit().putBoolean("submitting", true).apply();
}
}
})
.setNegativeButton(R.string.app_disagree, new DialogInterface.OnClickListener() {

View File

@ -21,10 +21,8 @@ package eu.faircode.netguard;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
@ -35,8 +33,6 @@ import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -273,7 +269,6 @@ public class ActivityPro extends AppCompatActivity {
TextView tvSpeed = (TextView) findViewById(R.id.tvSpeed);
TextView tvTheme = (TextView) findViewById(R.id.tvTheme);
TextView tvAll = (TextView) findViewById(R.id.tvAll);
CheckBox cbSubmit = (CheckBox) findViewById(R.id.cbSubmit);
LinearLayout llChallenge = (LinearLayout) findViewById(R.id.llChallenge);
btnLog.setVisibility(IAB.isPurchased(SKU_LOG, this) ? View.GONE : View.VISIBLE);

View File

@ -1029,10 +1029,6 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
xmlExport(getSharedPreferences("notify", Context.MODE_PRIVATE), serializer);
serializer.endTag(null, "notify");
serializer.startTag(null, "submit");
xmlExport(getSharedPreferences("submit", Context.MODE_PRIVATE), serializer);
serializer.endTag(null, "submit");
serializer.startTag(null, "filter");
filterExport(serializer);
serializer.endTag(null, "filter");
@ -1170,7 +1166,6 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
xmlImport(handler.roaming, getSharedPreferences("roaming", Context.MODE_PRIVATE));
xmlImport(handler.apply, getSharedPreferences("apply", Context.MODE_PRIVATE));
xmlImport(handler.notify, getSharedPreferences("notify", Context.MODE_PRIVATE));
xmlImport(handler.submit, getSharedPreferences("submit", Context.MODE_PRIVATE));
// Upgrade imported settings
Receiver.upgrade(true, this);
@ -1218,7 +1213,6 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
public Map<String, Object> roaming = new HashMap<>();
public Map<String, Object> apply = new HashMap<>();
public Map<String, Object> notify = new HashMap<>();
public Map<String, Object> submit = new HashMap<>();
private Map<String, Object> current = null;
public XmlImportHandler(Context context) {
@ -1257,9 +1251,6 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
else if (qName.equals("notify"))
current = notify;
else if (qName.equals("submit"))
current = submit;
else if (qName.equals("filter")) {
current = null;
Log.i(TAG, "Clearing filters");

View File

@ -62,21 +62,9 @@ import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.net.ssl.HttpsURLConnection;
public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> implements Filterable {
private static final String TAG = "NetGuard.Adapter";
@ -94,10 +82,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
private List<Rule> listAll = new ArrayList<>();
private List<Rule> listFiltered = new ArrayList<>();
private static final String cUrl = "https://crowd.netguard.me/";
private static final int cTimeOutMs = 15000;
private static final double cConfidence = 0.35;
public static class ViewHolder extends RecyclerView.ViewHolder {
public View view;
@ -127,7 +111,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
public CheckBox cbApply;
public Button btnRelated;
public ImageButton ibFetch;
public ImageButton ibSettings;
public ImageButton ibLaunch;
@ -146,7 +129,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
public ImageButton btnClearAccess;
public CheckBox cbNotify;
public CheckBox cbSubmit;
public ViewHolder(View itemView) {
super(itemView);
@ -178,7 +160,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
cbApply = (CheckBox) itemView.findViewById(R.id.cbApply);
btnRelated = (Button) itemView.findViewById(R.id.btnRelated);
ibFetch = (ImageButton) itemView.findViewById(R.id.ibFetch);
ibSettings = (ImageButton) itemView.findViewById(R.id.ibSettings);
ibLaunch = (ImageButton) itemView.findViewById(R.id.ibLaunch);
@ -197,7 +178,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
btnClearAccess = (ImageButton) itemView.findViewById(R.id.btnClearAccess);
cbNotify = (CheckBox) itemView.findViewById(R.id.cbNotify);
cbSubmit = (CheckBox) itemView.findViewById(R.id.cbSubmit);
final View wifiParent = (View) cbWifi.getParent();
wifiParent.post(new Runnable() {
@ -446,135 +426,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
}
});
// Fetch settings
holder.ibFetch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new AsyncTask<Object, Object, Object>() {
@Override
protected void onPreExecute() {
holder.ibFetch.setEnabled(false);
}
@Override
protected Object doInBackground(Object... args) {
HttpsURLConnection urlConnection = null;
try {
JSONObject json = new JSONObject();
json.put("type", "fetch");
json.put("country", Locale.getDefault().getCountry());
json.put("netguard", Util.getSelfVersionCode(context));
json.put("fingerprint", Util.getFingerprint(context));
JSONObject pkg = new JSONObject();
pkg.put("name", rule.info.packageName);
pkg.put("version_code", rule.info.versionCode);
pkg.put("version_name", rule.info.versionName);
JSONArray pkgs = new JSONArray();
pkgs.put(pkg);
json.put("package", pkgs);
urlConnection = (HttpsURLConnection) new URL(cUrl).openConnection();
urlConnection.setConnectTimeout(cTimeOutMs);
urlConnection.setReadTimeout(cTimeOutMs);
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestProperty("Content-type", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
Log.i(TAG, "Request=" + json.toString());
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
out.write(json.toString().getBytes()); // UTF-8
out.flush();
int code = urlConnection.getResponseCode();
if (code != HttpsURLConnection.HTTP_OK)
throw new IOException("HTTP " + code);
InputStreamReader isr = new InputStreamReader(urlConnection.getInputStream());
String response = Util.readString(isr).toString();
Log.i(TAG, "Response=" + response);
JSONObject jfetched = new JSONObject(response);
JSONArray jpkgs = jfetched.getJSONArray("package");
for (int i = 0; i < jpkgs.length(); i++) {
JSONObject jpkg = jpkgs.getJSONObject(i);
String name = jpkg.getString("name");
int wifi = jpkg.getInt("wifi");
int wifi_screen = jpkg.getInt("wifi_screen");
int other = jpkg.getInt("other");
int other_screen = jpkg.getInt("other_screen");
int roaming = jpkg.getInt("roaming");
int devices = jpkg.getInt("devices");
double conf_wifi;
boolean block_wifi;
if (rule.wifi_default) {
conf_wifi = confidence(devices - wifi, devices);
block_wifi = !(devices - wifi > wifi && conf_wifi > cConfidence);
} else {
conf_wifi = confidence(wifi, devices);
block_wifi = (wifi > devices - wifi && conf_wifi > cConfidence);
}
boolean allow_wifi_screen = rule.screen_wifi_default;
if (block_wifi)
allow_wifi_screen = (wifi_screen > wifi / 2);
double conf_other;
boolean block_other;
if (rule.other_default) {
conf_other = confidence(devices - other, devices);
block_other = !(devices - other > other && conf_other > cConfidence);
} else {
conf_other = confidence(other, devices);
block_other = (other > devices - other && conf_other > cConfidence);
}
boolean allow_other_screen = rule.screen_other_default;
if (block_other)
allow_other_screen = (other_screen > other / 2);
boolean block_roaming = rule.roaming_default;
if (!block_other || allow_other_screen)
block_roaming = (roaming > (devices - other) / 2);
Log.i(TAG, "pkg=" + name +
" wifi=" + wifi + "/" + wifi_screen + "=" + block_wifi + "/" + allow_wifi_screen + " " + Math.round(100 * conf_wifi) + "%" +
" other=" + other + "/" + other_screen + "/" + roaming + "=" + block_other + "/" + allow_other_screen + "/" + block_roaming + " " + Math.round(100 * conf_other) + "%" +
" devices=" + devices);
rule.wifi_blocked = block_wifi;
rule.screen_wifi = allow_wifi_screen;
rule.other_blocked = block_other;
rule.screen_other = allow_other_screen;
rule.roaming = block_roaming;
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
return ex;
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
return null;
}
@Override
protected void onPostExecute(Object result) {
holder.ibFetch.setEnabled(true);
updateRule(rule, true, listAll);
}
}.execute(rule);
}
});
// Launch application settings
final Intent settings = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
settings.setData(Uri.parse("package:" + rule.info.packageName));
@ -744,8 +595,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
if (IAB.isPurchased(ActivityPro.SKU_FILTER, context)) {
DatabaseHelper.getInstance(context).setAccess(id, 0);
ServiceSinkhole.reload("allow host", context);
if (rule.submit)
ServiceJob.submit(rule, version, protocol, daddr, dport, 0, context);
} else
context.startActivity(new Intent(context, ActivityPro.class));
return true;
@ -754,8 +603,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
if (IAB.isPurchased(ActivityPro.SKU_FILTER, context)) {
DatabaseHelper.getInstance(context).setAccess(id, 1);
ServiceSinkhole.reload("block host", context);
if (rule.submit)
ServiceJob.submit(rule, version, protocol, daddr, dport, 1, context);
} else
context.startActivity(new Intent(context, ActivityPro.class));
return true;
@ -763,8 +610,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
case R.id.menu_reset:
DatabaseHelper.getInstance(context).setAccess(id, -1);
ServiceSinkhole.reload("reset host", context);
if (rule.submit)
ServiceJob.submit(rule, version, protocol, daddr, dport, -1, context);
return true;
}
return false;
@ -812,18 +657,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
updateRule(rule, true, listAll);
}
});
// Usage data sharing
holder.cbSubmit.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? View.VISIBLE : View.GONE);
holder.cbSubmit.setOnCheckedChangeListener(null);
holder.cbSubmit.setChecked(rule.submit);
holder.cbSubmit.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
rule.submit = isChecked;
updateRule(rule, true, listAll);
}
});
}
private void updateRule(Rule rule, boolean root, List<Rule> listAll) {
@ -834,8 +667,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
SharedPreferences screen_other = context.getSharedPreferences("screen_other", Context.MODE_PRIVATE);
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
SharedPreferences notify = context.getSharedPreferences("notify", Context.MODE_PRIVATE);
SharedPreferences submit = context.getSharedPreferences("submit", Context.MODE_PRIVATE);
SharedPreferences history = context.getSharedPreferences("history", Context.MODE_PRIVATE);
if (rule.wifi_blocked == rule.wifi_default)
wifi.edit().remove(rule.info.packageName).apply();
@ -872,14 +703,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
else
notify.edit().putBoolean(rule.info.packageName, rule.notify).apply();
if (rule.submit)
submit.edit().remove(rule.info.packageName).apply();
else
submit.edit().putBoolean(rule.info.packageName, rule.submit).apply();
rule.last_modified = new Date().getTime();
history.edit().putLong(rule.info.packageName + ":modified", rule.last_modified).apply();
rule.updateChanged(context);
Log.i(TAG, "Updated " + rule);
@ -910,9 +733,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
NotificationManagerCompat.from(context).cancel(rule.info.applicationInfo.uid);
ServiceSinkhole.reload("rule changed", context);
}
if (rule.submit)
ServiceJob.submit(rule, context);
}
@Override
@ -959,18 +779,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
};
}
private double confidence(int count, int total) {
// Agresti-Coull Interval
// http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Agresti-Coull_Interval
int n = total;
double p = count / (float) n;
double z = 1.96; // 95%
double n1 = n + z * z;
double p1 = (1 / n1) * (count + 0.5 * z * z);
double ci = z * Math.sqrt((1 / n1) * p1 * (1 - p1));
return 1 - ci;
}
@Override
public AdapterRule.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.rule, parent, false));

View File

@ -239,11 +239,6 @@ public class Receiver extends BroadcastReceiver {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
editor.putBoolean("filter", true); // Mandatory
if (Util.isPlayStoreInstall(context)) {
SharedPreferences apply = context.getSharedPreferences("apply", Context.MODE_PRIVATE);
apply.edit().putBoolean(context.getPackageName(), false).apply();
}
editor.putInt("version", newVersion);
editor.apply();
}

View File

@ -71,7 +71,6 @@ public class Rule {
public boolean apply = true;
public boolean notify = true;
public boolean submit = true;
public boolean relateduids = false;
public String[] related = null;
@ -81,8 +80,6 @@ public class Rule {
public float totalbytes;
public boolean changed;
public long last_modified;
public long last_submitted;
public boolean expanded = false;
@ -225,8 +222,6 @@ public class Rule {
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
SharedPreferences apply = context.getSharedPreferences("apply", Context.MODE_PRIVATE);
SharedPreferences notify = context.getSharedPreferences("notify", Context.MODE_PRIVATE);
SharedPreferences submit = context.getSharedPreferences("submit", Context.MODE_PRIVATE);
SharedPreferences history = context.getSharedPreferences("history", Context.MODE_PRIVATE);
// Get settings
boolean default_wifi = prefs.getBoolean("whitelist_wifi", true);
@ -324,10 +319,7 @@ public class Rule {
if (pre_system.containsKey(info.packageName))
rule.system = pre_system.get(info.packageName);
if (info.applicationInfo.uid == Process.myUid())
if (Util.isPlayStoreInstall(context) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
continue;
else
rule.system = true;
rule.system = true;
if (all ||
((rule.system ? show_system : show_user) &&
@ -348,13 +340,6 @@ public class Rule {
rule.apply = apply.getBoolean(info.packageName, true);
rule.notify = notify.getBoolean(info.packageName, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
rule.submit = submit.getBoolean(info.packageName, true);
else
rule.submit = false;
rule.last_modified = history.getLong(info.packageName + ":modified", 0);
rule.last_submitted = history.getLong(info.packageName + ":submitted", 0);
// Related packages
List<String> listPkg = new ArrayList<>();

View File

@ -1,253 +0,0 @@
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)
*/
import android.annotation.TargetApi;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Build;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.util.Log;
import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import java.util.Locale;
import javax.net.ssl.HttpsURLConnection;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class ServiceJob extends JobService {
private static int id = 0;
private static final String TAG = "NetGuard.Job";
private static final String cUrl = "https://crowd.netguard.me/";
private static final int cTimeOutMs = 15000;
@Override
public boolean onStartJob(JobParameters params) {
Log.i(TAG, "Start job=" + params.getJobId());
new AsyncTask<JobParameters, Object, Object>() {
@Override
protected JobParameters doInBackground(JobParameters... params) {
Log.i(TAG, "Executing job=" + params[0].getJobId());
HttpsURLConnection urlConnection = null;
try {
String android_id = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
JSONObject json = new JSONObject();
json.put("device", Util.sha256(android_id, ""));
json.put("product", Build.DEVICE);
json.put("sdk", Build.VERSION.SDK_INT);
json.put("country", Locale.getDefault().getCountry());
json.put("netguard", Util.getSelfVersionCode(ServiceJob.this));
try {
json.put("store", getPackageManager().getInstallerPackageName(getPackageName()));
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
json.put("store", null);
}
for (String name : params[0].getExtras().keySet())
json.put(name, params[0].getExtras().get(name));
urlConnection = (HttpsURLConnection) new URL(cUrl).openConnection();
urlConnection.setConnectTimeout(cTimeOutMs);
urlConnection.setReadTimeout(cTimeOutMs);
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestProperty("Content-type", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
out.write(json.toString().getBytes()); // UTF-8
out.flush();
int code = urlConnection.getResponseCode();
if (code != HttpsURLConnection.HTTP_OK)
throw new IOException("HTTP " + code);
InputStreamReader isr = new InputStreamReader(urlConnection.getInputStream());
Log.i(TAG, "Response=" + Util.readString(isr).toString());
jobFinished(params[0], false);
if ("rule".equals(params[0].getExtras().getString("type"))) {
SharedPreferences history = getSharedPreferences("history", Context.MODE_PRIVATE);
history.edit().putLong(params[0].getExtras().getString("package") + ":submitted", new Date().getTime()).apply();
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
jobFinished(params[0], true);
} finally {
if (urlConnection != null)
urlConnection.disconnect();
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
}
return null;
}
}.execute(params);
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
Log.i(TAG, "Stop job=" + params.getJobId());
return true;
}
public static void submit(Rule rule, Context context) {
PersistableBundle bundle = new PersistableBundle();
bundle.putString("type", "rule");
bundle.putInt("wifi_default", rule.wifi_default ? 1 : 0);
bundle.putInt("other_default", rule.other_default ? 1 : 0);
bundle.putInt("screen_wifi_default", rule.screen_wifi_default ? 1 : 0);
bundle.putInt("screen_other_default", rule.screen_other_default ? 1 : 0);
bundle.putInt("roaming_default", rule.roaming_default ? 1 : 0);
bundle.putInt("wifi_blocked", rule.wifi_blocked ? 1 : 0);
bundle.putInt("other_blocked", rule.other_blocked ? 1 : 0);
bundle.putInt("screen_wifi", rule.screen_wifi ? 1 : 0);
bundle.putInt("screen_other", rule.screen_other ? 1 : 0);
bundle.putInt("roaming", rule.roaming ? 1 : 0);
bundle.putInt("apply", rule.apply ? 1 : 0);
bundle.putInt("notify", rule.notify ? 1 : 0);
submit(rule, bundle, context);
}
public static void submit(Rule rule, int version, int protocol, String daddr, int dport, int blocked, Context context) {
PersistableBundle bundle = new PersistableBundle();
bundle.putString("type", "host");
bundle.putInt("version", version);
bundle.putInt("protocol", protocol);
bundle.putString("daddr", daddr);
bundle.putInt("dport", dport);
bundle.putInt("blocked", blocked);
submit(rule, bundle, context);
}
private static void submit(Rule rule, PersistableBundle bundle, Context context) {
PackageManager pm = context.getPackageManager();
JobScheduler scheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
// Get english application label
String label = null;
try {
Configuration config = new Configuration();
config.setLocale(new Locale("en"));
Resources res = pm.getResourcesForApplication(rule.info.packageName);
res.updateConfiguration(config, res.getDisplayMetrics());
label = res.getString(rule.info.applicationInfo.labelRes);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
CharSequence cs = rule.info.applicationInfo.loadLabel(pm);
if (cs != null)
label = cs.toString();
}
// Add application data
bundle.putInt("uid", rule.info.applicationInfo.uid);
bundle.putString("package", rule.info.packageName);
bundle.putInt("version_code", rule.info.versionCode);
bundle.putString("version_name", rule.info.versionName);
bundle.putString("label", label);
bundle.putInt("system", rule.system ? 1 : 0);
try {
bundle.putString("installer", pm.getInstallerPackageName(rule.info.packageName));
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
bundle.putString("installer", null);
}
// Cancel overlapping jobs
for (JobInfo pending : scheduler.getAllPendingJobs()) {
String type = pending.getExtras().getString("type");
if (type != null && type.equals(bundle.getString("type"))) {
if (type.equals("rule")) {
int uid = pending.getExtras().getInt("uid");
if (uid == bundle.getInt("uid")) {
Log.i(TAG, "Canceling id=" + pending.getId());
scheduler.cancel(pending.getId());
}
} else if (type.equals("host")) {
int uid = pending.getExtras().getInt("uid");
int version = pending.getExtras().getInt("version");
int protocol = pending.getExtras().getInt("protocol");
String daddr = pending.getExtras().getString("daddr");
int dport = pending.getExtras().getInt("dport");
if (uid == bundle.getInt("uid") &&
version == bundle.getInt("version") &&
protocol == bundle.getInt("protocol") &&
daddr != null && daddr.equals(bundle.getString("daddr")) &&
dport == bundle.getInt("dport")) {
Log.i(TAG, "Canceling id=" + pending.getId());
scheduler.cancel(pending.getId());
}
}
}
}
// Schedule job
ComponentName serviceName = new ComponentName(context, ServiceJob.class);
JobInfo job = new JobInfo.Builder(++id, serviceName)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setMinimumLatency(Util.isDebuggable(context) ? 10 * 1000 : 60 * 1000)
.setExtras(bundle)
.setPersisted(true)
.build();
if (scheduler.schedule(job) == JobScheduler.RESULT_SUCCESS)
Log.i(TAG, "Scheduled job=" + job.getId() + " success");
else
Log.e(TAG, "Scheduled job=" + job.getId() + " failed");
}
}

View File

@ -107,17 +107,6 @@ public class Util {
}
}
public static String sha256(String text, String salt) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] bytes = (text + salt).getBytes("UTF-8");
digest.update(bytes, 0, bytes.length);
bytes = digest.digest();
StringBuilder sb = new StringBuilder();
for (byte b : bytes)
sb.append(String.format("%02X", b));
return sb.toString();
}
public static boolean isConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = (cm == null ? null : cm.getActiveNetworkInfo());

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 789 B

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/fetch_disabled_black" android:state_enabled="false" />
<item android:drawable="@drawable/ic_cloud_download_black_24dp" />
</selector>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_cloud_download_black_24dp"
android:tint="@color/colorGrayed" />

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_cloud_download_white_24dp"
android:tint="@color/colorGrayed" />

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/fetch_disabled_white" android:state_enabled="false" />
<item android:drawable="@drawable/ic_cloud_download_white_24dp" />
</selector>

View File

@ -44,15 +44,6 @@
android:layout_height="wrap_content"
android:text="@string/app_first"
android:textAppearance="@style/TextMedium" />
<TextView
android:id="@+id/tvSubmit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dip"
android:text="@string/app_submit"
android:textAppearance="@style/TextMedium"
android:visibility="gone" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@ -229,16 +229,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/title_related" />
<ImageButton
android:id="@+id/ibFetch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:src="?attr/iconFetch" />
android:text="@string/title_related" />
<ImageButton
android:id="@+id/ibSettings"
@ -408,13 +401,5 @@
android:layout_marginTop="4dp"
android:text="@string/title_notify"
android:textAppearance="@style/TextSmall" />
<CheckBox
android:id="@+id/cbSubmit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/title_submit"
android:textAppearance="@style/TextSmall" />
</LinearLayout>
</LinearLayout>

View File

@ -7,7 +7,6 @@
<string name="app_first">Great care has been taken to develop and test NetGuard,
however it is impossible to guarantee NetGuard will work correctly on every device.
\n\nBy using NetGuard, you agree to the <a href="http://www.gnu.org/licenses/gpl.txt">GNU General Public License version 3</a></string>
<string name="app_submit">NetGuard will optionally share anonymized usage data to help improve how NetGuard protects you, by understanding how end users work with NetGuard.</string>
<string name="app_agree">I agree</string>
<string name="app_disagree">I disagree</string>
@ -215,7 +214,6 @@ Your internet traffic is not being sent to a remote VPN server.</string>
<string name="title_precedence">Access rules take precedence over other rules</string>
<string name="title_options">Options</string>
<string name="title_notify">Notify internet access attempts</string>
<string name="title_submit">Share settings</string>
<string name="title_rate">Rate</string>
<string name="title_allow">Allow</string>

View File

@ -4,7 +4,6 @@
<attr name="expander" format="reference" />
<attr name="iconQueue" format="reference" />
<attr name="iconMetered" format="reference" />
<attr name="iconFetch" format="reference" />
<attr name="iconSettings" format="reference" />
<attr name="iconDelete" format="reference" />
<attr name="iconLaunch" format="reference" />
@ -18,7 +17,6 @@
<item name="expander">@drawable/expander_black</item>
<item name="iconQueue">@drawable/ic_hourglass_empty_black_24dp</item>
<item name="iconMetered">@drawable/ic_attach_money_black_24dp</item>
<item name="iconFetch">@drawable/fetch_black</item>
<item name="iconSettings">@drawable/ic_settings_black_24dp</item>
<item name="iconDelete">@drawable/ic_delete_black_24dp</item>
<item name="iconLaunch">@drawable/ic_launch_black_24dp</item>
@ -29,7 +27,6 @@
<item name="expander">@drawable/expander_white</item>
<item name="iconQueue">@drawable/ic_hourglass_empty_white_24dp</item>
<item name="iconMetered">@drawable/ic_attach_money_white_24dp</item>
<item name="iconFetch">@drawable/fetch_white</item>
<item name="iconSettings">@drawable/ic_settings_white_24dp</item>
<item name="iconDelete">@drawable/ic_delete_white_24dp</item>
<item name="iconLaunch">@drawable/ic_launch_white_24dp</item>

View File

@ -28,7 +28,8 @@ Características:
&bull; Simple de usar
&bull; No requiere root
&bull; 100% código abierto
&bull; Sin seguimiento o perfilado de usuarios
&bull; No calling home
&bull; Sin seguimiento o análisis integrado
&bull; Sin publicidad
&bull; Desarrollado y soportado activamente
&bull; Soporta Android 4.0 o superior

View File

@ -28,6 +28,7 @@ Caracteristici:
&bull; Simplu de utilizat
&bull; Nu necesita acces root
&bull; 100% software cu sursa deschisa
&bull; Nu transmite datele nicaieri
&bull; Nu urmareste activitatea si nici nu o analizeaza
&bull; Fara reclama
&bull; Dezvoltare si asistenta continuua

View File

@ -28,7 +28,8 @@ Features:
&bull; Simple to use
&bull; No root required
&bull; 100% open source
&bull; No tracking and user profiling
&bull; No calling home
&bull; No tracking or analytics
&bull; No advertisements
&bull; Actively developed and supported
&bull; Android 4.0 and later supported