Skip to content

Commit c5b9c3f

Browse files
committed
Add check for updates action
1 parent 02ecdd1 commit c5b9c3f

File tree

8 files changed

+226
-7
lines changed

8 files changed

+226
-7
lines changed

app/build.gradle

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
22

33
android {
44
compileSdkVersion 23
5-
buildToolsVersion "23.0.1"
5+
buildToolsVersion "23.0.2"
66

77
defaultConfig {
88
applicationId "com.nowsecure.android.vts"
@@ -17,6 +17,10 @@ android {
1717
minifyEnabled false
1818
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
1919
}
20+
21+
debug {
22+
applicationIdSuffix ".debug"
23+
}
2024
}
2125

2226
sourceSets.main {
@@ -44,9 +48,13 @@ dependencies {
4448
compile 'com.android.support:cardview-v7:23.1.1'
4549
compile 'com.android.support:design:23.1.1'
4650
compile 'com.github.paolorotolo:appintro:3.3.0'
51+
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta3'
52+
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'
53+
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
4754
compile 'commons-io:commons-io:2.4'
55+
compile 'io.reactivex:rxandroid:1.0.1'
4856
compile 'org.apache.commons:commons-compress:1.5'
49-
compile('com.github.afollestad.material-dialogs:core:0.8.5.0@aar') {
57+
compile('com.github.afollestad.material-dialogs:core:0.8.5.3@aar') {
5058
transitive = true
5159
}
5260
}

app/src/main/java/fuzion24/device/vulnerability/test/ui/MainActivity.java

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package fuzion24.device.vulnerability.test.ui;
22

3+
import android.app.DownloadManager;
4+
import android.content.BroadcastReceiver;
5+
import android.content.Context;
36
import android.content.Intent;
7+
import android.content.IntentFilter;
48
import android.content.res.Configuration;
59
import android.graphics.Color;
610
import android.net.Uri;
711
import android.os.Bundle;
12+
import android.os.Environment;
13+
import android.support.annotation.NonNull;
814
import android.support.design.widget.CoordinatorLayout;
915
import android.support.design.widget.FloatingActionButton;
1016
import android.support.design.widget.Snackbar;
@@ -17,14 +23,17 @@
1723
import android.view.MenuItem;
1824
import android.view.View;
1925
import android.widget.TextView;
26+
import android.widget.Toast;
2027

2128
import com.afollestad.materialdialogs.DialogAction;
2229
import com.afollestad.materialdialogs.MaterialDialog;
30+
import com.nowsecure.android.vts.BuildConfig;
2331
import com.nowsecure.android.vts.R;
2432

2533
import org.json.JSONException;
2634
import org.json.JSONObject;
2735

36+
import java.io.File;
2837
import java.util.ArrayList;
2938
import java.util.List;
3039

@@ -33,9 +42,15 @@
3342
import fuzion24.device.vulnerability.test.VulnerabilityTestResult;
3443
import fuzion24.device.vulnerability.test.VulnerabilityTestRunner;
3544
import fuzion24.device.vulnerability.test.adapter.RecyclerAdapter;
45+
import fuzion24.device.vulnerability.update.client.RetrofitClient;
46+
import fuzion24.device.vulnerability.update.model.GithubRelease;
47+
import fuzion24.device.vulnerability.update.service.GithubApiService;
3648
import fuzion24.device.vulnerability.util.DeviceInfo;
3749
import fuzion24.device.vulnerability.util.SharedPreferencesUtils;
3850
import fuzion24.device.vulnerability.vulnerabilities.VulnerabilityResultSerialzier;
51+
import rx.Subscriber;
52+
import rx.android.schedulers.AndroidSchedulers;
53+
import rx.schedulers.Schedulers;
3954

4055
public class MainActivity extends AppCompatActivity {
4156

@@ -45,10 +60,27 @@ public class MainActivity extends AppCompatActivity {
4560

4661
private DeviceInfo devInfo;
4762
private ArrayList<VulnerabilityTestResult> testResults;
48-
private RecyclerView recyclerView;
4963
private TextView emptyView;
5064
private CoordinatorLayout coordinatorLayout;
51-
RecyclerAdapter recyclerAdapter;
65+
private RecyclerAdapter recyclerAdapter;
66+
private String downloadFilename;
67+
68+
// Download manager.
69+
private DownloadManager downloadManager;
70+
private BroadcastReceiver onComplete = new BroadcastReceiver() {
71+
72+
@Override
73+
public void onReceive(Context context, Intent intent) {
74+
String apkDirectory = String.format("%s/%s", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), downloadFilename);
75+
Intent downloadIntent = new Intent(Intent.ACTION_VIEW);
76+
77+
downloadIntent.setDataAndType(Uri.fromFile(new File(apkDirectory)), "application/vnd.android.package-archive");
78+
downloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
79+
80+
startActivity(downloadIntent);
81+
}
82+
83+
};
5284

5385
@Override
5486
protected void onCreate(Bundle savedInstanceState) {
@@ -66,9 +98,9 @@ protected void onCreate(Bundle savedInstanceState) {
6698
testResults = new ArrayList<>();
6799
}
68100

101+
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
69102
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
70103
emptyView = (TextView) findViewById(R.id.emptyView);
71-
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
72104
recyclerAdapter = new RecyclerAdapter(MainActivity.this, testResults);
73105

74106
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
@@ -82,10 +114,10 @@ protected void onCreate(Bundle savedInstanceState) {
82114
final TextView tvBuildModel = (TextView) findViewById(R.id.buildModel);
83115
final TextView tvBuildRelease = (TextView) findViewById(R.id.buildRelease);
84116
final TextView tvBuildSDK = (TextView) findViewById(R.id.buildSDK);
85-
86117
final TextView tvBuildABIList = (TextView) findViewById(R.id.buildABIList);
87118

88119
devInfo = DeviceInfo.getDeviceInfo();
120+
89121
tvBuildFingerPrint.setText(devInfo.getBuildFingerPrint());
90122
tvBuildID.setText(devInfo.getBuildID());
91123
tvKernelVersion.setText(devInfo.getKernelVersion());
@@ -96,6 +128,7 @@ protected void onCreate(Bundle savedInstanceState) {
96128
tvBuildSDK.setText(devInfo.getBuildSDK());
97129

98130
StringBuilder sb = new StringBuilder();
131+
99132
for (String s : devInfo.getSupportedABIS()) {
100133
sb.append(s);
101134
sb.append(" ");
@@ -111,6 +144,11 @@ public void onClick(View v) {
111144
runTestsSuit();
112145
}
113146
});
147+
148+
// Set the download callbacks.
149+
downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
150+
151+
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
114152
}
115153

116154
@Override
@@ -192,11 +230,74 @@ public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
192230

193231
return true;
194232

233+
case R.id.menu_check_updates:
234+
checkForUpdates();
235+
236+
return true;
237+
195238
default:
196239
return super.onOptionsItemSelected(item);
197240
}
198241
}
199242

243+
private void checkForUpdates() {
244+
final MaterialDialog mProgressDialog = new MaterialDialog.Builder(this)
245+
.title(R.string.loading)
246+
.content(R.string.checking_updates)
247+
.cancelable(false)
248+
.progress(true, 0)
249+
.show();
250+
251+
GithubApiService service = RetrofitClient.getRetrofitClient().create(GithubApiService.class);
252+
253+
service.getLatestRelease().subscribeOn(Schedulers.io())
254+
.observeOn(AndroidSchedulers.mainThread())
255+
.unsubscribeOn(Schedulers.io())
256+
.subscribe(new Subscriber<GithubRelease>() {
257+
258+
@Override
259+
public void onCompleted() {
260+
mProgressDialog.dismiss();
261+
}
262+
263+
@Override
264+
public void onError(Throwable e) {
265+
Toast.makeText(MainActivity.this, R.string.update_error, Toast.LENGTH_LONG).show();
266+
}
267+
268+
@Override
269+
public void onNext(final GithubRelease githubRelease) {
270+
Double currentVersion = Double.parseDouble(BuildConfig.VERSION_NAME.replace("v.", ""));
271+
Double repositoryVersion = Double.parseDouble(githubRelease.getTag_name().replace("v.", ""));
272+
273+
// Check if a new version is available.
274+
if (repositoryVersion > currentVersion) {
275+
new MaterialDialog.Builder(MainActivity.this)
276+
.title(R.string.update_available_title)
277+
.content(getString(R.string.update_avaiable_description, githubRelease.getTag_name()))
278+
.positiveText(R.string.update)
279+
.negativeText(R.string.dismiss)
280+
.onPositive(new MaterialDialog.SingleButtonCallback() {
281+
@Override
282+
public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) {
283+
downloadFilename = String.format("AndroidVTS-%s.apk", githubRelease.getTag_name());
284+
downloadManager.enqueue(new DownloadManager.Request(Uri.parse(githubRelease.getAssets().get(0).getBrowser_download_url()))
285+
.setTitle("Android VTS")
286+
.setDescription(getString(R.string.downloading_update))
287+
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, downloadFilename));
288+
}
289+
})
290+
.show();
291+
292+
return;
293+
}
294+
295+
Toast.makeText(MainActivity.this, R.string.no_update_available, Toast.LENGTH_LONG).show();
296+
}
297+
298+
});
299+
}
300+
200301
private void runTestsSuit() {
201302
new VulnerabilityTestRunner(MainActivity.this, true, new ResultsCallback() {
202303
@Override
@@ -288,4 +389,11 @@ protected void onSaveInstanceState(final Bundle outState) {
288389
outState.putSerializable(SERIALIZABLE_RESULTS, testResults);
289390
}
290391

392+
@Override
393+
public void onDestroy() {
394+
super.onDestroy();
395+
396+
unregisterReceiver(onComplete);
397+
}
398+
291399
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package fuzion24.device.vulnerability.update.client;
2+
3+
import retrofit2.GsonConverterFactory;
4+
import retrofit2.Retrofit;
5+
import retrofit2.RxJavaCallAdapterFactory;
6+
7+
/**
8+
* Retrofit client.
9+
*/
10+
11+
public class RetrofitClient {
12+
13+
public static Retrofit getRetrofitClient() {
14+
return new Retrofit.Builder()
15+
.baseUrl("https://api.github.com/")
16+
.addConverterFactory(GsonConverterFactory.create())
17+
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
18+
.build();
19+
}
20+
21+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package fuzion24.device.vulnerability.update.model;
2+
3+
import java.util.List;
4+
5+
/**
6+
* Github releases model.
7+
*/
8+
9+
public class GithubRelease {
10+
11+
private final String name;
12+
private final String tag_name;
13+
private final List<GithubReleaseAssets> assets;
14+
15+
public GithubRelease(String name, String tag_name, List<GithubReleaseAssets> assets) {
16+
this.name = name;
17+
this.tag_name = tag_name;
18+
this.assets = assets;
19+
}
20+
21+
public String getName() {
22+
return name;
23+
}
24+
25+
public String getTag_name() {
26+
return tag_name;
27+
}
28+
29+
public List<GithubReleaseAssets> getAssets() {
30+
return assets;
31+
}
32+
33+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package fuzion24.device.vulnerability.update.model;
2+
3+
/**
4+
* Github releases assets model.
5+
*/
6+
7+
public class GithubReleaseAssets {
8+
9+
private final String browser_download_url;
10+
11+
public GithubReleaseAssets(String browser_download_url) {
12+
this.browser_download_url = browser_download_url;
13+
}
14+
15+
public String getBrowser_download_url() {
16+
return browser_download_url;
17+
}
18+
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package fuzion24.device.vulnerability.update.service;
2+
3+
import fuzion24.device.vulnerability.update.model.GithubRelease;
4+
import retrofit2.http.GET;
5+
import rx.Observable;
6+
7+
/**
8+
* API Github service.
9+
*/
10+
11+
public interface GithubApiService {
12+
13+
@GET("repos/nowsecure/android-vts/releases/latest")
14+
Observable<GithubRelease> getLatestRelease();
15+
16+
}

app/src/main/res/menu/main_menu.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@
1818
android:checkable="true"
1919
app:showAsAction="never" />
2020

21+
<item
22+
android:id="@+id/menu_check_updates"
23+
android:title="@string/menu_check_for_updates"
24+
app:showAsAction="never" />
25+
2126
</menu>

app/src/main/res/values/strings.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<string name="appintro_security_description">The security of the device changes overtime, make sure you run periodically scans.</string>
1010
<string name="appintro_sharing">Sharing</string>
1111
<string name="appintro_sharing_description">Sharing the tests results will help to increase the knowledge about the android devices that contains security issues.</string>
12+
<string name="checking_updates">Checking for application updates...</string>
1213
<string name="cve_date">CVE Date: </string>
1314
<string name="cvssv2">CVSSV2: </string>
1415
<string name="description">Description</string>
@@ -26,6 +27,7 @@
2627
<string name="dialog_automatic_sharing_description">Do you want automatically share the scan results for research purpose? The device information collected does not contains unique identifiers or private information. Nothing related to your Google (or any other) account is collected.</string>
2728
<string name="dialog_automatic_sharing_title">Sharing scan results</string>
2829
<string name="dismiss">Dismiss</string>
30+
<string name="downloading_update">Downloading the new version.</string>
2931
<string name="empty_results">Start the scan to get the results</string>
3032
<string name="error_exporting_results">Error exporting the results.</string>
3133
<string name="error_test">Error running the test:\n%s</string>
@@ -35,10 +37,13 @@
3537
<string name="global_sharing">Sharing</string>
3638
<string name="Impact">Impact</string>
3739
<string name="information_not_available">Information not available yet.</string>
40+
<string name="loading">Loading</string>
41+
<string name="menu_check_for_updates">Check for updates</string>
3842
<string name="menu_share_results_automatically">Share results automatically</string>
3943
<string name="more_information">More Information</string>
4044
<string name="my_device_is_vulnerable_info">Now What?</string>
4145
<string name="names">Names</string>
46+
<string name="no_update_available">There are no updates available.</string>
4247
<string name="notification_new_tests">New tests are available</string>
4348
<string name="patches">Patches</string>
4449
<string name="run_tests">Please run the tests first</string>
@@ -49,10 +54,14 @@
4954
<string name="scan_details_vulnerable_message">Your device is vulnerable</string>
5055
<string name="share_results_via">Share results via</string>
5156
<string name="show_details">Show Details</string>
57+
<string name="splashscreen_description">Android Vulnerability Test Suite</string>
5258
<string name="start">Start</string>
5359
<string name="submit_results">Share for Research</string>
5460
<string name="test_result_failure">Vulnerable</string>
5561
<string name="test_result_success">Not Vulnerable</string>
56-
<string name="splashscreen_description">Android Vulnerability Test Suite</string>
62+
<string name="update">Update</string>
63+
<string name="update_avaiable_description">A new update is available (version %s). Do you want to update to the latest version?</string>
64+
<string name="update_available_title">An update is available</string>
65+
<string name="update_error">It was not possible to check for updates. Please try again later.</string>
5766

5867
</resources>

0 commit comments

Comments
 (0)