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.elkriefy.android.apps.permissionmigrationguide; import android.Manifest; import android.annotation.TargetApi; import android.content.pm.PackageManager; import android.location.Location; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; import com.google.android.gms.location.LocationServices; import java.util.ArrayList; import java.util.List; /** * Location sample showcase the Location API and retrieve the last know location. * * This have 3 different methods: * 1. Doing so before Android Marshmallow * 2. Doing so in Android Marshmallow * 3. Doing so but using the Support library to handle Runtime permissions in Android Marshmallow * and above. */ public class MainActivity extends AppCompatActivity implements ConnectionCallbacks, OnConnectionFailedListener { protected static final String TAG = "MainActivity"; /** * Can only use lower 8 bits for requestCode when using support library solution */ private static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 4; private static final int NO_PERMISSIONS_CHECK = 0; private static final int MARSHMALLOW_PERMISSIONS_CHECK = 1; private static final int SUPPORT_LIBRARY_PERMISSION_CHECK = 2; /** * Provides the entry point to Google Play services. */ protected GoogleApiClient mGoogleApiClient; /** * Represents a geographical location. */ protected Location mLastLocation; protected String mLatitudeLabel; protected String mLongitudeLabel; protected TextView mLatitudeText; protected TextView mLongitudeText; protected Spinner mSpinner; protected int mState; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); mState = NO_PERMISSIONS_CHECK; mLatitudeLabel = getResources().getString(R.string.latitude_label); mLongitudeLabel = getResources().getString(R.string.longitude_label); mLatitudeText = (TextView) findViewById((R.id.latitude_text)); mLongitudeText = (TextView) findViewById((R.id.longitude_text)); mSpinner = (Spinner) findViewById((R.id.permission_case_chooser)); buildGoogleApiClient(); populateSpinner(); } private void populateSpinner() { List<String> list = new ArrayList<>(); list.add("No permissions check"); list.add("Android Marshmallow permissions"); list.add("Support Library Permissions"); ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, list); dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mSpinner.setAdapter(dataAdapter); mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (mGoogleApiClient.isConnected()) { mGoogleApiClient.disconnect(); } switch (position) { case NO_PERMISSIONS_CHECK: mState = NO_PERMISSIONS_CHECK; break; case MARSHMALLOW_PERMISSIONS_CHECK: mState = MARSHMALLOW_PERMISSIONS_CHECK; break; case SUPPORT_LIBRARY_PERMISSION_CHECK: mState = SUPPORT_LIBRARY_PERMISSION_CHECK; break; } mGoogleApiClient.connect(); } @Override public void onNothingSelected(AdapterView<?> parent) { if (mGoogleApiClient.isConnected()) { mGoogleApiClient.disconnect(); } } }); } /** * Builds a GoogleApiClient. Uses the addApi() method to request the LocationServices API. */ protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApiIfAvailable(LocationServices.API).build(); } @Override protected void onStop() { super.onStop(); if (mGoogleApiClient.isConnected()) { mGoogleApiClient.disconnect(); } } private void getLocation() { // Provides a simple way of getting a device's location and is well suited for // applications that do not require a fine-grained location and that do not need location // updates. Gets the best and most recent location currently available, which may be null // in rare cases when a location is not available. mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (mLastLocation != null) { mLatitudeText.setText(String.format("%s: %f", mLatitudeLabel, mLastLocation.getLatitude())); mLongitudeText.setText(String.format("%s: %f", mLongitudeLabel, mLastLocation.getLongitude())); } else { Toast.makeText(this, R.string.no_location_detected, Toast.LENGTH_LONG).show(); } } @Override public void onConnectionFailed(ConnectionResult result) { // Refer to the javadoc for ConnectionResult to see what error codes might be returned in // onConnectionFailed. Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); } @Override public void onConnectionSuspended(int cause) { // The connection to Google Play services was lost for some reason. We call connect() to // attempt to re-establish the connection. Log.i(TAG, "Connection suspended"); mGoogleApiClient.connect(); } /** * Runs when a GoogleApiClient object successfully connects. */ @Override public void onConnected(Bundle connectionHint) { switch (mState) { case NO_PERMISSIONS_CHECK: getLocation(); break; case MARSHMALLOW_PERMISSIONS_CHECK: if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) marshmallowPermissionsFlowOnConnected(); else { Toast.makeText(this, R.string.not_marshmallow, Toast.LENGTH_LONG).show(); } break; case SUPPORT_LIBRARY_PERMISSION_CHECK: supportLibPermissionsOnConnected(); break; } } @TargetApi(Build.VERSION_CODES.M) private void marshmallowPermissionsFlowOnConnected() { if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { getLocation(); } else { // Should we show an explanation? if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) { // Explain to the user why we need to read the contacts Toast.makeText(this, R.string.permission_rationale, Toast.LENGTH_LONG).show(); } requestPermissions(new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { marshmallowonRequestPermissionsResult(requestCode, grantResults); } private void marshmallowonRequestPermissionsResult(int requestCode, @NonNull int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted getLocation(); } else { // permission denied, boo! Disable the // functionality that depends on this permission. Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_LONG).show(); } return; } } } private void supportLibPermissionsOnConnected() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { getLocation(); } else { // Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { // Explain to the user why we need to read the contacts Toast.makeText(this, R.string.permission_rationale, Toast.LENGTH_LONG).show(); } ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); } } }