I'm writing an app in which its only function is acting as a receiver for Bluetooth Low Energy. The app is useless if the user does not allow BLE. When the app is started for the first time, I want it to ask the user for Locations Permission (since Android requires it for BLE). I bring the permissions dialog up, but the rest of the app continues while the user is reading the dialog, starting BLEScanner and all that. I want the app to pause while the user is reading the dialog and deciding what to do. Here's my setup:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
//More UI preparation stuff
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
Where "PermissionDialog" is a different class that uses an DialogFragment to explain why the app needs the permission and then closes/restarts the app. In this case, the rest of the app continues, attempting to do Bluetooth stuff while the user is still reading the permission dialog that has popped up! Naively, I thought I could use a synchronize lock to do it, as below, but in this case, the callback is never called:
private final Object initLock = new Object();
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
Log.i("Lock", "At the lock!");
try {
synchronized (initLock) {
initLock.wait();
}
}
catch (InterruptedException e) {
//TODO find out what to do here
}
Log.i("Lock", "Past the lock!");
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
synchronized (initLock){
initLock.notify();
}
}
else{
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
}
What's the proper way to do this? I have a few ideas, but they all balloon in scope. Do I need to make another class that inherits AppCompatActivity to do the permissions and I call it as a thread? But then how do I know where the onRequestPermissionResult callback will go? I'm at a loss.
Put the code inside your //More UI preparation stuff to a new method. After the permissions, say 'init()'
private void init(){
//More UI preparation stuff
}
Then inside onCreate, if permission is already granted, call init(); otherwise request permission.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
} else {
init();
}
}
Now handle the user's response inside onRequestPermissionsResult - If user has granted, initialize the UI, otherwise block the feature and/or notify the user about the issue.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
init();
} else{
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
}
PS: For this same purpose, I have prepared a library which makes this process a lot easier. Have a look at my library.
You can use EasyPermissions and implement EasyPermissions.PermissionCallbacks to resolve it.
And add this annotation:#AfterPermissionGranted before the method you want to run
such as :
AfterPermissionGranted(PERMISSION_REQUESTCODE_BASE)
private void requestPerminssions(){
if(EasyPermissions.hasPermissions(this,PERMISSIONS)){
int hasCityData=config.getInt("isDataEmpty",0);
if(hasCityData==0){
new CountryInfoThread().execute();
}else {
new LocalPositionThread().execute();
}
}
}
I ended up using a private variable:
private boolean readyToStart = false;
In this way:
#Override
protected void onCreate(Bundle savedInstanceState) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
else{
readyToStart = true;
}
}
#Override
protected void onResume() {
super.onResume();
if (readyToStart) {
startBluetooth();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[],
int[] grantResults) {
Log.i("Permission", "Callback made");
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
else{
startBluetooth();
}
}
}
}
}
Related
I want developing app who listent to user every time and when keyword said so doing something.
for that I used vosk-api
I declaring IntentService. currently when user click on swich botton in the bottom navigation the service is stop. How I can run the service all the time in the background something like ok google?
the code is:
public class MainActivity extends AppCompatActivity {
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Check if user has given permission to record audio
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent(this, MyIntentService.class);
startService(intent);
} else {
Log.e("MainActivity", "RECORD_AUDIO not allowed");
}
}
}
public class MyIntentService extends IntentService {
private SpeechService speechService;
private Model model;
public MyIntentService() {
super("MyIntentService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
initRecognizer();
speechService.addListener(new RecognitionListener() {
#Override
public void onPartialResult(String s) {
Log.d("MyIntentService", s + "\n");
if (s.contains("me"))
Toast.makeText(getApplicationContext(), "coollll!!", Toast.LENGTH_SHORT).show();
}
#Override
public void onResult(String s) {
Log.d("MyIntentService", s + "\n");
if (s.contains("me"))
Toast.makeText(getApplicationContext(), "coollll!!", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(Exception e) {
Log.d("MyIntentService", "Error");
}
#Override
public void onTimeout() {
speechService.cancel();
speechService = null;
Log.d("MyIntentService", "onTimeout");
}
});
speechService.startListening();
}
public void initRecognizer(){
Assets assets;
try {
assets = new Assets(getApplicationContext());
File assetDir = assets.syncAssets();
model = new Model(assetDir.toString() + "/model-android");
KaldiRecognizer rec = new KaldiRecognizer(model, 16000.0f);
speechService = new SpeechService(rec, 16000.0f);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks!
I did this by creating a foreground service that implements RecognitionListener. But I started with the vosk demo app.
I call initModel() inside of onCreate method in a service. In the callback of the initModel method I call recognizeMicrophone method that is the same as in the demo app.
I have the following class, that is extended by all my activities, where I want to save the last location using LocationServices.
Debugging it seems that permissions are granted, and I enter the onComplete method, but task.getResult() is always null. How is this possible?
public class MyAppCompatActivity extends AppCompatActivity {
private static final int LOCATION_REQUEST_CODE = 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
LOCATION_REQUEST_CODE);
} else
setUserLocation();
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case LOCATION_REQUEST_CODE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
setUserLocation();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
#SuppressLint("MissingPermission")
private void setUserLocation() {
LocationServices.getFusedLocationProviderClient(this).getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
ROUserInfo user = UserManager.getROUserInfo();
if(user==null || task.getResult()==null)
return;
user.User._Position._Latitude=task.getResult().getLatitude();
user.User._Position._Longitude=task.getResult().getLongitude();
UserManager.updateUserOnServer(user);
}
});
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have to ask for a permission when starting the app, however, the rest of the app start working before there is an answer to the dialog box which leads to the problem that the activity does not get the permission to use it until it is restarted even if the permission is granted.
How can I wait for a response before continuing with the rest of the app?
I faced the same issue in one of my apps, I needed to have all permissions ready on a virtual assistant chat screen. I collect Location, Audio and Storage permissions in a dummy Activity with some checkboxes that reflect their status. When my app has all three essential permissions, then, I make it jump from the dummy Activity to the main Chat Activity.
I'm pasting the entire Dummy Activity code here, it might need some cleanup, so just take what you need:
public class bootActivity extends Activity {
Context ctx;
private CheckBox checkboxLocation;
private CheckBox checkboxAudioRecording;
private CheckBox checkboxStorage;
private Activity thisActivity;
private String[] permissionsArray=new String[]{Manifest.permission.RECORD_AUDIO,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.WRITE_EXTERNAL_STORAGE,};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app.loge("BOOTING....START");
setContentView(R.layout.activity_boot);
thisActivity=this;
app.setBootingTRUE(getApplicationContext());
ctx=getApplicationContext();
//BIND UI
checkboxLocation=(CheckBox)findViewById(R.id.checkboxlocation);
checkboxLocation.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b==true) {
if (needPermissionLocation()) {
app.loge("Requesting LOCATION permission");
ActivityCompat.requestPermissions(thisActivity, permissionsArray,appPermissionsCallbackConstant);
}
}
refreshUI();
if((!needPermissionLocation())&&(!needPermissionRecordAudio())&&(!(needPermissionStorage()))){
launchApp();
}
}
});
checkboxAudioRecording=(CheckBox)findViewById(R.id.checkboxaudiorecording);
checkboxAudioRecording.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b==true) {
if (needPermissionRecordAudio()) {
app.loge("Requesting RECORDING permission");
ActivityCompat.requestPermissions(thisActivity, permissionsArray, appPermissionsCallbackConstant);
}
}
refreshUI();
if((!needPermissionLocation())&&(!needPermissionRecordAudio())&&(!(needPermissionStorage()))){
launchApp();
}
}
});
checkboxStorage=(CheckBox)findViewById(R.id.checkboxstorage);
checkboxStorage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b==true) {
if (needPermissionStorage()) {
app.loge("Requesting STORAGE permissions");
ActivityCompat.requestPermissions(thisActivity, permissionsArray, appPermissionsCallbackConstant);
}
}
refreshUI();
if((!needPermissionLocation())&&(!needPermissionRecordAudio())&&(!(needPermissionStorage()))){
launchApp();
}
}
});
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
if(data!=null) {
app.logy("URI:" + data.toString());
String userinput=data.getQueryParameter("input");
app.logy("User Input: "+userinput);
if(userinput!=null) {
//app.setBootingFALSE(getApplicationContext());
app.setDeeplinkInput(ctx,userinput);
app.logy("USER INPUT: " + userinput);
}
}
if(action!=null) {
app.logy("ACTION:" + action);
}
// checkPermissions(); //launches app if permissions are OK, if not, updates permission status on the checkboxes
app.logy("BOOTING....END");
}//end onCreate
boolean needPermissionLocation(){
return ((ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)||
(ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED));
}
boolean needPermissionRecordAudio(){
return (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED);
}
boolean needPermissionStorage(){
return ((ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)&&
(ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED));
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==appPermissionsCallbackConstant){
app.loge("BootActivity.onRequestPermissionsResult");
refreshUI();
if((!needPermissionLocation())&&(!needPermissionRecordAudio())&&(!needPermissionStorage())){
launchApp();
}
}
}
void refreshUI(){
app.loge("refreshUI()");
//Refresh CHECKBOXES with permissions
if(needPermissionRecordAudio())
checkboxAudioRecording.setChecked(false);
else
checkboxAudioRecording.setChecked(true);
if(needPermissionLocation())
checkboxLocation.setChecked(false);
else
checkboxLocation.setChecked(true);
if(needPermissionStorage())
checkboxStorage.setChecked(false);
else
checkboxStorage.setChecked(true);
}
void launchApp(){
app.loge("BootActivity.LaunchApp()");
Intent i = new Intent(bootActivity.this, MainActivity.class);
startActivity(i);
finish();
}
final int appPermissionsCallbackConstant=1111;
void checkPermissions(){
app.loge("BootActivity.checkPermissions()");
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)&&
(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)&&
(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)&&
(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)&&
(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
app.loge("All permissions are OK");
checkboxAudioRecording.setChecked(true);
checkboxLocation.setChecked(true);
checkboxStorage.setChecked(true);
launchApp();
}
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
checkboxAudioRecording.setChecked(false);
app.loge("Requesting RECORD_AUDIO PERMISSION");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO},appPermissionsCallbackConstant);
}
else{
checkboxAudioRecording.setChecked(true);
}
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)||
(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
app.loge("Requesting LOCATION PERMISSIONS");
checkboxLocation.setChecked(false);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION},appPermissionsCallbackConstant);
}
else{
checkboxLocation.setChecked(true);
}
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)||
(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)){
checkboxStorage.setChecked(false);
app.loge("Requesting STORAGE READ/WRITE PERMISSION");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},appPermissionsCallbackConstant);
}
else{
checkboxStorage.setChecked(true);
}
}
#Override
protected void onResume() {
super.onResume();
app.loge("BootActivity.onResume");
thisActivity=this;
refreshUI();
if((!needPermissionLocation())&&(!needPermissionRecordAudio())&&(!needPermissionStorage())){
launchApp();
}
}
#Override
public void onNewIntent(Intent intent) {
this.setIntent(intent);
}
}
I have a LocationListener which is extended LiveData Class. From the Android 6.0, the permission is requested in runtime. Now , when I tried to implements the LiveData Class and it required the permission checking in onActive() function. I have to make the boilerplate code in each activity for the permission requested and result received. Is there any way to move such
onRequestPermissionsResult() and checkSelfPermission() functions to the LocationListener ?
LocationFragment.java
public class LocationFragment extends LifecycleFragment {
private FragmentLocationBinding binding;
public LocationFragment() {
// Required empty public constructor
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (ContextCompat.checkSelfPermission(getActivity(),
permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_COARSE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
200);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
//get the viewmodel from activity
LastLocationViewModel lastLocationViewModel = ViewModelProviders.of(getActivity())
.get(LastLocationViewModel.class);
lastLocationViewModel.getLastKnowLocation().observe(this, location -> {
binding.setLocation(location);
});
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 200: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(), "Rights Granted", Toast.LENGTH_SHORT).show();
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
binding = DataBindingUtil
.inflate(LayoutInflater.from(getActivity()), R.layout.fragment_location, null, false);
return binding.getRoot();
}
}
LastLocationListener.java
public class LastLocationListener extends LiveData<Location> {
private LocationManager locationManager;
private Context context;
private LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d("Location Msg", location.toString());
setValue(location);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
public LastLocationListener(Context context) {
this.context = context;
locationManager = (LocationManager) context.getSystemService(
Context.LOCATION_SERVICE);
}
#Override
protected void onActive() {
if (ActivityCompat.checkSelfPermission(context, permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context, permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// 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.
return;
}
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
}
#Override
protected void onInactive() {
locationManager.removeUpdates(listener);
}
}
when I tried to implements the LiveData Class and it required the permission checking in onActive() function
No, it does not. What you are seeing is a Lint warning, which you can suppress.
What is required is that you hold the permission before attempting to use this particular bit of LiveData.
Is there any way to move such onRequestPermissionsResult() and checkSelfPermission() functions to the LocationListener ?
No.
I am trying to check the user's Location settings before retrieving their location but I cannot get the onResult callback to fire. I first initialized the GoogleClientApi object in onCreate() and tried debugging, it says "No such instance field" at the result.setResultCallback() breakpoint. I have spent numerous hours on this, please help me out!
public class MainActivity extendsAppCompatActivity
implements,OnConnectionFailedListener{
private static final int PERMISSION_CODE = 23;
private static final int RESOLUTION_CODE = 0x1;
public GoogleApiClient googleClient;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
checkLocationSettings();
}
public void checkLocationSettings() {
googleClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.addOnConnectionFailedListener(this)
.build();
LocationSettingsRequest.Builder locationSettingsBuilder = new LocationSettingsRequest.Builder()
.addLocationRequest(new LocationRequest().setInterval(5000)).setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleClient
, locationSettingsBuilder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult locationSettingsResult) {
Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
checkLocationPermission();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
status.startResolutionForResult(MainActivity.this, RESOLUTION_CODE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Toast.makeText(MainActivity.this, "Location is missing", Toast.LENGTH_LONG).show();
}
}
});
}
private void checkLocationPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_CODE);
} else {
googleClient.connect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case RESOLUTION_CODE:
switch (resultCode) {
case RESULT_OK:
checkLocationPermission();
break;
case RESULT_CANCELED:
Toast.makeText(MainActivity.this, "Location is required, turn it on", Toast.LENGTH_SHORT).show();
break;
}
break;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
googleClient.connect();
} else {
Toast.makeText(MainActivity.this, "Error Activty", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// 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.
return;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(googleClient);
textView.setText(location.getLatitude() + location.getLongitude() + "");
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
protected void onStop() {
super.onStop();
if(googleClient.isConnected()){
googleClient.disconnect();
}
}
}
From these SO threads, No such instance field and Initialize boolean value "no such instance field", if there wasn't a problem with the code, try restarting Android Studio. Maybe it's using an incorrect file from the previous version. This thread: Why is LocationSettingsResult startResolutionForResult not calling onActivityResult? might also help on how to connect to GoogleApiClient for getting the user's location.