2015-10-24 18:01:55 +00:00
|
|
|
package eu.faircode.netguard;
|
|
|
|
|
2015-11-03 17:57:29 +00:00
|
|
|
/*
|
|
|
|
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 by Marcel Bokhorst (M66B)
|
|
|
|
*/
|
|
|
|
|
2015-10-25 09:29:49 +00:00
|
|
|
import android.app.AlertDialog;
|
2015-11-19 08:21:00 +00:00
|
|
|
import android.app.PendingIntent;
|
2015-10-25 14:22:55 +00:00
|
|
|
import android.content.BroadcastReceiver;
|
|
|
|
import android.content.Context;
|
2015-10-30 15:51:24 +00:00
|
|
|
import android.content.DialogInterface;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.content.Intent;
|
2015-10-25 14:22:55 +00:00
|
|
|
import android.content.IntentFilter;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.content.SharedPreferences;
|
2015-10-31 13:15:26 +00:00
|
|
|
import android.graphics.Color;
|
2015-10-25 15:48:41 +00:00
|
|
|
import android.net.Uri;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.net.VpnService;
|
|
|
|
import android.os.AsyncTask;
|
|
|
|
import android.preference.PreferenceManager;
|
2015-10-30 15:51:24 +00:00
|
|
|
import android.support.v4.content.LocalBroadcastManager;
|
2015-10-25 10:11:46 +00:00
|
|
|
import android.support.v4.view.MenuItemCompat;
|
2015-10-31 13:15:26 +00:00
|
|
|
import android.support.v4.widget.SwipeRefreshLayout;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.support.v7.app.AppCompatActivity;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.support.v7.widget.LinearLayoutManager;
|
|
|
|
import android.support.v7.widget.RecyclerView;
|
2015-10-25 10:11:46 +00:00
|
|
|
import android.support.v7.widget.SearchView;
|
2015-10-26 16:28:47 +00:00
|
|
|
import android.support.v7.widget.SwitchCompat;
|
2015-11-01 06:31:36 +00:00
|
|
|
import android.text.method.LinkMovementMethod;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.util.Log;
|
2015-10-25 09:29:49 +00:00
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuInflater;
|
|
|
|
import android.view.MenuItem;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.view.View;
|
2015-10-30 15:51:24 +00:00
|
|
|
import android.widget.Button;
|
2015-10-24 18:01:55 +00:00
|
|
|
import android.widget.CompoundButton;
|
2015-10-25 09:29:49 +00:00
|
|
|
import android.widget.TextView;
|
2015-10-25 18:02:33 +00:00
|
|
|
import android.widget.Toast;
|
2015-10-24 18:01:55 +00:00
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
2015-10-25 09:29:49 +00:00
|
|
|
public class ActivityMain extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
2015-10-24 18:01:55 +00:00
|
|
|
private static final String TAG = "NetGuard.Main";
|
|
|
|
|
|
|
|
private boolean running = false;
|
2015-10-31 13:15:26 +00:00
|
|
|
private SwipeRefreshLayout swipeRefresh;
|
2015-10-24 18:01:55 +00:00
|
|
|
private RuleAdapter adapter = null;
|
2015-10-29 08:56:22 +00:00
|
|
|
private MenuItem menuSearch = null;
|
2015-11-02 18:53:56 +00:00
|
|
|
private AlertDialog dialogFirst = null;
|
2015-11-03 11:21:34 +00:00
|
|
|
private AlertDialog dialogVpn = null;
|
2015-11-02 18:53:56 +00:00
|
|
|
private AlertDialog dialogAbout = null;
|
2015-10-24 18:01:55 +00:00
|
|
|
|
2015-10-25 09:29:49 +00:00
|
|
|
private static final int REQUEST_VPN = 1;
|
2015-11-02 18:16:30 +00:00
|
|
|
private static final int REQUEST_IAB = 2;
|
2015-11-07 11:43:30 +00:00
|
|
|
private static final int REQUEST_INVITE = 3;
|
2015-11-26 19:34:03 +00:00
|
|
|
private static final int REQUEST_LOGCAT = 4;
|
2015-10-30 15:51:24 +00:00
|
|
|
|
2015-11-25 19:05:17 +00:00
|
|
|
public static final String ACTION_RULES_CHANGED = "eu.faircode.netguard.ACTION_RULES_CHANGED";
|
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
@Override
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
2015-10-25 09:29:49 +00:00
|
|
|
Log.i(TAG, "Create");
|
2015-10-26 17:47:31 +00:00
|
|
|
|
|
|
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
|
|
setTheme(prefs.getBoolean("dark_theme", false) ? R.style.AppThemeDark : R.style.AppTheme);
|
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
setContentView(R.layout.main);
|
2015-10-25 09:29:49 +00:00
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
running = true;
|
2015-10-29 16:33:06 +00:00
|
|
|
boolean enabled = prefs.getBoolean("enabled", false);
|
2015-11-21 09:53:03 +00:00
|
|
|
boolean initialized = prefs.getBoolean("initialized", false);
|
|
|
|
|
|
|
|
// Upgrade
|
|
|
|
Receiver.upgrade(initialized, this);
|
2015-10-24 18:01:55 +00:00
|
|
|
|
2015-11-04 19:48:27 +00:00
|
|
|
if (enabled)
|
|
|
|
SinkholeService.start(this);
|
|
|
|
else
|
|
|
|
SinkholeService.stop(this);
|
|
|
|
|
2015-10-25 09:29:49 +00:00
|
|
|
// Action bar
|
2015-11-15 15:39:59 +00:00
|
|
|
View actionView = getLayoutInflater().inflate(R.layout.action, null);
|
2015-11-02 05:29:09 +00:00
|
|
|
SwitchCompat swEnabled = (SwitchCompat) actionView.findViewById(R.id.swEnabled);
|
2015-11-10 13:41:32 +00:00
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
getSupportActionBar().setDisplayShowCustomEnabled(true);
|
2015-11-02 05:29:09 +00:00
|
|
|
getSupportActionBar().setCustomView(actionView);
|
2015-10-24 18:01:55 +00:00
|
|
|
|
2015-10-24 19:50:29 +00:00
|
|
|
// On/off switch
|
2015-10-29 16:33:06 +00:00
|
|
|
swEnabled.setChecked(enabled);
|
2015-10-24 18:01:55 +00:00
|
|
|
swEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
|
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
2015-11-12 15:13:03 +00:00
|
|
|
prefs.edit().putBoolean("enabled", isChecked).apply();
|
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
if (isChecked) {
|
2015-10-25 10:55:49 +00:00
|
|
|
Log.i(TAG, "Switch on");
|
2015-11-22 19:30:29 +00:00
|
|
|
try {
|
|
|
|
final Intent prepare = VpnService.prepare(ActivityMain.this);
|
|
|
|
if (prepare == null) {
|
2015-11-23 10:05:16 +00:00
|
|
|
Log.i(TAG, "Prepare done");
|
2015-11-22 19:30:29 +00:00
|
|
|
onActivityResult(REQUEST_VPN, RESULT_OK, null);
|
|
|
|
} else {
|
|
|
|
// Show dialog
|
|
|
|
LayoutInflater inflater = LayoutInflater.from(ActivityMain.this);
|
|
|
|
View view = inflater.inflate(R.layout.vpn, null);
|
|
|
|
dialogVpn = new AlertDialog.Builder(ActivityMain.this)
|
|
|
|
.setView(view)
|
|
|
|
.setCancelable(false)
|
|
|
|
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
if (running) {
|
|
|
|
Log.i(TAG, "Start intent=" + prepare);
|
|
|
|
try {
|
|
|
|
startActivityForResult(prepare, REQUEST_VPN);
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
|
|
|
Util.sendCrashReport(ex, ActivityMain.this);
|
|
|
|
onActivityResult(REQUEST_VPN, RESULT_CANCELED, null);
|
|
|
|
}
|
2015-11-03 11:21:34 +00:00
|
|
|
}
|
|
|
|
}
|
2015-11-22 19:30:29 +00:00
|
|
|
})
|
|
|
|
.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
|
|
|
@Override
|
|
|
|
public void onDismiss(DialogInterface dialogInterface) {
|
|
|
|
dialogVpn = null;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.create();
|
|
|
|
dialogVpn.show();
|
|
|
|
}
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
|
|
|
Util.sendCrashReport(ex, ActivityMain.this);
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-10-25 10:55:49 +00:00
|
|
|
Log.i(TAG, "Switch off");
|
2015-11-05 09:55:34 +00:00
|
|
|
prefs.edit().putBoolean("enabled", false).apply();
|
2015-10-29 06:47:12 +00:00
|
|
|
SinkholeService.stop(ActivityMain.this);
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-10-31 13:15:26 +00:00
|
|
|
// Disabled warning
|
|
|
|
TextView tvDisabled = (TextView) findViewById(R.id.tvDisabled);
|
|
|
|
tvDisabled.setVisibility(enabled ? View.GONE : View.VISIBLE);
|
|
|
|
|
|
|
|
// Application list
|
|
|
|
RecyclerView rvApplication = (RecyclerView) findViewById(R.id.rvApplication);
|
|
|
|
rvApplication.setHasFixedSize(true);
|
|
|
|
rvApplication.setLayoutManager(new LinearLayoutManager(this));
|
2015-11-11 06:54:34 +00:00
|
|
|
adapter = new RuleAdapter(ActivityMain.this);
|
2015-10-31 13:15:26 +00:00
|
|
|
rvApplication.setAdapter(adapter);
|
2015-10-25 09:29:49 +00:00
|
|
|
|
2015-10-31 13:23:18 +00:00
|
|
|
// Swipe to refresh
|
2015-10-31 13:15:26 +00:00
|
|
|
swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefresh);
|
|
|
|
swipeRefresh.setColorSchemeColors(Color.WHITE, Color.WHITE, Color.WHITE);
|
|
|
|
swipeRefresh.setProgressBackgroundColorSchemeResource(R.color.colorPrimary);
|
|
|
|
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
|
|
|
@Override
|
|
|
|
public void onRefresh() {
|
|
|
|
updateApplicationList();
|
|
|
|
}
|
|
|
|
});
|
2015-10-31 13:23:18 +00:00
|
|
|
|
2015-11-14 10:04:27 +00:00
|
|
|
// Listen for preference changes
|
|
|
|
prefs.registerOnSharedPreferenceChangeListener(this);
|
|
|
|
|
2015-11-25 19:05:17 +00:00
|
|
|
// Listen for rule set changes
|
|
|
|
IntentFilter iff = new IntentFilter(ACTION_RULES_CHANGED);
|
|
|
|
LocalBroadcastManager.getInstance(this).registerReceiver(onRulesetChanged, iff);
|
|
|
|
|
2015-11-14 10:04:27 +00:00
|
|
|
// Listen for added/removed applications
|
|
|
|
IntentFilter intentFilter = new IntentFilter();
|
|
|
|
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
|
|
|
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
|
|
|
intentFilter.addDataScheme("package");
|
|
|
|
registerReceiver(packageChangedReceiver, intentFilter);
|
|
|
|
|
2015-11-02 12:22:58 +00:00
|
|
|
// First use
|
2015-11-18 07:36:53 +00:00
|
|
|
if (!initialized) {
|
2015-11-02 12:22:58 +00:00
|
|
|
// Create view
|
|
|
|
LayoutInflater inflater = LayoutInflater.from(this);
|
|
|
|
View view = inflater.inflate(R.layout.first, null);
|
|
|
|
TextView tvFirst = (TextView) view.findViewById(R.id.tvFirst);
|
|
|
|
tvFirst.setMovementMethod(LinkMovementMethod.getInstance());
|
|
|
|
|
|
|
|
// Show dialog
|
2015-11-02 18:53:56 +00:00
|
|
|
dialogFirst = new AlertDialog.Builder(this)
|
2015-11-02 12:22:58 +00:00
|
|
|
.setView(view)
|
|
|
|
.setCancelable(false)
|
|
|
|
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
2015-11-06 22:49:03 +00:00
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
2015-11-02 18:53:56 +00:00
|
|
|
if (running)
|
|
|
|
prefs.edit().putBoolean("initialized", true).apply();
|
2015-11-02 12:22:58 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
2015-11-06 22:49:03 +00:00
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
2015-11-02 21:18:56 +00:00
|
|
|
finish();
|
2015-11-02 12:22:58 +00:00
|
|
|
}
|
|
|
|
})
|
2015-11-02 18:53:56 +00:00
|
|
|
.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
|
|
|
@Override
|
|
|
|
public void onDismiss(DialogInterface dialogInterface) {
|
|
|
|
dialogFirst = null;
|
|
|
|
}
|
|
|
|
})
|
2015-11-02 12:22:58 +00:00
|
|
|
.create();
|
2015-11-02 18:53:56 +00:00
|
|
|
dialogFirst.show();
|
2015-11-02 12:22:58 +00:00
|
|
|
}
|
2015-11-18 07:36:53 +00:00
|
|
|
|
|
|
|
// Fill application list
|
|
|
|
updateApplicationList();
|
2015-10-25 14:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-11-14 10:04:27 +00:00
|
|
|
public void onDestroy() {
|
|
|
|
Log.i(TAG, "Destroy");
|
|
|
|
running = false;
|
2015-11-14 09:49:37 +00:00
|
|
|
|
2015-11-14 10:04:27 +00:00
|
|
|
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
|
2015-11-14 10:04:18 +00:00
|
|
|
|
2015-11-25 19:05:17 +00:00
|
|
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(onRulesetChanged);
|
2015-10-25 14:22:55 +00:00
|
|
|
unregisterReceiver(packageChangedReceiver);
|
2015-10-30 15:51:24 +00:00
|
|
|
|
2015-11-03 11:21:34 +00:00
|
|
|
if (dialogFirst != null) {
|
2015-11-02 18:53:56 +00:00
|
|
|
dialogFirst.dismiss();
|
2015-11-03 11:21:34 +00:00
|
|
|
dialogFirst = null;
|
|
|
|
}
|
|
|
|
if (dialogVpn != null) {
|
|
|
|
dialogVpn.dismiss();
|
|
|
|
dialogVpn = null;
|
|
|
|
}
|
|
|
|
if (dialogAbout != null) {
|
2015-11-02 18:53:56 +00:00
|
|
|
dialogAbout.dismiss();
|
2015-11-03 11:21:34 +00:00
|
|
|
dialogAbout = null;
|
|
|
|
}
|
2015-11-02 18:53:56 +00:00
|
|
|
|
2015-10-25 14:22:55 +00:00
|
|
|
super.onDestroy();
|
|
|
|
}
|
|
|
|
|
2015-11-04 19:20:30 +00:00
|
|
|
@Override
|
|
|
|
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
|
|
|
|
Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK));
|
2015-11-20 10:34:23 +00:00
|
|
|
Util.logExtras(data);
|
2015-11-04 19:20:30 +00:00
|
|
|
|
|
|
|
if (requestCode == REQUEST_VPN) {
|
|
|
|
// Handle VPN approval
|
2015-11-05 09:55:34 +00:00
|
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
|
|
prefs.edit().putBoolean("enabled", resultCode == RESULT_OK).apply();
|
2015-11-04 19:20:30 +00:00
|
|
|
if (resultCode == RESULT_OK)
|
|
|
|
SinkholeService.start(this);
|
|
|
|
|
|
|
|
} else if (requestCode == REQUEST_IAB) {
|
2015-11-19 08:21:00 +00:00
|
|
|
// Handle IAB result
|
|
|
|
Intent intent = new Intent(IAB.ACTION_IAB);
|
|
|
|
intent.putExtra("RESULT_CODE", resultCode);
|
|
|
|
if (data != null)
|
|
|
|
intent.putExtra("RESPONSE_CODE", data.getIntExtra("RESPONSE_CODE", -1));
|
|
|
|
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
|
2015-11-04 19:20:30 +00:00
|
|
|
|
2015-11-07 17:18:37 +00:00
|
|
|
} else if (requestCode == REQUEST_INVITE) {
|
2015-11-08 09:14:56 +00:00
|
|
|
// Do nothing
|
2015-11-07 17:18:37 +00:00
|
|
|
|
2015-11-26 19:34:03 +00:00
|
|
|
} else if (requestCode == REQUEST_LOGCAT) {
|
|
|
|
// Send logcat by e-mail
|
|
|
|
Util.sendLogcat(data.getData(), this);
|
|
|
|
|
2015-11-04 19:20:30 +00:00
|
|
|
} else {
|
|
|
|
Log.w(TAG, "Unknown activity result request=" + requestCode);
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSharedPreferenceChanged(SharedPreferences prefs, String name) {
|
|
|
|
Log.i(TAG, "Preference " + name + "=" + prefs.getAll().get(name));
|
|
|
|
if ("enabled".equals(name)) {
|
|
|
|
// Get enabled
|
|
|
|
boolean enabled = prefs.getBoolean(name, false);
|
|
|
|
|
|
|
|
// Display disabled warning
|
|
|
|
TextView tvDisabled = (TextView) findViewById(R.id.tvDisabled);
|
|
|
|
tvDisabled.setVisibility(enabled ? View.GONE : View.VISIBLE);
|
|
|
|
|
|
|
|
// Check switch state
|
|
|
|
SwitchCompat swEnabled = (SwitchCompat) getSupportActionBar().getCustomView().findViewById(R.id.swEnabled);
|
|
|
|
if (swEnabled.isChecked() != enabled)
|
|
|
|
swEnabled.setChecked(enabled);
|
2015-11-04 22:44:17 +00:00
|
|
|
|
|
|
|
} else if ("whitelist_wifi".equals(name) ||
|
|
|
|
"whitelist_other".equals(name) ||
|
2015-11-21 08:48:33 +00:00
|
|
|
"screen_wifi".equals(name) ||
|
|
|
|
"screen_other".equals(name) ||
|
2015-11-04 22:44:17 +00:00
|
|
|
"whitelist_roaming".equals(name) ||
|
2015-11-08 12:05:55 +00:00
|
|
|
"manage_system".equals(name) ||
|
|
|
|
"imported".equals(name))
|
2015-11-04 22:44:17 +00:00
|
|
|
updateApplicationList();
|
|
|
|
|
|
|
|
else if ("dark_theme".equals(name))
|
|
|
|
recreate();
|
2015-11-04 19:20:30 +00:00
|
|
|
}
|
|
|
|
|
2015-11-25 19:05:17 +00:00
|
|
|
private BroadcastReceiver onRulesetChanged = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
Log.i(TAG, "Received " + intent);
|
|
|
|
Util.logExtras(intent);
|
|
|
|
|
|
|
|
if (adapter != null)
|
2015-11-25 20:09:00 +00:00
|
|
|
if (intent.getBooleanExtra("connected", false))
|
|
|
|
if (intent.getBooleanExtra("metered", false))
|
|
|
|
adapter.setMobileActive();
|
|
|
|
else
|
|
|
|
adapter.setWifiActive();
|
2015-11-25 19:05:17 +00:00
|
|
|
else
|
2015-11-25 20:09:00 +00:00
|
|
|
adapter.setDisconnected();
|
2015-11-25 19:05:17 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-10-25 14:22:55 +00:00
|
|
|
private BroadcastReceiver packageChangedReceiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
Log.i(TAG, "Received " + intent);
|
2015-11-20 10:34:23 +00:00
|
|
|
Util.logExtras(intent);
|
2015-10-31 13:15:26 +00:00
|
|
|
updateApplicationList();
|
2015-10-25 14:22:55 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-10-31 13:15:26 +00:00
|
|
|
private void updateApplicationList() {
|
2015-10-24 18:01:55 +00:00
|
|
|
new AsyncTask<Object, Object, List<Rule>>() {
|
2015-10-31 19:52:24 +00:00
|
|
|
private boolean refreshing = true;
|
|
|
|
|
2015-10-31 17:12:57 +00:00
|
|
|
@Override
|
|
|
|
protected void onPreExecute() {
|
|
|
|
swipeRefresh.post(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2015-10-31 19:52:24 +00:00
|
|
|
if (refreshing)
|
|
|
|
swipeRefresh.setRefreshing(true);
|
2015-10-31 17:12:57 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-10-24 18:01:55 +00:00
|
|
|
@Override
|
|
|
|
protected List<Rule> doInBackground(Object... arg) {
|
2015-11-01 08:38:51 +00:00
|
|
|
return Rule.getRules(false, TAG, ActivityMain.this);
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostExecute(List<Rule> result) {
|
|
|
|
if (running) {
|
2015-11-15 14:42:38 +00:00
|
|
|
if (adapter != null)
|
2015-10-31 17:12:57 +00:00
|
|
|
adapter.set(result);
|
2015-11-01 13:28:03 +00:00
|
|
|
if (menuSearch != null)
|
|
|
|
MenuItemCompat.collapseActionView(menuSearch);
|
2015-10-31 19:52:24 +00:00
|
|
|
if (swipeRefresh != null) {
|
|
|
|
refreshing = false;
|
2015-10-31 13:15:26 +00:00
|
|
|
swipeRefresh.setRefreshing(false);
|
2015-10-31 19:52:24 +00:00
|
|
|
}
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
|
2015-10-25 09:29:49 +00:00
|
|
|
@Override
|
|
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
|
|
MenuInflater inflater = getMenuInflater();
|
|
|
|
inflater.inflate(R.menu.main, menu);
|
2015-10-25 10:11:46 +00:00
|
|
|
|
2015-10-25 15:28:41 +00:00
|
|
|
// Search
|
2015-10-29 08:56:22 +00:00
|
|
|
menuSearch = menu.findItem(R.id.menu_search);
|
|
|
|
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuSearch);
|
2015-10-25 10:11:46 +00:00
|
|
|
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onQueryTextSubmit(String query) {
|
2015-10-25 11:52:54 +00:00
|
|
|
if (adapter != null)
|
2015-11-15 14:42:38 +00:00
|
|
|
adapter.getFilter().filter(query);
|
2015-10-25 10:11:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onQueryTextChange(String newText) {
|
2015-10-25 11:52:54 +00:00
|
|
|
if (adapter != null)
|
2015-11-15 14:42:38 +00:00
|
|
|
adapter.getFilter().filter(newText);
|
2015-10-25 10:11:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onClose() {
|
2015-10-25 11:52:54 +00:00
|
|
|
if (adapter != null)
|
|
|
|
adapter.getFilter().filter(null);
|
2015-10-25 10:11:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-11-20 10:34:23 +00:00
|
|
|
if (!Util.hasValidFingerprint(this) || getIntentInvite(this).resolveActivity(getPackageManager()) == null)
|
2015-11-07 11:46:55 +00:00
|
|
|
menu.removeItem(R.id.menu_invite);
|
|
|
|
|
|
|
|
if (getIntentSupport().resolveActivity(getPackageManager()) == null)
|
|
|
|
menu.removeItem(R.id.menu_support);
|
2015-10-31 20:48:09 +00:00
|
|
|
|
2015-11-04 22:44:17 +00:00
|
|
|
return true;
|
2015-10-25 22:04:10 +00:00
|
|
|
}
|
|
|
|
|
2015-10-25 09:29:49 +00:00
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
// Handle item selection
|
|
|
|
switch (item.getItemId()) {
|
2015-11-04 22:44:17 +00:00
|
|
|
case R.id.menu_settings:
|
2015-11-11 06:54:34 +00:00
|
|
|
startActivity(new Intent(this, ActivitySettings.class));
|
2015-10-26 17:47:31 +00:00
|
|
|
return true;
|
|
|
|
|
2015-11-07 11:43:30 +00:00
|
|
|
case R.id.menu_invite:
|
|
|
|
startActivityForResult(getIntentInvite(this), REQUEST_INVITE);
|
|
|
|
return true;
|
|
|
|
|
2015-10-30 07:05:47 +00:00
|
|
|
case R.id.menu_support:
|
2015-11-17 14:12:33 +00:00
|
|
|
startActivity(getIntentSupport());
|
2015-10-29 14:01:41 +00:00
|
|
|
return true;
|
|
|
|
|
2015-10-25 09:29:49 +00:00
|
|
|
case R.id.menu_about:
|
2015-10-30 07:57:36 +00:00
|
|
|
menu_about();
|
2015-10-25 09:29:49 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
2015-10-24 18:01:55 +00:00
|
|
|
}
|
|
|
|
|
2015-10-30 07:57:36 +00:00
|
|
|
private void menu_about() {
|
2015-10-30 15:51:24 +00:00
|
|
|
// Create view
|
2015-10-30 07:57:36 +00:00
|
|
|
LayoutInflater inflater = LayoutInflater.from(this);
|
|
|
|
View view = inflater.inflate(R.layout.about, null);
|
|
|
|
TextView tvVersion = (TextView) view.findViewById(R.id.tvVersion);
|
2015-11-07 16:51:13 +00:00
|
|
|
Button btnRate = (Button) view.findViewById(R.id.btnRate);
|
2015-10-30 15:51:24 +00:00
|
|
|
final Button btnDonate = (Button) view.findViewById(R.id.btnDonate);
|
|
|
|
final TextView tvThanks = (TextView) view.findViewById(R.id.tvThanks);
|
2015-11-01 06:31:36 +00:00
|
|
|
TextView tvLicense = (TextView) view.findViewById(R.id.tvLicense);
|
2015-10-30 15:51:24 +00:00
|
|
|
|
|
|
|
// Show version
|
2015-10-30 07:57:36 +00:00
|
|
|
tvVersion.setText(Util.getSelfVersionName(this));
|
2015-11-20 10:34:23 +00:00
|
|
|
if (!Util.hasValidFingerprint(this))
|
2015-11-14 09:33:56 +00:00
|
|
|
tvVersion.setTextColor(Color.GRAY);
|
2015-10-30 15:51:24 +00:00
|
|
|
|
2015-11-01 06:31:36 +00:00
|
|
|
// Handle license
|
|
|
|
tvLicense.setMovementMethod(LinkMovementMethod.getInstance());
|
|
|
|
|
2015-10-30 15:51:24 +00:00
|
|
|
// Handle logcat
|
2015-11-13 11:38:02 +00:00
|
|
|
view.setOnClickListener(new View.OnClickListener() {
|
|
|
|
private short tap = 0;
|
2015-11-20 20:16:10 +00:00
|
|
|
private Toast toast = Toast.makeText(ActivityMain.this, "", Toast.LENGTH_SHORT);
|
2015-11-13 11:38:02 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
2015-11-20 20:16:10 +00:00
|
|
|
tap++;
|
|
|
|
if (tap == 7) {
|
2015-11-13 11:38:02 +00:00
|
|
|
tap = 0;
|
2015-11-20 20:16:10 +00:00
|
|
|
toast.cancel();
|
2015-11-26 19:34:03 +00:00
|
|
|
|
|
|
|
Intent intent = getIntentLogcat();
|
|
|
|
if (intent.resolveActivity(getPackageManager()) != null)
|
|
|
|
startActivityForResult(intent, REQUEST_LOGCAT, null);
|
|
|
|
|
2015-11-20 20:16:10 +00:00
|
|
|
} else if (tap > 3) {
|
|
|
|
toast.setText(Integer.toString(7 - tap));
|
|
|
|
toast.show();
|
2015-10-30 07:57:36 +00:00
|
|
|
}
|
2015-11-13 11:38:02 +00:00
|
|
|
}
|
|
|
|
});
|
2015-10-30 15:51:24 +00:00
|
|
|
|
2015-11-07 16:51:13 +00:00
|
|
|
// Handle rate
|
|
|
|
btnRate.setVisibility(getIntentRate(this).resolveActivity(getPackageManager()) == null ? View.GONE : View.VISIBLE);
|
|
|
|
btnRate.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
|
|
|
startActivity(getIntentRate(ActivityMain.this));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-11-14 20:25:05 +00:00
|
|
|
// In-app billing
|
2015-11-18 16:48:54 +00:00
|
|
|
final IAB iab = new IAB(this);
|
2015-11-14 20:25:05 +00:00
|
|
|
|
2015-10-30 19:30:16 +00:00
|
|
|
// Handle donate
|
2015-10-30 15:51:24 +00:00
|
|
|
btnDonate.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
2015-11-14 20:25:05 +00:00
|
|
|
try {
|
2015-11-19 08:21:00 +00:00
|
|
|
PendingIntent pi = iab.getIntentSender();
|
|
|
|
if (pi == null) {
|
2015-11-14 20:25:05 +00:00
|
|
|
Log.i(TAG, "Donate");
|
|
|
|
Intent donate = new Intent(Intent.ACTION_VIEW);
|
|
|
|
donate.setData(Uri.parse("http://www.netguard.me/"));
|
|
|
|
startActivity(donate);
|
|
|
|
} else {
|
2015-11-19 08:21:00 +00:00
|
|
|
btnDonate.setEnabled(false);
|
2015-11-14 20:25:05 +00:00
|
|
|
Log.i(TAG, "IAB donate");
|
2015-11-19 08:21:00 +00:00
|
|
|
startIntentSenderForResult(pi.getIntentSender(), REQUEST_IAB, new Intent(), 0, 0, 0);
|
2015-11-02 18:16:30 +00:00
|
|
|
}
|
2015-11-14 20:25:05 +00:00
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
2015-11-20 09:10:22 +00:00
|
|
|
Util.sendCrashReport(ex, ActivityMain.this);
|
2015-11-14 20:25:05 +00:00
|
|
|
}
|
2015-10-30 15:51:24 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-11-19 08:21:00 +00:00
|
|
|
// Handle IAB result
|
|
|
|
final BroadcastReceiver onIABResult = new BroadcastReceiver() {
|
2015-10-30 15:51:24 +00:00
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
2015-11-19 08:21:00 +00:00
|
|
|
int resultCode = intent.getIntExtra("RESULT_CODE", RESULT_CANCELED);
|
|
|
|
int responseCode = intent.getIntExtra("RESPONSE_CODE", -1);
|
|
|
|
final boolean ok = (resultCode == RESULT_OK);
|
|
|
|
Log.i(TAG, "IAB result ok=" + ok + " response=" + IAB.getIABResult(responseCode));
|
|
|
|
|
2015-11-14 20:25:05 +00:00
|
|
|
runOnUiThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (running) {
|
2015-11-19 08:21:00 +00:00
|
|
|
btnDonate.setEnabled(true);
|
|
|
|
if (ok) {
|
|
|
|
btnDonate.setVisibility(View.GONE);
|
|
|
|
tvThanks.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
Intent donate = new Intent(Intent.ACTION_VIEW);
|
|
|
|
donate.setData(Uri.parse("http://www.netguard.me/"));
|
|
|
|
if (donate.resolveActivity(getPackageManager()) != null)
|
|
|
|
startActivity(donate);
|
|
|
|
}
|
2015-11-14 20:25:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2015-10-30 15:51:24 +00:00
|
|
|
}
|
|
|
|
};
|
2015-11-19 08:21:00 +00:00
|
|
|
IntentFilter iff = new IntentFilter(IAB.ACTION_IAB);
|
|
|
|
LocalBroadcastManager.getInstance(this).registerReceiver(onIABResult, iff);
|
2015-10-30 15:51:24 +00:00
|
|
|
|
|
|
|
// Show dialog
|
2015-11-02 18:53:56 +00:00
|
|
|
dialogAbout = new AlertDialog.Builder(this)
|
2015-10-30 07:57:36 +00:00
|
|
|
.setView(view)
|
2015-10-30 15:51:24 +00:00
|
|
|
.setCancelable(true)
|
|
|
|
.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
|
|
|
@Override
|
|
|
|
public void onDismiss(DialogInterface dialogInterface) {
|
2015-11-02 18:53:56 +00:00
|
|
|
if (running)
|
2015-11-19 08:21:00 +00:00
|
|
|
LocalBroadcastManager.getInstance(ActivityMain.this).unregisterReceiver(onIABResult);
|
2015-11-14 20:25:05 +00:00
|
|
|
|
|
|
|
iab.unbind();
|
|
|
|
|
2015-11-02 18:53:56 +00:00
|
|
|
dialogAbout = null;
|
2015-10-30 15:51:24 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.create();
|
2015-11-02 18:53:56 +00:00
|
|
|
dialogAbout.show();
|
2015-10-30 15:51:24 +00:00
|
|
|
|
2015-11-14 20:25:05 +00:00
|
|
|
// Connect to billing
|
2015-11-20 10:34:23 +00:00
|
|
|
if (Util.hasValidFingerprint(this))
|
2015-11-14 20:25:05 +00:00
|
|
|
iab.bind();
|
2015-10-30 07:57:36 +00:00
|
|
|
}
|
|
|
|
|
2015-11-26 19:34:03 +00:00
|
|
|
|
2015-11-07 11:43:30 +00:00
|
|
|
private static Intent getIntentInvite(Context context) {
|
2015-11-08 09:14:56 +00:00
|
|
|
Intent intent = new Intent("com.google.android.gms.appinvite.ACTION_APP_INVITE");
|
|
|
|
intent.setPackage("com.google.android.gms");
|
|
|
|
intent.putExtra("com.google.android.gms.appinvite.TITLE", context.getString(R.string.menu_invite));
|
|
|
|
intent.putExtra("com.google.android.gms.appinvite.MESSAGE", context.getString(R.string.msg_try));
|
|
|
|
intent.putExtra("com.google.android.gms.appinvite.BUTTON_TEXT", context.getString(R.string.msg_try));
|
|
|
|
// com.google.android.gms.appinvite.DEEP_LINK_URL
|
|
|
|
return intent;
|
2015-11-07 11:43:30 +00:00
|
|
|
}
|
|
|
|
|
2015-11-07 16:51:13 +00:00
|
|
|
private static Intent getIntentRate(Context context) {
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName()));
|
|
|
|
if (intent.resolveActivity(context.getPackageManager()) == null)
|
|
|
|
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + context.getPackageName()));
|
|
|
|
return intent;
|
|
|
|
}
|
|
|
|
|
2015-11-01 06:38:52 +00:00
|
|
|
private static Intent getIntentSupport() {
|
2015-10-31 20:48:09 +00:00
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
2015-11-17 15:24:13 +00:00
|
|
|
intent.setData(Uri.parse("https://github.com/M66B/NetGuard/blob/master/FAQ.md"));
|
2015-10-31 20:48:09 +00:00
|
|
|
return intent;
|
|
|
|
}
|
2015-11-26 19:34:03 +00:00
|
|
|
|
|
|
|
private Intent getIntentLogcat() {
|
|
|
|
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
|
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
|
|
intent.setType("text/plain");
|
|
|
|
intent.putExtra(Intent.EXTRA_TITLE, "logcat.txt");
|
|
|
|
return intent;
|
|
|
|
}
|
2015-10-31 19:02:22 +00:00
|
|
|
}
|