Java tutorial
/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jimandreas.android.designlibdemo; import android.Manifest; import android.annotation.SuppressLint; import android.content.Intent; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.support.design.widget.BottomNavigationView; import android.support.design.widget.CollapsingToolbarLayout; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.ActivityCompat; import android.support.v7.widget.Toolbar; import android.text.Html; import android.text.Spanned; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; import java.util.concurrent.TimeUnit; import butterknife.BindView; import butterknife.ButterKnife; public class Leak1TestActivity extends BottomNavViewBaseActivity implements LocationListener { private static final int WHOAMI_NAVBAR_MENUID = R.id.action_leak1; @SuppressWarnings("unused") private static final String TAG = "LeakTestActivity"; public static final String EXTRA_NAME = "plumber"; @BindView(R.id.leak_title) TextView leak_title; @BindView(R.id.leak_text) TextView leak_text; @BindView(R.id.more_button) FloatingActionButton more_button; @BindView(R.id.bottom_navigation) BottomNavigationView bottomNavigationView; // private static Drawable leaked_drawable; @SuppressWarnings("FieldCanBeLocal") private LocationManager locationManager; @Override public BottomNavigationView getBottomNavigationView() { return bottomNavigationView; } @Override public int getActivityMenuID() { return WHOAMI_NAVBAR_MENUID; } @Override public int getContentViewId() { return R.layout.leak_detail; } @SuppressLint("SetTextI18n") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.leak_detail); ButterKnife.bind(this); Intent intent = getIntent(); final String leakTestName = intent.getStringExtra(EXTRA_NAME); final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); collapsingToolbar.setTitle(leakTestName); loadBackdrop(); /** * This leak is courtesy of: * * https://medium.com/freenet-engineering/memory-leaks-in-android-identify-treat-and-avoid-d0b1233acc8#.9sanu6r7h */ leak_title.setText(R.string.leak1); String desc_raw = "Switch between the activities by selecting the BottomNavigationView item." + " This should leak the listener in the code" + " and produce a LeakCanary response.\n\n" + "This leak is courtesy of the entry by: \n\n" + "<big><strong>Johan Olsson</big></strong>\n\n" + "on his post to medium.com titled:\n\n" + "<big><strong>Memory leaks in Androididentify, treat and avoid</big></strong>\n" + "\nFor more information, press the FAB (floating action button)."; desc_raw = desc_raw.replace("\n", "<br>"); Spanned desc; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { desc = Html.fromHtml(desc_raw, Html.FROM_HTML_MODE_LEGACY); } else { //noinspection deprecation desc = Html.fromHtml(desc_raw); } leak_text.setText(desc); /** * And here is the actual leak! */ locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. Log.e(TAG, "******* Do not have Manifest permission for Location access!!"); return; } try { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, TimeUnit.MINUTES.toMillis(5), 100, this); } catch (Exception e) { Toast.makeText(this, "Sorry can't do this test, no location service", Toast.LENGTH_LONG).show(); } /* * FAB button (floating action button = FAB) to get more information * No more snackbar - until it is "BottomNavigationView" sensitive... */ more_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse( "https://medium.com/freenet-engineering/memory-leaks-in-android-identify-treat-and-avoid-d0b1233acc8#.9sanu6r7h")); startActivity(intent); } }); } private void loadBackdrop() { final ImageView imageView = (ImageView) findViewById(R.id.backdrop); Glide.with(this).load(R.drawable.leak_1).centerCrop().into(imageView); } /** * required methods for LocationListener interface implementation */ @Override public void onLocationChanged(Location location) { } @Override public void onStatusChanged(String s, int i, Bundle bundle) { } @Override public void onProviderEnabled(String s) { } @Override public void onProviderDisabled(String s) { } }