From 643a7fd67a2d97d455950d3ee1bb1767d87dd6a1 Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Thu, 4 Jan 2018 15:22:22 -0500 Subject: [PATCH 01/10] Streamline handling the broadcast receiver and intent filter --- .../portauthority/activity/MainActivity.java | 73 +++++++------------ 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java index acf4cd43..efa57ba8 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java +++ b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java @@ -76,7 +76,6 @@ public final class MainActivity extends AppCompatActivity implements MainAsyncRe private ProgressDialog scanProgressDialog; private Handler signalHandler = new Handler(); private Handler scanHandler; - private BroadcastReceiver receiver; private IntentFilter intentFilter = new IntentFilter(); private HostAdapter hostAdapter; private List hosts = Collections.synchronizedList(new ArrayList()); @@ -85,6 +84,25 @@ public final class MainActivity extends AppCompatActivity implements MainAsyncRe private DownloadAsyncTask portTask; private boolean sortAscending; + private BroadcastReceiver receiver = new BroadcastReceiver() { + + /** + * Detect if a network connection has been lost or established + * @param context + * @param intent + */ + @Override + public void onReceive(Context context, Intent intent) { + NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + if (info == null) { + return; + } + + getNetworkInfo(info); + } + + }; + /** * Activity created * @@ -117,8 +135,9 @@ protected void onCreate(Bundle savedInstanceState) { setupHostsAdapter(); setupDrawer(); - setupReceivers(); setupHostDiscovery(); + + intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); } /** @@ -384,33 +403,6 @@ private void setClip(CharSequence label, String text) { } } - /** - * Sets up and registers receivers - */ - private void setupReceivers() { - receiver = new BroadcastReceiver() { - - /** - * Detect if a network connection has been lost or established - * @param context - * @param intent - */ - @Override - public void onReceive(Context context, Intent intent) { - NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); - if (info == null) { - return; - } - - getNetworkInfo(info); - } - - }; - - intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - registerReceiver(receiver, intentFilter); - } - /** * Gets network information about the device and updates various UI elements */ @@ -604,6 +596,9 @@ private void getExternalIp() { public void onPause() { super.onPause(); + unregisterReceiver(receiver); + signalHandler.removeCallbacksAndMessages(null); + if (scanProgressDialog != null) { scanProgressDialog.dismiss(); } @@ -622,25 +617,11 @@ public void onPause() { } /** - * Activity destroyed - */ - @Override - public void onDestroy() { - super.onDestroy(); - - signalHandler.removeCallbacksAndMessages(null); - - if (receiver != null) { - unregisterReceiver(receiver); - } - } - - /** - * Activity restarted + * Activity resumed. */ @Override - public void onRestart() { - super.onRestart(); + public void onResume() { + super.onResume(); registerReceiver(receiver, intentFilter); } From fb17079c388bf3ba9fed1f272a0b4c7c42217f9b Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Thu, 4 Jan 2018 15:24:10 -0500 Subject: [PATCH 02/10] Fix travis builds using android 27 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b31175c1..52c7ec63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: - secure: "em+bEb3nWLV7f+Dt4y9/OH2Lpf6mscT9E52kXhSEm/PiFpTtzlx7BgHGlpsYVwsMf0e7x2AdF/yzq4c7ugoMqWmFXMthgFUKcLTXqW/IeARGz3smMXnyScRoaFElDm0Q33fxiqDlU7UVA4j1FysR5GqTU10MasJgGpoyTthRQvra0LU8zwI4IMiASfa8Tij5LclsbaTpcgB4TdXtBmbpKQAUzjvV/ZfLsYQ950C0rbVKk9T1xtc8d5BTbggwHWbMMqGn6RFvSCQioeI/Q6Daak6zDglUY+JE/1BnzlGzoba9C7TLZV4+TQkmB5kc6FtKqSXycjwJSKm3wQFYOzJrLMPqMtlmaAeTEs5yBIYtIIAiID+hbeUKvWTpoUxwUYz7s7XLikJRdxe7iBlhdy3qv+FdGOJjV9g/xeSVXISvXzcKp2sNdU+FABBBDAA2CKWrZOXuzPAh8iYxLnt649hQFAw99ylkn75+LpJgq7gRUO87Fde0Zw3vYhLIS8UH3OBtggV1yrYHuKXWUyfkiA/xcm+NSFgIXJzGvYlOZWS+uZvXeh7wJz5CF0t3m6emBoqX6JAXQ/t9SgwGX8lwbLPK3HiYBnTMEDxb6qpIiYa8E8tfudA1YNyeszG8mZtiErJf9YleagACuASwPFsLb8Bg9BNJX5X89+VrbzPbncZD9Tc=" before_install: + - yes | sdkmanager "platforms;android-27" - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- addons: From a2ef828467f3e57c18d11af4f379c51342becbc5 Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Thu, 4 Jan 2018 15:28:02 -0500 Subject: [PATCH 03/10] Be a bit more efficient when comparing IPs as hosts get added to the list --- .../com/aaronjwood/portauthority/activity/MainActivity.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java index efa57ba8..f96cacd3 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java +++ b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java @@ -50,10 +50,10 @@ import com.squareup.leakcanary.LeakCanary; import java.io.IOException; -import java.math.BigInteger; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -681,8 +681,8 @@ public void run() { @Override public int compare(Host lhs, Host rhs) { try { - int leftIp = new BigInteger(InetAddress.getByName(lhs.getIp()).getAddress()).intValue(); - int rightIp = new BigInteger(InetAddress.getByName(rhs.getIp()).getAddress()).intValue(); + int leftIp = ByteBuffer.wrap(InetAddress.getByName(lhs.getIp()).getAddress()).getInt(); + int rightIp = ByteBuffer.wrap(InetAddress.getByName(rhs.getIp()).getAddress()).getInt(); return leftIp - rightIp; } catch (UnknownHostException ignored) { From 226f71bf4ce6317187ff1e69461705cb398dbb2c Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Thu, 4 Jan 2018 15:38:29 -0500 Subject: [PATCH 04/10] Workaround known Android bug --- app/src/main/AndroidManifest.xml | 1 + .../portauthority/PortAuthority.java | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 app/src/main/java/com/aaronjwood/portauthority/PortAuthority.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c4afc32f..6f79851c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ Date: Thu, 4 Jan 2018 15:42:48 -0500 Subject: [PATCH 05/10] Install leak canary using the newer way --- .../com/aaronjwood/portauthority/PortAuthority.java | 10 ++++++++++ .../portauthority/activity/MainActivity.java | 6 ------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/aaronjwood/portauthority/PortAuthority.java b/app/src/main/java/com/aaronjwood/portauthority/PortAuthority.java index 47f9204f..b1dcc00e 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/PortAuthority.java +++ b/app/src/main/java/com/aaronjwood/portauthority/PortAuthority.java @@ -3,11 +3,21 @@ import android.app.Application; import android.os.Process; +import com.squareup.leakcanary.LeakCanary; + public class PortAuthority extends Application { @Override public void onCreate() { super.onCreate(); + + if (LeakCanary.isInAnalyzerProcess(this)) { + // This process is dedicated to LeakCanary for heap analysis. + // You should not init your app in this process. + return; + } + + LeakCanary.install(this); checkReplacingState(); // Workaround for https://issuetracker.google.com/issues/36972466 } diff --git a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java index f96cacd3..448eaf5d 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java +++ b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java @@ -32,7 +32,6 @@ import android.widget.RelativeLayout; import android.widget.TextView; -import com.aaronjwood.portauthority.BuildConfig; import com.aaronjwood.portauthority.R; import com.aaronjwood.portauthority.adapter.HostAdapter; import com.aaronjwood.portauthority.async.DownloadAsyncTask; @@ -47,7 +46,6 @@ import com.aaronjwood.portauthority.response.MainAsyncResponse; import com.aaronjwood.portauthority.utils.Errors; import com.aaronjwood.portauthority.utils.UserPreference; -import com.squareup.leakcanary.LeakCanary; import java.io.IOException; import java.net.InetAddress; @@ -112,10 +110,6 @@ public void onReceive(Context context, Intent intent) { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (BuildConfig.DEBUG) { - LeakCanary.install(getApplication()); - } - setContentView(R.layout.activity_main); internalIp = findViewById(R.id.internalIpAddress); From e0163e20d1a67c22c2f7ed0f0345206ce1a050f0 Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Thu, 4 Jan 2018 15:54:16 -0500 Subject: [PATCH 06/10] Optimizations --- .../portauthority/activity/MainActivity.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java index 448eaf5d..25969736 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java +++ b/app/src/main/java/com/aaronjwood/portauthority/activity/MainActivity.java @@ -9,6 +9,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.database.sqlite.SQLiteException; import android.net.NetworkInfo; import android.net.wifi.WifiManager; @@ -227,18 +228,20 @@ private void setupHostDiscovery() { */ @Override public void onClick(View v) { + Resources resources = getResources(); + Context context = getApplicationContext(); try { if (!wifi.isEnabled()) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.wifiDisabled)); + Errors.showError(context, resources.getString(R.string.wifiDisabled)); return; } if (!wifi.isConnectedWifi()) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.notConnectedWifi)); + Errors.showError(context, resources.getString(R.string.notConnectedWifi)); return; } } catch (Wireless.NoWifiManagerException | Wireless.NoConnectivityManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.failedWifiManager)); + Errors.showError(context, resources.getString(R.string.failedWifiManager)); return; } @@ -246,7 +249,7 @@ public void onClick(View v) { try { numSubnetHosts = wifi.getNumberOfHostsInWifiSubnet(); } catch (Wireless.NoWifiManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.failedSubnetHosts)); + Errors.showError(context, resources.getString(R.string.failedSubnetHosts)); return; } @@ -258,8 +261,8 @@ public void onClick(View v) { scanProgressDialog = new ProgressDialog(MainActivity.this, R.style.DialogTheme); scanProgressDialog.setCancelable(false); - scanProgressDialog.setTitle(getResources().getString(R.string.hostScan)); - scanProgressDialog.setMessage(String.format(getResources().getString(R.string.subnetHosts), numSubnetHosts)); + scanProgressDialog.setTitle(resources.getString(R.string.hostScan)); + scanProgressDialog.setMessage(String.format(resources.getString(R.string.subnetHosts), numSubnetHosts)); scanProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); scanProgressDialog.setProgress(0); scanProgressDialog.setMax(numSubnetHosts); @@ -267,11 +270,11 @@ public void onClick(View v) { try { Integer ip = wifi.getInternalWifiIpAddress(Integer.class); - new ScanHostsAsyncTask(MainActivity.this, db).execute(ip, wifi.getInternalWifiSubnet(), UserPreference.getHostSocketTimeout(getApplicationContext())); + new ScanHostsAsyncTask(MainActivity.this, db).execute(ip, wifi.getInternalWifiSubnet(), UserPreference.getHostSocketTimeout(context)); discoverHostsBtn.setAlpha(.3f); discoverHostsBtn.setEnabled(false); } catch (UnknownHostException | Wireless.NoWifiManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.notConnectedWifi)); + Errors.showError(context, resources.getString(R.string.notConnectedWifi)); } } }); @@ -404,6 +407,8 @@ private void getNetworkInfo(NetworkInfo info) { setupMac(); getExternalIp(); + final Resources resources = getResources(); + final Context context = getApplicationContext(); try { boolean enabled = wifi.isEnabled(); if (!info.isConnected() || !enabled) { @@ -419,7 +424,7 @@ private void getNetworkInfo(NetworkInfo info) { return; } } catch (Wireless.NoWifiManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.failedWifiManager)); + Errors.showError(context, resources.getString(R.string.failedWifiManager)); } if (!info.isConnected()) { @@ -438,17 +443,17 @@ public void run() { try { speed = wifi.getLinkSpeed(); } catch (Wireless.NoWifiManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.failedLinkSpeed)); + Errors.showError(context, resources.getString(R.string.failedLinkSpeed)); return; } try { signal = wifi.getSignalStrength(); } catch (Wireless.NoWifiManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.failedSignal)); + Errors.showError(context, resources.getString(R.string.failedSignal)); return; } - signalStrength.setText(String.format(getResources().getString(R.string.signalLink), signal, speed)); + signalStrength.setText(String.format(resources.getString(R.string.signalLink), signal, speed)); signalHandler.postDelayed(this, TIMER_INTERVAL); } }, 0); @@ -460,13 +465,13 @@ public void run() { try { wifiSsid = wifi.getSSID(); } catch (Wireless.NoWifiManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.failedSsid)); + Errors.showError(context, resources.getString(R.string.failedSsid)); return; } try { wifiBssid = wifi.getBSSID(); } catch (Wireless.NoWifiManagerException e) { - Errors.showError(getApplicationContext(), getResources().getString(R.string.failedBssid)); + Errors.showError(context, resources.getString(R.string.failedBssid)); return; } From 3db30e5b9bcf11ade8e7e3fc7eeed8142fb67bf9 Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Thu, 4 Jan 2018 16:18:56 -0500 Subject: [PATCH 07/10] Move away from deprecated HTTP lib and use OkHttp going forward --- app/build.gradle | 2 +- app/proguard.pro | 8 ++++++- .../portauthority/async/WanIpAsyncTask.java | 24 +++++++------------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c938acf5..1a70f3f6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,6 @@ sonarqube { android { compileSdkVersion 27 buildToolsVersion '27.0.2' - useLibrary 'org.apache.http.legacy' defaultConfig { minSdkVersion 14 @@ -68,6 +67,7 @@ android { dependencies { compile 'com.android.support:support-v4:27.0.2' compile 'com.android.support:appcompat-v7:27.0.2' + compile 'com.squareup.okhttp3:okhttp:3.9.1' compile 'jcifs:jcifs:1.3.17' compile 'dnsjava:dnsjava:2.1.7' //This does absolutely nothing diff --git a/app/proguard.pro b/app/proguard.pro index 34183354..26ef9e2c 100644 --- a/app/proguard.pro +++ b/app/proguard.pro @@ -2,4 +2,10 @@ -dontwarn org.xbill.DNS.spi.DNSJavaNameServiceDescriptor -keep class org.xbill.** { *; } -keepattributes EnclosingMethod --keepattributes InnerClasses \ No newline at end of file +-keepattributes InnerClasses + +-dontwarn okhttp3.** +-dontwarn okio.** +-dontwarn javax.annotation.** +# A resource is loaded with a relative path so the package of this class must be preserved. +-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase diff --git a/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java b/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java index 4cbe571f..45bca7cf 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java +++ b/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java @@ -4,17 +4,13 @@ import com.aaronjwood.portauthority.response.MainAsyncResponse; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.util.EntityUtils; - import java.io.IOException; import java.lang.ref.WeakReference; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + public class WanIpAsyncTask extends AsyncTask { // IP service is 100% open source https://github.com/aaronjwood/public-ip-api @@ -39,18 +35,16 @@ public WanIpAsyncTask(MainAsyncResponse delegate) { @Override protected String doInBackground(Void... params) { String error = "Couldn't get your external IP"; - HttpClient httpclient = new DefaultHttpClient(); - HttpGet httpget = new HttpGet(EXTERNAL_IP_SERVICE); + OkHttpClient httpClient = new OkHttpClient(); + Request request = new Request.Builder().url(EXTERNAL_IP_SERVICE).build(); try { - HttpResponse response = httpclient.execute(httpget); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + Response response = httpClient.newCall(request).execute(); + if (!response.isSuccessful()) { return error; } - return EntityUtils.toString(response.getEntity()).trim(); - } catch (ClientProtocolException e) { - return error; + return response.body().string().trim(); } catch (IOException e) { return error; } From 05cc3dfaf15a63f9b4e6a16858665e5fbbe294f0 Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Tue, 9 Jan 2018 20:15:21 -0500 Subject: [PATCH 08/10] Fix resource leak in certain cases --- .../com/aaronjwood/portauthority/async/WanIpAsyncTask.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java b/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java index 45bca7cf..abe352a9 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java +++ b/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java @@ -10,6 +10,7 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import okhttp3.ResponseBody; public class WanIpAsyncTask extends AsyncTask { @@ -40,11 +41,13 @@ protected String doInBackground(Void... params) { try { Response response = httpClient.newCall(request).execute(); + ResponseBody body = response.body(); if (!response.isSuccessful()) { + body.close(); return error; } - return response.body().string().trim(); + return response.body().string().trim(); // string() closes the resource automatically. } catch (IOException e) { return error; } From 15400ced63e84e42186ebdf78f14771efd9f3127 Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Mon, 15 Jan 2018 20:03:48 -0500 Subject: [PATCH 09/10] Try with resources (finally!) --- app/build.gradle | 4 ++-- .../aaronjwood/portauthority/async/WanIpAsyncTask.java | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1a70f3f6..3e8b40d1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,8 +28,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } buildTypes { diff --git a/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java b/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java index abe352a9..123002b9 100644 --- a/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java +++ b/app/src/main/java/com/aaronjwood/portauthority/async/WanIpAsyncTask.java @@ -1,5 +1,6 @@ package com.aaronjwood.portauthority.async; +import android.annotation.SuppressLint; import android.os.AsyncTask; import com.aaronjwood.portauthority.response.MainAsyncResponse; @@ -10,7 +11,6 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import okhttp3.ResponseBody; public class WanIpAsyncTask extends AsyncTask { @@ -34,20 +34,18 @@ public WanIpAsyncTask(MainAsyncResponse delegate) { * @return External IP address */ @Override + @SuppressLint("NewApi") protected String doInBackground(Void... params) { String error = "Couldn't get your external IP"; OkHttpClient httpClient = new OkHttpClient(); Request request = new Request.Builder().url(EXTERNAL_IP_SERVICE).build(); - try { - Response response = httpClient.newCall(request).execute(); - ResponseBody body = response.body(); + try (Response response = httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { - body.close(); return error; } - return response.body().string().trim(); // string() closes the resource automatically. + return response.body().string().trim(); } catch (IOException e) { return error; } From f5697322decf52bde346bb77d907cc3a949d827d Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Thu, 1 Feb 2018 21:48:34 -0800 Subject: [PATCH 10/10] Bump versions --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3e8b40d1..e83fc8b0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,8 +21,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 27 - versionCode 53 - versionName "2.2.4" + versionCode 54 + versionName "2.2.6" applicationId "com.aaronjwood.portauthority" setProperty("archivesBaseName", "PortAuthority-$versionName") }