Skip to content

Commit fa26186

Browse files
committed
Add Per-App Mode to the Project.
1 parent 4b1e217 commit fa26186

File tree

15 files changed

+544
-23
lines changed

15 files changed

+544
-23
lines changed

app/build.gradle

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ buildscript {
1111
}
1212

1313
android {
14-
compileSdkVersion 19
14+
compileSdkVersion 25
1515
buildToolsVersion "23.0.1"
16+
useLibrary 'org.apache.http.legacy'
1617

1718
defaultConfig {
1819
applicationId "com.vm.shadowsocks"
1920
minSdkVersion 14
20-
targetSdkVersion 19
21+
targetSdkVersion 25
2122
versionCode 1
2223
versionName "1.1"
2324
}
@@ -44,6 +45,8 @@ dependencies {
4445
compile 'com.embarkmobile:zxing-android-integration:2.0.0@aar'
4546
compile 'com.google.zxing:core:3.0.1'
4647
compile 'org.bouncycastle:bcprov-jdk15on:1.52'
48+
compile 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
49+
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
4750
compile('com.googlecode.json-simple:json-simple:1.1.1') {
4851
exclude group: 'junit', module: 'junit'
4952
exclude group: 'org.hamcrest', module: 'hamcrest-core'

app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
</intent-filter>
2323
</activity>
2424

25+
<activity
26+
android:name="com.vm.shadowsocks.ui.AppManager"
27+
android:label="@string/proxied_apps"
28+
android:excludeFromRecents="true"
29+
android:launchMode="singleTask"/>
30+
2531
<service
2632
android:name="com.vm.shadowsocks.core.LocalVpnService"
2733
android:permission="android.permission.BIND_VPN_SERVICE">
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.vm.shadowsocks.core;
2+
3+
import android.graphics.drawable.Drawable;
4+
5+
public class AppInfo {
6+
private Drawable appIcon;
7+
private String appLabel;
8+
private String pkgName;
9+
10+
public AppInfo() {
11+
}
12+
13+
public Drawable getAppIcon() {
14+
return this.appIcon;
15+
}
16+
17+
public String getAppLabel() {
18+
return this.appLabel;
19+
}
20+
21+
public String getPkgName() {
22+
return this.pkgName;
23+
}
24+
25+
public void setAppIcon(Drawable var1) {
26+
this.appIcon = var1;
27+
}
28+
29+
public void setAppLabel(String var1) {
30+
this.appLabel = var1;
31+
}
32+
33+
public void setPkgName(String var1) {
34+
this.pkgName = var1;
35+
}
36+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package com.vm.shadowsocks.core;
2+
3+
import android.content.Context;
4+
import android.content.SharedPreferences;
5+
import android.graphics.drawable.Drawable;
6+
import android.os.Build;
7+
8+
import org.json.JSONArray;
9+
import org.json.JSONObject;
10+
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
import static android.content.Context.MODE_PRIVATE;
15+
16+
public class AppProxyManager {
17+
public static boolean isLollipopOrAbove = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
18+
19+
public static AppProxyManager Instance;
20+
private static final String PROXY_APPS = "PROXY_APPS";
21+
private Context mContext;
22+
23+
public List<AppInfo> mlistAppInfo = new ArrayList<AppInfo>();
24+
public List<AppInfo> proxyAppInfo = new ArrayList<AppInfo>();
25+
26+
public AppProxyManager(Context context){
27+
this.mContext = context;
28+
Instance = this;
29+
readProxyAppsList();
30+
}
31+
32+
public void removeProxyApp(String pkg){
33+
for (AppInfo app : this.proxyAppInfo) {
34+
if (app.getPkgName().equals(pkg)){
35+
proxyAppInfo.remove(app);
36+
break;
37+
}
38+
}
39+
writeProxyAppsList();
40+
}
41+
42+
public void addProxyApp(String pkg){
43+
for (AppInfo app : this.mlistAppInfo) {
44+
if (app.getPkgName().equals(pkg)){
45+
proxyAppInfo.add(app);
46+
break;
47+
}
48+
}
49+
writeProxyAppsList();
50+
}
51+
52+
public boolean isAppProxy(String pkg){
53+
for (AppInfo app : this.proxyAppInfo) {
54+
if (app.getPkgName().equals(pkg)){
55+
return true;
56+
}
57+
}
58+
return false;
59+
}
60+
61+
private void readProxyAppsList() {
62+
SharedPreferences preferences = mContext.getSharedPreferences("shadowsocksProxyUrl", MODE_PRIVATE);
63+
String tmpString = preferences.getString(PROXY_APPS, "");
64+
try {
65+
if (proxyAppInfo != null){
66+
proxyAppInfo.clear();
67+
}
68+
if (tmpString.isEmpty()){
69+
return;
70+
}
71+
JSONArray jsonArray = new JSONArray(tmpString);
72+
for (int i = 0; i < jsonArray.length() ; i++){
73+
JSONObject object = jsonArray.getJSONObject(i);
74+
AppInfo appInfo = new AppInfo();
75+
appInfo.setAppLabel(object.getString("label"));
76+
appInfo.setPkgName(object.getString("pkg"));
77+
proxyAppInfo.add(appInfo);
78+
}
79+
} catch (Exception e){
80+
e.printStackTrace();
81+
}
82+
}
83+
84+
private void writeProxyAppsList() {
85+
SharedPreferences preferences = mContext.getSharedPreferences("shadowsocksProxyUrl", MODE_PRIVATE);
86+
try {
87+
JSONArray jsonArray = new JSONArray();
88+
for (int i = 0; i < proxyAppInfo.size() ; i++){
89+
JSONObject object = new JSONObject();
90+
AppInfo appInfo = proxyAppInfo.get(i);
91+
object.put("label", appInfo.getAppLabel());
92+
object.put("pkg", appInfo.getPkgName());
93+
jsonArray.put(object);
94+
}
95+
SharedPreferences.Editor editor = preferences.edit();
96+
editor.putString(PROXY_APPS, jsonArray.toString());
97+
editor.apply();
98+
} catch (Exception e){
99+
e.printStackTrace();
100+
}
101+
}
102+
}

app/src/main/java/com/vm/shadowsocks/core/LocalVpnService.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ String getAppInstallID() {
140140
appInstallID = UUID.randomUUID().toString();
141141
Editor editor = preferences.edit();
142142
editor.putString("AppInstallID", appInstallID);
143-
editor.commit();
143+
editor.apply();
144144
}
145145
return appInstallID;
146146
}
@@ -385,6 +385,22 @@ private ParcelFileDescriptor establishVPN() throws Exception {
385385
}
386386
}
387387

388+
if (AppProxyManager.isLollipopOrAbove){
389+
if (AppProxyManager.Instance.proxyAppInfo.size() == 0){
390+
writeLog("Proxy All Apps");
391+
}
392+
for (AppInfo app : AppProxyManager.Instance.proxyAppInfo){
393+
try{
394+
builder.addAllowedApplication(app.getPkgName());
395+
writeLog("Proxy App: " + app.getAppLabel());
396+
} catch (Exception e){
397+
writeLog("Proxy App Fail: " + app.getAppLabel());
398+
}
399+
}
400+
} else {
401+
writeLog("No Pre-App proxy, due to low Android version.");
402+
}
403+
388404
Intent intent = new Intent(this, MainActivity.class);
389405
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
390406
builder.setConfigureIntent(pendingIntent);

0 commit comments

Comments
 (0)