From ac06bd8dc7045a1f61c47dda79622c3b4908a3c4 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 17 Jan 2018 18:15:38 +0100 Subject: #8811 set vpn option to top of navigation drawer, minor ux improvements --- .../AbstractProviderDetailActivity.java | 2 + .../java/se/leap/bitmaskclient/ConfigHelper.java | 34 +++++++++- .../main/java/se/leap/bitmaskclient/Dashboard.java | 3 +- .../java/se/leap/bitmaskclient/MainActivity.java | 34 ++++++++++ .../ProviderCredentialsBaseActivity.java | 3 + .../java/se/leap/bitmaskclient/StartActivity.java | 34 +++++++++- .../drawer/NavigationDrawerFragment.java | 74 ++++++++-------------- 7 files changed, 129 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java index a92f8f96..d521a3a9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java @@ -21,6 +21,7 @@ import butterknife.InjectView; import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; public abstract class AbstractProviderDetailActivity extends ButterKnifeActivity { @@ -83,6 +84,7 @@ public abstract class AbstractProviderDetailActivity extends ButterKnifeActivity } else { Log.d(TAG, "use anonymously selected"); intent = new Intent(getApplicationContext(), MainActivity.class); + intent.setAction(ACTION_SHOW_VPN_FRAGMENT); } intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); startActivity(intent); diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java index 0e861059..ccdf5064 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java @@ -16,6 +16,7 @@ */ package se.leap.bitmaskclient; +import android.content.SharedPreferences; import android.support.annotation.NonNull; import android.util.Log; @@ -28,8 +29,9 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL; import java.security.KeyFactory; import java.security.KeyStore; import java.security.KeyStoreException; @@ -45,6 +47,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import static android.R.attr.name; +import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; /** * Stores constants, and implements auxiliary methods used across all Bitmask Android classes. @@ -256,4 +259,33 @@ public class ConfigHelper { public static KeyStore getKeystore() { return keystore_trusted; } + + + public static String getCurrentProviderName(@NonNull SharedPreferences preferences) { + try { + JSONObject providerDefintion = new JSONObject(preferences.getString(Provider.KEY, "")); + return providerDefintion.getString(Provider.DOMAIN); + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + public static boolean providerInSharedPreferences(@NonNull SharedPreferences preferences) { + return preferences.getBoolean(PROVIDER_CONFIGURED, false); + } + + public static Provider getSavedProviderFromSharedPreferences(@NonNull SharedPreferences preferences) { + Provider provider = new Provider(); + try { + provider.setUrl(new URL(preferences.getString(Provider.MAIN_URL, ""))); + provider.define(new JSONObject(preferences.getString(Provider.KEY, ""))); + provider.setCACert(preferences.getString(Provider.CA_CERT, "")); + } catch (MalformedURLException | JSONException e) { + e.printStackTrace(); + } + + return provider; + } + } diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 82ff9db8..5ccb48b5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -18,7 +18,6 @@ package se.leap.bitmaskclient; import android.annotation.SuppressLint; import android.app.AlertDialog; -import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -42,8 +41,8 @@ import java.util.List; import java.util.Map; import butterknife.InjectView; -import se.leap.bitmaskclient.fragments.AboutFragment; import de.blinkt.openvpn.core.VpnStatus; +import se.leap.bitmaskclient.fragments.AboutFragment; import se.leap.bitmaskclient.userstatus.SessionDialog; import se.leap.bitmaskclient.userstatus.User; import se.leap.bitmaskclient.userstatus.UserStatusFragment; diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java index 41e496bb..40a9052c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java @@ -1,7 +1,9 @@ package se.leap.bitmaskclient; +import android.content.Intent; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.AppCompatActivity; @@ -16,6 +18,7 @@ public class MainActivity extends AppCompatActivity { private static Provider provider = new Provider(); private static FragmentManagerEnhanced fragmentManager; + public final static String ACTION_SHOW_VPN_FRAGMENT = "action_show_vpn_fragment"; /** * Fragment managing the behaviors, interactions and presentation of the navigation drawer. @@ -37,6 +40,7 @@ public class MainActivity extends AppCompatActivity { R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout)); + handleIntentAction(getIntent()); } public static void sessionDialog(Bundle resultData) { @@ -48,4 +52,34 @@ public class MainActivity extends AppCompatActivity { } } + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + handleIntentAction(intent); + } + + private void handleIntentAction(Intent intent) { + if (intent == null || intent.getAction() == null) { + return; + } + + Fragment fragment = null; + + switch (intent.getAction()) { + case ACTION_SHOW_VPN_FRAGMENT: + fragment = new VpnFragment(); + break; + default: + break; + } + + if (fragment != null) { + fragmentManager.beginTransaction() + .replace(R.id.container, fragment) + .commit(); + } + } + + } diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java index c61b078f..1ed64559 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java @@ -16,6 +16,8 @@ import butterknife.OnClick; import se.leap.bitmaskclient.userstatus.SessionDialog; import se.leap.bitmaskclient.userstatus.User; +import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; + /** * Created by fupduck on 09.01.18. */ @@ -109,6 +111,7 @@ public abstract class ProviderCredentialsBaseActivity extends ButterKnifeActivit //MainActivity.sessionDialog(resultData); } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { Intent intent = new Intent(activity, MainActivity.class); + intent.setAction(ACTION_SHOW_VPN_FRAGMENT); activity.startActivity(intent); } else if (resultCode == ProviderAPI.FAILED_LOGIN) { //MainActivity.sessionDialog(resultData); diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java index 43d7f152..bb01ddc0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java @@ -15,7 +15,9 @@ import java.lang.annotation.RetentionPolicy; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.userstatus.User; +import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; +import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; /** @@ -71,9 +73,8 @@ public class StartActivity extends Activity { VpnStatus.initLogCache(getApplicationContext().getCacheDir()); User.init(getString(R.string.default_username)); - // go to Dashboard - Intent intent = new Intent(this, MainActivity.class); - startActivity(intent); + prepareEIP(); + } /** @@ -141,4 +142,31 @@ public class StartActivity extends Activity { preferences.edit().putInt(PREFERENCES_APP_VERSION, versionCode).apply(); } + private void prepareEIP() { + boolean provider_exists = ConfigHelper.providerInSharedPreferences(preferences); + if (provider_exists) { + Provider provider = ConfigHelper.getSavedProviderFromSharedPreferences(preferences); + if(!provider.isConfigured()) { + configureLeapProvider(); + } else { + Log.d(TAG, "vpn provider is configured"); + + //buildDashboard(getIntent().getBooleanExtra(EIP_RESTART_ON_BOOT, false)); +// user_status_fragment.restoreSessionStatus(savedInstanceState); + Intent intent = new Intent(this, MainActivity.class); + intent.setAction(MainActivity.ACTION_SHOW_VPN_FRAGMENT); + startActivity(intent); + } + } else { + configureLeapProvider(); + } + } + + private void configureLeapProvider() { + if (getIntent().hasExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) { + getIntent().removeExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE); + } + startActivityForResult(new Intent(this, ConfigurationWizard.class), REQUEST_CODE_CONFIGURE_LEAP); + } + } diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java index 566134dd..ef59185a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -6,7 +6,6 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; -import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.view.GravityCompat; @@ -27,15 +26,14 @@ import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; +import se.leap.bitmaskclient.ConfigHelper; import se.leap.bitmaskclient.ConfigurationWizard; -import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.VpnFragment; import se.leap.bitmaskclient.fragments.AboutFragment; import se.leap.bitmaskclient.fragments.LogFragment; -import se.leap.bitmaskclient.userstatus.User; -import se.leap.bitmaskclient.userstatus.UserStatusFragment; +import static android.content.Context.MODE_PRIVATE; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; @@ -46,11 +44,6 @@ import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; */ public class NavigationDrawerFragment extends Fragment { - /** - * Remember the position of the selected item. - */ - private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position"; - /** * Per the design guidelines, you should show the drawer on launch until the user manually * expands it. This shared preference tracks this. @@ -67,8 +60,8 @@ public class NavigationDrawerFragment extends Fragment { private ListView mDrawerSettingsListView; private ListView mDrawerAccountsListView; private View mFragmentContainerView; + private ArrayAdapter accountListAdapter; - private int mCurrentSelectedPosition = 0; private boolean mFromSavedInstanceState; private boolean mUserLearnedDrawer; @@ -85,20 +78,8 @@ public class NavigationDrawerFragment extends Fragment { // Read in the flag indicating whether or not the user has demonstrated awareness of the // drawer. See PREF_USER_LEARNED_DRAWER for details. - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); - mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false); - - preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); - - if (savedInstanceState != null) { - mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION); - mFromSavedInstanceState = true; - } - - // Select either the default item (0) or the last selected item. - if (mDrawerSettingsListView != null) { - selectItem(mDrawerSettingsListView, mCurrentSelectedPosition); - } + preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + mUserLearnedDrawer = preferences.getBoolean(PREF_USER_LEARNED_DRAWER, false); } @Override @@ -142,12 +123,10 @@ public class NavigationDrawerFragment extends Fragment { android.R.layout.simple_list_item_activated_1, android.R.id.text1, new String[]{ - getString(R.string.vpn_fragment_title), getString(R.string.switch_provider_menu_option), getString(R.string.log_fragment_title), getString(R.string.about_fragment_title), })); - mDrawerSettingsListView.setItemChecked(mCurrentSelectedPosition, true); mDrawerAccountsListView = mDrawerView.findViewById(R.id.accountList); mDrawerAccountsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @@ -157,14 +136,21 @@ public class NavigationDrawerFragment extends Fragment { } }); - mDrawerAccountsListView.setAdapter(new ArrayAdapter( - actionBar.getThemedContext(), + + + accountListAdapter = new ArrayAdapter<>(actionBar.getThemedContext(), android.R.layout.simple_list_item_activated_1, - android.R.id.text1, - new String[]{ - User.userName(), - })); - mDrawerAccountsListView.setItemChecked(mCurrentSelectedPosition, true); + android.R.id.text1); + + String providerName = ConfigHelper.getCurrentProviderName(preferences); + if (providerName == null) { + //TODO: ADD A header to the ListView containing a useful message. + //TODO 2: disable switchProvider + } else { + accountListAdapter.add(providerName); + } + + mDrawerAccountsListView.setAdapter(accountListAdapter); mFragmentContainerView = activity.findViewById(fragmentId); mDrawerLayout = drawerLayout; @@ -204,9 +190,7 @@ public class NavigationDrawerFragment extends Fragment { // The user manually opened the drawer; store this flag to prevent auto-showing // the navigation drawer automatically in the future. mUserLearnedDrawer = true; - SharedPreferences sp = PreferenceManager - .getDefaultSharedPreferences(getActivity()); - sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply(); + preferences.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply(); } getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu() @@ -228,11 +212,9 @@ public class NavigationDrawerFragment extends Fragment { }); mDrawerLayout.addDrawerListener(mDrawerToggle); - selectItem(mDrawerSettingsListView, 0); } private void selectItem(AdapterView list, int position) { - mCurrentSelectedPosition = position; if (list != null) { ((ListView) list).setItemChecked(position, true); } @@ -255,7 +237,6 @@ public class NavigationDrawerFragment extends Fragment { @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition); } @Override @@ -307,31 +288,26 @@ public class NavigationDrawerFragment extends Fragment { Fragment fragment = null; if (parent == mDrawerAccountsListView) { - mTitle = User.userName(); - fragment = new UserStatusFragment(); - Bundle bundle = new Bundle(); - bundle.putBoolean(Provider.ALLOW_REGISTRATION, new Provider().allowsRegistration()); - fragment.setArguments(bundle); + mTitle = getString(R.string.vpn_fragment_title); + fragment = new VpnFragment(); } else { Log.d("Drawer", String.format("Selected position %d", position)); switch (position) { - case 1: + case 0: // TODO STOP VPN // if (provider.hasEIP()) eip_fragment.stopEipIfPossible(); preferences.edit().clear().apply(); startActivityForResult(new Intent(getActivity(), ConfigurationWizard.class), REQUEST_CODE_SWITCH_PROVIDER); break; - case 2: + case 1: mTitle = getString(R.string.log_fragment_title); fragment = new LogFragment(); break; - case 3: + case 2: mTitle = getString(R.string.about_fragment_title); fragment = new AboutFragment(); break; default: - mTitle = getString(R.string.vpn_fragment_title); - fragment = new VpnFragment(); break; } } -- cgit v1.2.3 From 276453c90042eae745681275da25c6894fb6554c Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 17 Jan 2018 18:45:49 +0100 Subject: #8811 unit test added --- .../se/leap/bitmaskclient/ConfigHelperTest.java | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 app/src/test/java/se/leap/bitmaskclient/ConfigHelperTest.java diff --git a/app/src/test/java/se/leap/bitmaskclient/ConfigHelperTest.java b/app/src/test/java/se/leap/bitmaskclient/ConfigHelperTest.java new file mode 100644 index 00000000..a9a5733d --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/ConfigHelperTest.java @@ -0,0 +1,57 @@ +package se.leap.bitmaskclient; + +import android.content.SharedPreferences; + +import org.junit.Before; +import org.junit.Test; + +import se.leap.bitmaskclient.testutils.MockSharedPreferences; +import se.leap.bitmaskclient.testutils.TestSetupHelper; + +import static org.junit.Assert.*; +import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +/** + * Created by cyberta on 17.01.18. + */ +public class ConfigHelperTest { + + private SharedPreferences mockPreferences; + + + @Before + public void setup() { + mockPreferences = new MockSharedPreferences(); + } + + @Test + public void providerInSharedPreferences_notInPreferences_returnsFalse() throws Exception { + assertFalse(ConfigHelper.providerInSharedPreferences(mockPreferences)); + } + + @Test + public void providerInSharedPreferences_inPreferences_returnsTrue() throws Exception { + mockPreferences.edit().putBoolean(PROVIDER_CONFIGURED, true).apply(); + assertTrue(ConfigHelper.providerInSharedPreferences(mockPreferences)); + } + + @Test + public void getSavedProviderFromSharedPreferences_notInPreferences_returnsDefaultProvider() throws Exception { + Provider provider = ConfigHelper.getSavedProviderFromSharedPreferences(mockPreferences); + assertFalse(provider.isConfigured()); + } + + @Test + public void getSavedProviderFromSharedPreferences_notInPreferences_returnsConfiguredProvider() throws Exception { + mockPreferences.edit() + .putString(Provider.KEY, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"))) + .putString(Provider.MAIN_URL, "https://riseup.net") + .putString(Provider.CA_CERT, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"))) + .apply(); + Provider provider = ConfigHelper.getSavedProviderFromSharedPreferences(mockPreferences); + assertTrue(provider.isConfigured()); + } + + +} \ No newline at end of file -- cgit v1.2.3 From 7d4129b2854e25c42b6df766d30671c91fc699ae Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jan 2018 12:10:37 +0100 Subject: #8799 fix confusing cancel dialog --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9536d96e..96b79222 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -64,7 +64,7 @@ Initiating connection Cancel connection? There is a connection attempt in progress. Do you wish to cancel it? - In order to avoid leaking your personal information, please close your browser and start a private window after disconnecting the Encrypted VPN Internet Access. Thanks. + Turn off VPN connection? When the VPN is off, you may leak personal information to your Internet provider or local network. "Not running! Insecure connection!" Connection Secure. It seems there is a problem with the provider. -- cgit v1.2.3 From 7abdfa72e372d927bf2dec3185e05588cb1a94b7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jan 2018 13:14:38 +0100 Subject: #8822 adds leakCanary library to Bitmask for analyzing memory leaks --- app/build.gradle | 13 +++++++++++ .../java/se/leap/bitmaskclient/BitmaskApp.java | 26 +++++++++++++++++++++- .../drawer/NavigationDrawerFragment.java | 7 ++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index cb865ecd..a71cff57 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,6 +77,8 @@ dependencies { androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.6.3' testCompile 'junit:junit:4.12' testCompile 'org.json:json:20170516' + debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4' + releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' compile 'com.jakewharton:butterknife:6.1.0' provided 'com.squareup.dagger:dagger-compiler:1.2.2' compile 'com.github.pedrovgs:renderers:1.5' @@ -92,6 +94,17 @@ dependencies { compile 'com.android.support:support-fragment:26.1.0' } +// Ensure the no-op dependency is always used in JVM tests. +configurations.all { config -> + if (config.name.contains('UnitTest')) { + config.resolutionStrategy.eachDependency { details -> + if (details.requested.group == 'com.squareup.leakcanary' && details.requested.name == 'leakcanary-android') { + details.useTarget(group: details.requested.group, name: 'leakcanary-android-no-op', version: details.requested.version) + } + } + } +} + def processFileInplace(file, Closure processText) { def text = file.text file.write(processText(text)) diff --git a/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java b/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java index 88a01b62..f9e45b79 100644 --- a/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java +++ b/app/src/main/java/se/leap/bitmaskclient/BitmaskApp.java @@ -1,6 +1,10 @@ package se.leap.bitmaskclient; import android.app.Application; +import android.content.Context; + +import com.squareup.leakcanary.LeakCanary; +import com.squareup.leakcanary.RefWatcher; /** * Created by cyberta on 24.10.17. @@ -8,11 +12,31 @@ import android.app.Application; public class BitmaskApp extends Application { + private RefWatcher refWatcher; + @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; + } + refWatcher = LeakCanary.install(this); + // Normal app init code...*/ PRNGFixes.apply(); - //TODO: add LeakCanary! } + /** + * Use this method to get a RefWatcher object that checks for memory leaks in the given context. + * Call refWatcher.watch(this) to check if all references get garbage collected. + * @param context + * @return the RefWatcher object + */ + public static RefWatcher getRefWatcher(Context context) { + BitmaskApp application = (BitmaskApp) context.getApplicationContext(); + return application.refWatcher; + } + + } diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java index 566134dd..84c407d7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -36,6 +36,7 @@ import se.leap.bitmaskclient.fragments.LogFragment; import se.leap.bitmaskclient.userstatus.User; import se.leap.bitmaskclient.userstatus.UserStatusFragment; +import static se.leap.bitmaskclient.BitmaskApp.getRefWatcher; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; @@ -287,6 +288,12 @@ public class NavigationDrawerFragment extends Fragment { return super.onOptionsItemSelected(item); } + @Override + public void onDestroy() { + super.onDestroy(); + getRefWatcher(getActivity()).watch(this); + } + /** * Per the navigation drawer design guidelines, updates the action bar to show the global app * 'context', rather than just what's in the current screen. -- cgit v1.2.3 From f7dfa7bc000b802570dddc19e8f274193e25b336 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jan 2018 15:56:27 +0100 Subject: #8822 add no-op leak canary to Beta build type --- app/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/app/build.gradle b/app/build.gradle index a71cff57..b28d9f35 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -79,6 +79,7 @@ dependencies { testCompile 'org.json:json:20170516' debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' + betaCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' compile 'com.jakewharton:butterknife:6.1.0' provided 'com.squareup.dagger:dagger-compiler:1.2.2' compile 'com.github.pedrovgs:renderers:1.5' -- cgit v1.2.3