Removed usage data sharing
27
FAQ.md
|
@ -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.
|
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.
|
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 />
|
<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 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).
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ Features:
|
||||||
* Simple to use
|
* Simple to use
|
||||||
* No root required
|
* No root required
|
||||||
* 100% open source
|
* 100% open source
|
||||||
* No tracking and user profiling
|
* No calling home
|
||||||
|
* No tracking or analytics
|
||||||
* No advertisements
|
* No advertisements
|
||||||
* Actively developed and supported
|
* Actively developed and supported
|
||||||
* Android 4.0 and later supported
|
* Android 4.0 and later supported
|
||||||
|
@ -183,9 +184,6 @@ Frequently Asked Questions (FAQ)
|
||||||
<a name="FAQ38"></a>
|
<a name="FAQ38"></a>
|
||||||
[**(38) Why did NetGuard stop running?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ38)
|
[**(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
|
Permissions
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
16
app/app.iml
|
@ -104,14 +104,6 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
<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/renderscript" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" 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/res" type="java-test-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" 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" />
|
<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/jni" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/renderscript" 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/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/assets" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/binaries" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/binaries" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||||
|
|
|
@ -117,11 +117,6 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".ServiceJob"
|
|
||||||
android:exported="true"
|
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".ServiceTile"
|
android:name=".ServiceTile"
|
||||||
android:icon="@drawable/ic_security_white_24dp"
|
android:icon="@drawable/ic_security_white_24dp"
|
||||||
|
|
|
@ -331,16 +331,13 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
||||||
registerReceiver(packageChangedReceiver, intentFilter);
|
registerReceiver(packageChangedReceiver, intentFilter);
|
||||||
|
|
||||||
// First use
|
// First use
|
||||||
boolean submitting = prefs.getBoolean("submitting", false);
|
if (!initialized) {
|
||||||
if (!initialized || !submitting) {
|
|
||||||
// Create view
|
// Create view
|
||||||
LayoutInflater inflater = LayoutInflater.from(this);
|
LayoutInflater inflater = LayoutInflater.from(this);
|
||||||
View view = inflater.inflate(R.layout.first, null, false);
|
View view = inflater.inflate(R.layout.first, null, false);
|
||||||
|
|
||||||
TextView tvFirst = (TextView) view.findViewById(R.id.tvFirst);
|
TextView tvFirst = (TextView) view.findViewById(R.id.tvFirst);
|
||||||
TextView tvSubmit = (TextView) view.findViewById(R.id.tvSubmit);
|
|
||||||
tvFirst.setMovementMethod(LinkMovementMethod.getInstance());
|
tvFirst.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
tvSubmit.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? View.VISIBLE : View.GONE);
|
|
||||||
|
|
||||||
// Show dialog
|
// Show dialog
|
||||||
dialogFirst = new AlertDialog.Builder(this)
|
dialogFirst = new AlertDialog.Builder(this)
|
||||||
|
@ -349,10 +346,8 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
||||||
.setPositiveButton(R.string.app_agree, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.app_agree, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if (running) {
|
if (running)
|
||||||
prefs.edit().putBoolean("initialized", true).apply();
|
prefs.edit().putBoolean("initialized", true).apply();
|
||||||
prefs.edit().putBoolean("submitting", true).apply();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.app_disagree, new DialogInterface.OnClickListener() {
|
.setNegativeButton(R.string.app_disagree, new DialogInterface.OnClickListener() {
|
||||||
|
|
|
@ -21,10 +21,8 @@ package eu.faircode.netguard;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
@ -35,8 +33,6 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -273,7 +269,6 @@ public class ActivityPro extends AppCompatActivity {
|
||||||
TextView tvSpeed = (TextView) findViewById(R.id.tvSpeed);
|
TextView tvSpeed = (TextView) findViewById(R.id.tvSpeed);
|
||||||
TextView tvTheme = (TextView) findViewById(R.id.tvTheme);
|
TextView tvTheme = (TextView) findViewById(R.id.tvTheme);
|
||||||
TextView tvAll = (TextView) findViewById(R.id.tvAll);
|
TextView tvAll = (TextView) findViewById(R.id.tvAll);
|
||||||
CheckBox cbSubmit = (CheckBox) findViewById(R.id.cbSubmit);
|
|
||||||
LinearLayout llChallenge = (LinearLayout) findViewById(R.id.llChallenge);
|
LinearLayout llChallenge = (LinearLayout) findViewById(R.id.llChallenge);
|
||||||
|
|
||||||
btnLog.setVisibility(IAB.isPurchased(SKU_LOG, this) ? View.GONE : View.VISIBLE);
|
btnLog.setVisibility(IAB.isPurchased(SKU_LOG, this) ? View.GONE : View.VISIBLE);
|
||||||
|
|
|
@ -1029,10 +1029,6 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
||||||
xmlExport(getSharedPreferences("notify", Context.MODE_PRIVATE), serializer);
|
xmlExport(getSharedPreferences("notify", Context.MODE_PRIVATE), serializer);
|
||||||
serializer.endTag(null, "notify");
|
serializer.endTag(null, "notify");
|
||||||
|
|
||||||
serializer.startTag(null, "submit");
|
|
||||||
xmlExport(getSharedPreferences("submit", Context.MODE_PRIVATE), serializer);
|
|
||||||
serializer.endTag(null, "submit");
|
|
||||||
|
|
||||||
serializer.startTag(null, "filter");
|
serializer.startTag(null, "filter");
|
||||||
filterExport(serializer);
|
filterExport(serializer);
|
||||||
serializer.endTag(null, "filter");
|
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.roaming, getSharedPreferences("roaming", Context.MODE_PRIVATE));
|
||||||
xmlImport(handler.apply, getSharedPreferences("apply", Context.MODE_PRIVATE));
|
xmlImport(handler.apply, getSharedPreferences("apply", Context.MODE_PRIVATE));
|
||||||
xmlImport(handler.notify, getSharedPreferences("notify", Context.MODE_PRIVATE));
|
xmlImport(handler.notify, getSharedPreferences("notify", Context.MODE_PRIVATE));
|
||||||
xmlImport(handler.submit, getSharedPreferences("submit", Context.MODE_PRIVATE));
|
|
||||||
|
|
||||||
// Upgrade imported settings
|
// Upgrade imported settings
|
||||||
Receiver.upgrade(true, this);
|
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> roaming = new HashMap<>();
|
||||||
public Map<String, Object> apply = new HashMap<>();
|
public Map<String, Object> apply = new HashMap<>();
|
||||||
public Map<String, Object> notify = new HashMap<>();
|
public Map<String, Object> notify = new HashMap<>();
|
||||||
public Map<String, Object> submit = new HashMap<>();
|
|
||||||
private Map<String, Object> current = null;
|
private Map<String, Object> current = null;
|
||||||
|
|
||||||
public XmlImportHandler(Context context) {
|
public XmlImportHandler(Context context) {
|
||||||
|
@ -1257,9 +1251,6 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
||||||
else if (qName.equals("notify"))
|
else if (qName.equals("notify"))
|
||||||
current = notify;
|
current = notify;
|
||||||
|
|
||||||
else if (qName.equals("submit"))
|
|
||||||
current = submit;
|
|
||||||
|
|
||||||
else if (qName.equals("filter")) {
|
else if (qName.equals("filter")) {
|
||||||
current = null;
|
current = null;
|
||||||
Log.i(TAG, "Clearing filters");
|
Log.i(TAG, "Clearing filters");
|
||||||
|
|
|
@ -62,21 +62,9 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import com.squareup.picasso.Picasso;
|
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.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
|
|
||||||
public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> implements Filterable {
|
public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> implements Filterable {
|
||||||
private static final String TAG = "NetGuard.Adapter";
|
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> listAll = new ArrayList<>();
|
||||||
private List<Rule> listFiltered = 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 static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
public View view;
|
public View view;
|
||||||
|
|
||||||
|
@ -127,7 +111,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
|
||||||
public CheckBox cbApply;
|
public CheckBox cbApply;
|
||||||
|
|
||||||
public Button btnRelated;
|
public Button btnRelated;
|
||||||
public ImageButton ibFetch;
|
|
||||||
public ImageButton ibSettings;
|
public ImageButton ibSettings;
|
||||||
public ImageButton ibLaunch;
|
public ImageButton ibLaunch;
|
||||||
|
|
||||||
|
@ -146,7 +129,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
|
||||||
public ImageButton btnClearAccess;
|
public ImageButton btnClearAccess;
|
||||||
|
|
||||||
public CheckBox cbNotify;
|
public CheckBox cbNotify;
|
||||||
public CheckBox cbSubmit;
|
|
||||||
|
|
||||||
public ViewHolder(View itemView) {
|
public ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
|
@ -178,7 +160,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
|
||||||
cbApply = (CheckBox) itemView.findViewById(R.id.cbApply);
|
cbApply = (CheckBox) itemView.findViewById(R.id.cbApply);
|
||||||
|
|
||||||
btnRelated = (Button) itemView.findViewById(R.id.btnRelated);
|
btnRelated = (Button) itemView.findViewById(R.id.btnRelated);
|
||||||
ibFetch = (ImageButton) itemView.findViewById(R.id.ibFetch);
|
|
||||||
ibSettings = (ImageButton) itemView.findViewById(R.id.ibSettings);
|
ibSettings = (ImageButton) itemView.findViewById(R.id.ibSettings);
|
||||||
ibLaunch = (ImageButton) itemView.findViewById(R.id.ibLaunch);
|
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);
|
btnClearAccess = (ImageButton) itemView.findViewById(R.id.btnClearAccess);
|
||||||
|
|
||||||
cbNotify = (CheckBox) itemView.findViewById(R.id.cbNotify);
|
cbNotify = (CheckBox) itemView.findViewById(R.id.cbNotify);
|
||||||
cbSubmit = (CheckBox) itemView.findViewById(R.id.cbSubmit);
|
|
||||||
|
|
||||||
final View wifiParent = (View) cbWifi.getParent();
|
final View wifiParent = (View) cbWifi.getParent();
|
||||||
wifiParent.post(new Runnable() {
|
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
|
// Launch application settings
|
||||||
final Intent settings = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
final Intent settings = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
settings.setData(Uri.parse("package:" + rule.info.packageName));
|
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)) {
|
if (IAB.isPurchased(ActivityPro.SKU_FILTER, context)) {
|
||||||
DatabaseHelper.getInstance(context).setAccess(id, 0);
|
DatabaseHelper.getInstance(context).setAccess(id, 0);
|
||||||
ServiceSinkhole.reload("allow host", context);
|
ServiceSinkhole.reload("allow host", context);
|
||||||
if (rule.submit)
|
|
||||||
ServiceJob.submit(rule, version, protocol, daddr, dport, 0, context);
|
|
||||||
} else
|
} else
|
||||||
context.startActivity(new Intent(context, ActivityPro.class));
|
context.startActivity(new Intent(context, ActivityPro.class));
|
||||||
return true;
|
return true;
|
||||||
|
@ -754,8 +603,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
|
||||||
if (IAB.isPurchased(ActivityPro.SKU_FILTER, context)) {
|
if (IAB.isPurchased(ActivityPro.SKU_FILTER, context)) {
|
||||||
DatabaseHelper.getInstance(context).setAccess(id, 1);
|
DatabaseHelper.getInstance(context).setAccess(id, 1);
|
||||||
ServiceSinkhole.reload("block host", context);
|
ServiceSinkhole.reload("block host", context);
|
||||||
if (rule.submit)
|
|
||||||
ServiceJob.submit(rule, version, protocol, daddr, dport, 1, context);
|
|
||||||
} else
|
} else
|
||||||
context.startActivity(new Intent(context, ActivityPro.class));
|
context.startActivity(new Intent(context, ActivityPro.class));
|
||||||
return true;
|
return true;
|
||||||
|
@ -763,8 +610,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
|
||||||
case R.id.menu_reset:
|
case R.id.menu_reset:
|
||||||
DatabaseHelper.getInstance(context).setAccess(id, -1);
|
DatabaseHelper.getInstance(context).setAccess(id, -1);
|
||||||
ServiceSinkhole.reload("reset host", context);
|
ServiceSinkhole.reload("reset host", context);
|
||||||
if (rule.submit)
|
|
||||||
ServiceJob.submit(rule, version, protocol, daddr, dport, -1, context);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -812,18 +657,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
|
||||||
updateRule(rule, true, listAll);
|
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) {
|
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 screen_other = context.getSharedPreferences("screen_other", Context.MODE_PRIVATE);
|
||||||
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
|
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
|
||||||
SharedPreferences notify = context.getSharedPreferences("notify", 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)
|
if (rule.wifi_blocked == rule.wifi_default)
|
||||||
wifi.edit().remove(rule.info.packageName).apply();
|
wifi.edit().remove(rule.info.packageName).apply();
|
||||||
|
@ -872,14 +703,6 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
|
||||||
else
|
else
|
||||||
notify.edit().putBoolean(rule.info.packageName, rule.notify).apply();
|
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);
|
rule.updateChanged(context);
|
||||||
Log.i(TAG, "Updated " + rule);
|
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);
|
NotificationManagerCompat.from(context).cancel(rule.info.applicationInfo.uid);
|
||||||
ServiceSinkhole.reload("rule changed", context);
|
ServiceSinkhole.reload("rule changed", context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rule.submit)
|
|
||||||
ServiceJob.submit(rule, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
public AdapterRule.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public AdapterRule.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.rule, parent, false));
|
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.rule, parent, false));
|
||||||
|
|
|
@ -239,11 +239,6 @@ public class Receiver extends BroadcastReceiver {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
||||||
editor.putBoolean("filter", true); // Mandatory
|
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.putInt("version", newVersion);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,6 @@ public class Rule {
|
||||||
|
|
||||||
public boolean apply = true;
|
public boolean apply = true;
|
||||||
public boolean notify = true;
|
public boolean notify = true;
|
||||||
public boolean submit = true;
|
|
||||||
|
|
||||||
public boolean relateduids = false;
|
public boolean relateduids = false;
|
||||||
public String[] related = null;
|
public String[] related = null;
|
||||||
|
@ -81,8 +80,6 @@ public class Rule {
|
||||||
public float totalbytes;
|
public float totalbytes;
|
||||||
|
|
||||||
public boolean changed;
|
public boolean changed;
|
||||||
public long last_modified;
|
|
||||||
public long last_submitted;
|
|
||||||
|
|
||||||
public boolean expanded = false;
|
public boolean expanded = false;
|
||||||
|
|
||||||
|
@ -225,8 +222,6 @@ public class Rule {
|
||||||
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
|
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
|
||||||
SharedPreferences apply = context.getSharedPreferences("apply", Context.MODE_PRIVATE);
|
SharedPreferences apply = context.getSharedPreferences("apply", Context.MODE_PRIVATE);
|
||||||
SharedPreferences notify = context.getSharedPreferences("notify", 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
|
// Get settings
|
||||||
boolean default_wifi = prefs.getBoolean("whitelist_wifi", true);
|
boolean default_wifi = prefs.getBoolean("whitelist_wifi", true);
|
||||||
|
@ -324,10 +319,7 @@ public class Rule {
|
||||||
if (pre_system.containsKey(info.packageName))
|
if (pre_system.containsKey(info.packageName))
|
||||||
rule.system = pre_system.get(info.packageName);
|
rule.system = pre_system.get(info.packageName);
|
||||||
if (info.applicationInfo.uid == Process.myUid())
|
if (info.applicationInfo.uid == Process.myUid())
|
||||||
if (Util.isPlayStoreInstall(context) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
rule.system = true;
|
||||||
continue;
|
|
||||||
else
|
|
||||||
rule.system = true;
|
|
||||||
|
|
||||||
if (all ||
|
if (all ||
|
||||||
((rule.system ? show_system : show_user) &&
|
((rule.system ? show_system : show_user) &&
|
||||||
|
@ -348,13 +340,6 @@ public class Rule {
|
||||||
|
|
||||||
rule.apply = apply.getBoolean(info.packageName, true);
|
rule.apply = apply.getBoolean(info.packageName, true);
|
||||||
rule.notify = notify.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
|
// Related packages
|
||||||
List<String> listPkg = new ArrayList<>();
|
List<String> listPkg = new ArrayList<>();
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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) {
|
public static boolean isConnected(Context context) {
|
||||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo ni = (cm == null ? null : cm.getActiveNetworkInfo());
|
NetworkInfo ni = (cm == null ? null : cm.getActiveNetworkInfo());
|
||||||
|
|
Before Width: | Height: | Size: 344 B |
Before Width: | Height: | Size: 353 B |
Before Width: | Height: | Size: 235 B |
Before Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 404 B |
Before Width: | Height: | Size: 417 B |
Before Width: | Height: | Size: 592 B |
Before Width: | Height: | Size: 610 B |
Before Width: | Height: | Size: 764 B |
Before Width: | Height: | Size: 789 B |
|
@ -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>
|
|
|
@ -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" />
|
|
|
@ -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" />
|
|
|
@ -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>
|
|
|
@ -44,15 +44,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/app_first"
|
android:text="@string/app_first"
|
||||||
android:textAppearance="@style/TextMedium" />
|
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>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -229,16 +229,9 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
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_marginEnd="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:src="?attr/iconFetch" />
|
android:text="@string/title_related" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/ibSettings"
|
android:id="@+id/ibSettings"
|
||||||
|
@ -408,13 +401,5 @@
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="@string/title_notify"
|
android:text="@string/title_notify"
|
||||||
android:textAppearance="@style/TextSmall" />
|
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>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -7,7 +7,6 @@
|
||||||
<string name="app_first">Great care has been taken to develop and test NetGuard,
|
<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.
|
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>
|
\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_agree">I agree</string>
|
||||||
<string name="app_disagree">I disagree</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_precedence">Access rules take precedence over other rules</string>
|
||||||
<string name="title_options">Options</string>
|
<string name="title_options">Options</string>
|
||||||
<string name="title_notify">Notify internet access attempts</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_rate">Rate</string>
|
||||||
<string name="title_allow">Allow</string>
|
<string name="title_allow">Allow</string>
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
<attr name="expander" format="reference" />
|
<attr name="expander" format="reference" />
|
||||||
<attr name="iconQueue" format="reference" />
|
<attr name="iconQueue" format="reference" />
|
||||||
<attr name="iconMetered" format="reference" />
|
<attr name="iconMetered" format="reference" />
|
||||||
<attr name="iconFetch" format="reference" />
|
|
||||||
<attr name="iconSettings" format="reference" />
|
<attr name="iconSettings" format="reference" />
|
||||||
<attr name="iconDelete" format="reference" />
|
<attr name="iconDelete" format="reference" />
|
||||||
<attr name="iconLaunch" format="reference" />
|
<attr name="iconLaunch" format="reference" />
|
||||||
|
@ -18,7 +17,6 @@
|
||||||
<item name="expander">@drawable/expander_black</item>
|
<item name="expander">@drawable/expander_black</item>
|
||||||
<item name="iconQueue">@drawable/ic_hourglass_empty_black_24dp</item>
|
<item name="iconQueue">@drawable/ic_hourglass_empty_black_24dp</item>
|
||||||
<item name="iconMetered">@drawable/ic_attach_money_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="iconSettings">@drawable/ic_settings_black_24dp</item>
|
||||||
<item name="iconDelete">@drawable/ic_delete_black_24dp</item>
|
<item name="iconDelete">@drawable/ic_delete_black_24dp</item>
|
||||||
<item name="iconLaunch">@drawable/ic_launch_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="expander">@drawable/expander_white</item>
|
||||||
<item name="iconQueue">@drawable/ic_hourglass_empty_white_24dp</item>
|
<item name="iconQueue">@drawable/ic_hourglass_empty_white_24dp</item>
|
||||||
<item name="iconMetered">@drawable/ic_attach_money_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="iconSettings">@drawable/ic_settings_white_24dp</item>
|
||||||
<item name="iconDelete">@drawable/ic_delete_white_24dp</item>
|
<item name="iconDelete">@drawable/ic_delete_white_24dp</item>
|
||||||
<item name="iconLaunch">@drawable/ic_launch_white_24dp</item>
|
<item name="iconLaunch">@drawable/ic_launch_white_24dp</item>
|
||||||
|
|
|
@ -28,7 +28,8 @@ Características:
|
||||||
• Simple de usar
|
• Simple de usar
|
||||||
• No requiere root
|
• No requiere root
|
||||||
• 100% código abierto
|
• 100% código abierto
|
||||||
• Sin seguimiento o perfilado de usuarios
|
• No calling home
|
||||||
|
• Sin seguimiento o análisis integrado
|
||||||
• Sin publicidad
|
• Sin publicidad
|
||||||
• Desarrollado y soportado activamente
|
• Desarrollado y soportado activamente
|
||||||
• Soporta Android 4.0 o superior
|
• Soporta Android 4.0 o superior
|
||||||
|
|
|
@ -28,6 +28,7 @@ Caracteristici:
|
||||||
• Simplu de utilizat
|
• Simplu de utilizat
|
||||||
• Nu necesita acces root
|
• Nu necesita acces root
|
||||||
• 100% software cu sursa deschisa
|
• 100% software cu sursa deschisa
|
||||||
|
• Nu transmite datele nicaieri
|
||||||
• Nu urmareste activitatea si nici nu o analizeaza
|
• Nu urmareste activitatea si nici nu o analizeaza
|
||||||
• Fara reclama
|
• Fara reclama
|
||||||
• Dezvoltare si asistenta continuua
|
• Dezvoltare si asistenta continuua
|
||||||
|
|
|
@ -28,7 +28,8 @@ Features:
|
||||||
• Simple to use
|
• Simple to use
|
||||||
• No root required
|
• No root required
|
||||||
• 100% open source
|
• 100% open source
|
||||||
• No tracking and user profiling
|
• No calling home
|
||||||
|
• No tracking or analytics
|
||||||
• No advertisements
|
• No advertisements
|
||||||
• Actively developed and supported
|
• Actively developed and supported
|
||||||
• Android 4.0 and later supported
|
• Android 4.0 and later supported
|
||||||
|
|