Skip to content

Commit 00a079e

Browse files
committed
Add settings screen and monitoring of system apps. Clean up.
1 parent 0e284af commit 00a079e

20 files changed

+315
-218
lines changed

app/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ android {
2525
applicationId 'net.kollnig.missioncontrol'
2626
minSdkVersion 22
2727
targetSdkVersion 26
28-
versionCode 1
29-
versionName "1.0.0-alpha2"
28+
versionCode 3
29+
versionName "1.0.0-alpha3"
3030
}
3131

3232
buildTypes {
@@ -93,6 +93,7 @@ dependencies {
9393
implementation 'com.android.support:support-v4:28.0.0'
9494
implementation 'com.android.support:cardview-v7:28.0.0'
9595
implementation 'com.android.support:recyclerview-v7:28.0.0'
96+
implementation 'com.android.support:preference-v7:28.0.0'
9697

9798
implementation 'com.google.guava:guava:28.0-android'
9899
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

app/src/main/AndroidManifest.xml

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,52 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<!--
3-
~ Copyright (C) 2019 Konrad Kollnig, University of Oxford
4-
~
5-
~ TrackerControl is free software: you can redistribute it and/or modify
6-
~ it under the terms of the GNU General Public License as published by
7-
~ the Free Software Foundation, either version 2 of the License, or
8-
~ (at your option) any later version.
9-
~
10-
~ TrackerControl is distributed in the hope that it will be useful,
11-
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13-
~ GNU General Public License for more details.
14-
~
15-
~ You should have received a copy of the GNU General Public License
16-
~ along with TrackerControl. If not, see <http://www.gnu.org/licenses/>.
17-
-->
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="net.kollnig.missioncontrol">
184

19-
<manifest package="net.kollnig.missioncontrol"
20-
xmlns:android="http://schemas.android.com/apk/res/android">
21-
22-
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/><!--VPN Service-->
23-
<uses-permission android:name="android.permission.INTERNET"/>
24-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!--CSV export-->
5+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- VPN Service -->
6+
<uses-permission android:name="android.permission.INTERNET" />
7+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
258

269
<application
2710
android:name=".AppWithCrashReporting"
2811
android:icon="@mipmap/ic_launcher"
2912
android:label="@string/app_name"
3013
android:supportsRtl="true"
3114
android:theme="@style/AppTheme">
32-
33-
<activity android:name=".MainActivity"
34-
android:launchMode="singleTop"
35-
android:theme="@style/AppTheme.NoActionBar">
15+
<activity
16+
android:name=".main.SettingsActivity"
17+
android:label="Settings"
18+
android:parentActivityName=".MainActivity">
19+
<meta-data
20+
android:name="android.support.PARENT_ACTIVITY"
21+
android:value=".MainActivity" />
22+
</activity>
23+
<activity
24+
android:name=".MainActivity"
25+
android:launchMode="singleTop"
26+
android:theme="@style/AppTheme.NoActionBar">
3627
<intent-filter>
37-
<action android:name="android.intent.action.MAIN"/>
28+
<action android:name="android.intent.action.MAIN" />
3829

39-
<category android:name="android.intent.category.LAUNCHER"/>
30+
<category android:name="android.intent.category.LAUNCHER" />
4031
</intent-filter>
4132
<intent-filter>
42-
<action android:name="edu.uci.calit2.anteater.ACTION.NOTIFICATION"/>
33+
<action android:name="edu.uci.calit2.anteater.ACTION.NOTIFICATION" />
4334

44-
<category android:name="android.intent.category.DEFAULT"/>
35+
<category android:name="android.intent.category.DEFAULT" />
4536
</intent-filter>
4637
<intent-filter>
47-
<action android:name="android.intent.action.VIEW"/>
38+
<action android:name="android.intent.action.VIEW" />
4839
</intent-filter>
4940
</activity>
50-
5141
<activity
5242
android:name=".DetailsActivity"
5343
android:label="@string/title_activity_detail"
5444
android:parentActivityName=".MainActivity"
5545
android:theme="@style/AppTheme.NoActionBar">
5646
<meta-data
5747
android:name="android.support.PARENT_ACTIVITY"
58-
android:value="net.kollnig.missioncontrol.MainActivity"/>
48+
android:value="net.kollnig.missioncontrol.MainActivity" />
5949
</activity>
60-
6150
<!--
6251
No UI activity that requests VPN rights.
6352
If VPN rights can be obtained, the activity initiates a connection attempt
@@ -66,13 +55,13 @@
6655
android:name=".vpn.VpnStarterActivity"
6756
android:excludeFromRecents="true"
6857
android:launchMode="singleTask"
69-
android:theme="@android:style/Theme.NoDisplay"/>
58+
android:theme="@android:style/Theme.NoDisplay" />
7059

7160
<receiver android:name=".vpn.DeviceBootListener">
7261

7362
<!-- Attempts to reestablish VPN on reboot -->
7463
<intent-filter>
75-
<action android:name="android.intent.action.BOOT_COMPLETED"/>
64+
<action android:name="android.intent.action.BOOT_COMPLETED" />
7665
</intent-filter>
7766
</receiver>
7867

@@ -83,7 +72,7 @@
8372
android:grantUriPermissions="true">
8473
<meta-data
8574
android:name="android.support.FILE_PROVIDER_PATHS"
86-
android:resource="@xml/provider_paths"/>
75+
android:resource="@xml/provider_paths" />
8776
</provider>
8877
</application>
8978

app/src/main/java/net/kollnig/missioncontrol/DetailsActivity.java

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@
5959
public class DetailsActivity extends AppCompatActivity {
6060
public static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
6161
public static PlayStore.AppInfo app = null;
62+
public static String consent;
6263
private final String TAG = DetailsActivity.class.getSimpleName();
6364
Set<OnAppInfoLoadedListener> listeners = new HashSet<>();
6465
File exportDir = new File(
6566
Environment.getExternalStorageDirectory(), "mission_control");
6667
private String appId;
6768
private String appName;
68-
public static String consent;
6969

7070
@Override
7171
protected void onCreate (Bundle savedInstanceState) {
@@ -79,7 +79,7 @@ protected void onCreate (Bundle savedInstanceState) {
7979

8080
// Check if consent to contact external servers
8181
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
82-
consent = sharedPref.getString(MainActivity.CONSENT_PREF, MainActivity.CONSENT_NO);
82+
consent = sharedPref.getString(MainActivity.FIRST_START, MainActivity.CONSENT_NO);
8383

8484
// Set up paging
8585
DetailsPagesAdapter detailsPagesAdapter =
@@ -105,12 +105,9 @@ protected void onCreate (Bundle savedInstanceState) {
105105
@Override
106106
public void run () {
107107
app = PlayStore.getInfo(appId);
108-
runOnUiThread(new Runnable() {
109-
@Override
110-
public void run () {
111-
for (OnAppInfoLoadedListener listener : listeners) {
112-
listener.appInfoLoaded();
113-
}
108+
runOnUiThread(() -> {
109+
for (OnAppInfoLoadedListener listener : listeners) {
110+
listener.appInfoLoaded();
114111
}
115112
});
116113
}
@@ -131,7 +128,7 @@ public boolean onOptionsItemSelected (MenuItem item) {
131128
case android.R.id.home:
132129
NavUtils.navigateUpFromSameTask(this);
133130
return true;
134-
case R.id.menu_option_export_csv:
131+
case R.id.action_export_csv:
135132
if (hasPermissions()) {
136133
exportCsv();
137134
}
@@ -274,12 +271,7 @@ protected void onPostExecute (final Boolean success) {
274271
// Export successul, ask user to further share file!
275272
View v = findViewById(R.id.view_pager);
276273
Snackbar s = Snackbar.make(v, R.string.exported, Snackbar.LENGTH_LONG);
277-
s.setAction(R.string.share_csv, new View.OnClickListener() {
278-
@Override
279-
public void onClick (View v) {
280-
shareExport();
281-
}
282-
});
274+
s.setAction(R.string.share_csv, v1 -> shareExport());
283275
s.setActionTextColor(getResources().getColor(R.color.colorPrimary));
284276
s.show();
285277
}

app/src/main/java/net/kollnig/missioncontrol/MainActivity.java

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
import android.annotation.SuppressLint;
2121
import android.app.Activity;
22-
import android.content.DialogInterface;
2322
import android.content.Intent;
2423
import android.content.SharedPreferences;
2524
import android.net.Uri;
@@ -41,6 +40,7 @@
4140

4241
import net.kollnig.missioncontrol.main.AppBlocklistController;
4342
import net.kollnig.missioncontrol.main.AppsFragment;
43+
import net.kollnig.missioncontrol.main.SettingsActivity;
4444
import net.kollnig.missioncontrol.vpn.InConsumer;
4545
import net.kollnig.missioncontrol.vpn.OutConsumer;
4646
import net.kollnig.missioncontrol.vpn.OutFilter;
@@ -53,10 +53,10 @@
5353
public class MainActivity extends AppCompatActivity implements AntMonitorActivity,
5454
View.OnClickListener {
5555
private static final String TAG = MainActivity.class.getSimpleName();
56-
private final String APPS_FRAG_TAG = "appsFragTag";
57-
public static String CONSENT_PREF = "consent";
56+
public static String FIRST_START = "first-start";
5857
public static String CONSENT_YES = "yes";
5958
public static String CONSENT_NO = "no";
59+
private final String APPS_FRAG_TAG = "appsFragTag";
6060
SwitchCompat mSwitchMonitoring;
6161
Toolbar mToolbar;
6262
FragmentManager fm;
@@ -88,46 +88,49 @@ protected void onCreate (Bundle savedInstanceState) {
8888

8989
// Use click events only, for simplicity, disable swipe
9090
mSwitchMonitoring.setOnClickListener(this);
91-
mSwitchMonitoring.setOnTouchListener(new View.OnTouchListener() {
92-
@Override
93-
public boolean onTouch (View v, MotionEvent event) {
94-
return event.getActionMasked() == MotionEvent.ACTION_MOVE;
95-
}
96-
});
91+
mSwitchMonitoring.setOnTouchListener((v, event) -> event.getActionMasked() == MotionEvent.ACTION_MOVE);
9792

9893
// Initialise VPN controller
9994
mVpnController = VpnController.getInstance(this);
10095
VpnController.setDnsCacheEnabled(true);
10196

97+
// Initialise default settings (only first app start)
98+
android.support.v7.preference.PreferenceManager
99+
.setDefaultValues(this, R.xml.preferences, false);
100+
final SharedPreferences settingsPref =
101+
android.support.v7.preference.PreferenceManager
102+
.getDefaultSharedPreferences(this);
103+
Boolean showSystemApps = settingsPref.getBoolean
104+
(SettingsActivity.KEY_PREF_SYSTEMAPPS_SWITCH, false);
105+
102106
// Set up the bottom bottomNavigation
103107
fm = getSupportFragmentManager();
104108
Fragment fApps = fm.findFragmentByTag(APPS_FRAG_TAG);
105109
if (fApps != null) {
106110
fm.beginTransaction().show(fApps).commit();
107111
} else {
108-
fm.beginTransaction().add(R.id.main_container, AppsFragment.newInstance(), APPS_FRAG_TAG).commit();
112+
fm.beginTransaction().add
113+
(R.id.main_container, AppsFragment.newInstance(showSystemApps), APPS_FRAG_TAG)
114+
.commit();
109115
}
110116

111117
// Ask for consent to contact Google and other servers
112-
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
113-
final String consent = sharedPref.getString(CONSENT_PREF, null);
118+
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
119+
final Boolean firstStart = sharedPref.getBoolean(FIRST_START, true);
120+
121+
if (firstStart) {
122+
sharedPref.edit().putBoolean(FIRST_START, false).apply();
114123

115-
if (consent == null) {
116124
AlertDialog.Builder builder = new AlertDialog.Builder(this);
117125
builder.setMessage(R.string.confirm_google_info)
118126
.setTitle(R.string.external_servers);
119-
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
120-
public void onClick (DialogInterface dialog, int id) {
121-
sharedPref.edit().putString(CONSENT_PREF, CONSENT_YES).apply();
122-
dialog.dismiss();
123-
}
127+
builder.setPositiveButton(R.string.yes, (dialog, id) -> {
128+
settingsPref.edit().putBoolean
129+
(SettingsActivity.KEY_PREF_GOOGLEPLAY_SWITCH, true).apply();
130+
dialog.dismiss();
124131
});
125-
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
126-
@Override
127-
public void onClick (DialogInterface dialog, int i) {
128-
sharedPref.edit().putString(CONSENT_PREF, CONSENT_NO).apply();
129-
dialog.dismiss();
130-
}
132+
builder.setNegativeButton(R.string.no, (dialog, id) -> {
133+
dialog.dismiss();
131134
});
132135
AlertDialog dialog = builder.create();
133136
dialog.setCancelable(false); // avoid back button
@@ -143,12 +146,12 @@ public void onClick (DialogInterface dialog, int i) {
143146
*/
144147
private void startMonitoring () {
145148
// Check if we are connected to the internet
146-
if (!mVpnController.isConnectedToInternet()) {
149+
/*if (!mVpnController.isConnectedToInternet()) {
147150
Toast.makeText(MainActivity.this, R.string.no_service,
148151
Toast.LENGTH_LONG).show();
149152
updateMonitoringSwitch(true, false);
150153
return;
151-
}
154+
}*/
152155

153156
// Check if we have VPN rights from the user
154157
Intent intent = android.net.VpnService.prepare(MainActivity.this);
@@ -178,6 +181,8 @@ protected void onActivityResult (int request, int result, Intent data) {
178181

179182
// Connect - triggers onVpnStateChanged
180183
mVpnController.connect(null, outFilter, inConsumer, outConsumer);
184+
185+
Toast.makeText(this, R.string.instructions_monitoring, Toast.LENGTH_SHORT).show();
181186
} else {
182187
// enable the switch again so user can try again
183188
mSwitchMonitoring.setEnabled(true);
@@ -196,11 +201,15 @@ public boolean onCreateOptionsMenu (Menu menu) {
196201
@Override
197202
public boolean onOptionsItemSelected (MenuItem item) {
198203
switch (item.getItemId()) {
199-
case R.id.menu_option_about:
204+
case R.id.action_about:
200205
Uri aboutUri = Uri.parse(getString(R.string.about_url));
201206
Intent browserIntent = new Intent(Intent.ACTION_VIEW, aboutUri);
202207
startActivity(browserIntent);
203208
return true;
209+
case R.id.action_settings:
210+
Intent intent = new Intent(this, SettingsActivity.class);
211+
startActivity(intent);
212+
return true;
204213
}
205214
return super.onOptionsItemSelected(item);
206215
}

app/src/main/java/net/kollnig/missioncontrol/data/App.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
public class App implements Comparable<App> {
2323
public String name;
2424
public String id;
25+
public Boolean systemApp;
2526
public Integer trackerCount = 0;
2627
public Drawable icon;
2728

app/src/main/java/net/kollnig/missioncontrol/details/PolicyFragment.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,14 @@ public void onViewCreated (View v, Bundle savedInstanceState) {
100100
pbPolicy = v.findViewById(R.id.pbPolicy);
101101

102102
fab = v.findViewById(R.id.fab);
103-
fab.setOnClickListener(new View.OnClickListener() {
104-
@Override
105-
public void onClick (View v) {
106-
if (policyUrl == null) {
107-
Snackbar.make(v, getString(R.string.policy_loading_error), Snackbar.LENGTH_LONG)
108-
.show();
109-
} else {
110-
// Get URL
111-
Intent browserIntent = Common.browse(policyUrl);
112-
startActivity(browserIntent);
113-
}
103+
fab.setOnClickListener(v1 -> {
104+
if (policyUrl == null) {
105+
Snackbar.make(v1, getString(R.string.policy_loading_error), Snackbar.LENGTH_LONG)
106+
.show();
107+
} else {
108+
// Get URL
109+
Intent browserIntent = Common.browse(policyUrl);
110+
startActivity(browserIntent);
114111
}
115112
});
116113
fab.setVisibility(View.GONE);

0 commit comments

Comments
 (0)