From past few days I am looking for a solution but unable to find any. I am working on a situation when the google location accuracy is toggled off for android 9+ then the application should prompt user to toggle on the location accuracy.
Problem facing:
Is it possible if (statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) then navigate directly to google location accuracy screen of the device(which looks difficult). OR customise the dialog box which is prompted by google services library (which is not possible i assume). Any thoughts would be appreciated.
Below is the snippet.
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(UPDATE_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build(); mSettingsClient.checkLocationSettings(mLocationSettingsRequest).addOnSuccessListener(mActivity,
new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
mFusedProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper()).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
}
});
}
}).addOnFailureListener(mActivity, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
if(statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED){
//Location settings not satisfied.
try {
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(
mActivity,
LOCATION_REQUEST);
} catch (IntentSender.SendIntentException ex) {
}
} else {
}
}
});
Try this,works for me
private void showLocationDialog() {
new AlertDialog.Builder(RequestLocationUpdatesWithIntentActivity.this).setTitle("The location service is not enabled on the phone.")
.setMessage("Go to Settings > Location information (enable location service).")
.setNegativeButton("cancels", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("Unset", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
RequestLocationUpdatesWithIntentActivity.this.startActivity(intent);
} catch (ActivityNotFoundException ex) {
intent.setAction(Settings.ACTION_SETTINGS);
try {
RequestLocationUpdatesWithIntentActivity.this.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
})
.show();
}
You can call it here.
And then there's this effect.
Related
First time I run the app beacon monitoring and ranging is working fine. But the second time I lanuch the app i.e after calling onResume it is only showing following and no more calls to didRangeBeaconsInRegion : I am guessing it is because of beaconManager instance is not properly destroyed or something in calls to onDestroy. However according to the library example I tried unbinding in onPause() with no success. Any idea ?
I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 0
2020-07-15 18:41:40.776 9657-9657/com.something.beacon I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 0
2020-07-15 18:41:40.824 9657-9657/com.something.beacon I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 1
public class MainActivity extends AppCompatActivity implements BeaconConsumer {
private static final int PERMISSION_REQUEST_FINE_LOCATION = 1;
private static final int PERMISSION_REQUEST_BACKGROUND_LOCATION = 2;
ListView beaconList;
protected static final String TAG = "MonitoringActivity";
private BeaconManager beaconManager;
private FirebaseDatabase database;
private DatabaseReference beaconDBRef;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Firebase database setup
database = FirebaseDatabase.getInstance();
beaconDBRef = database.getReference().child("messages");
beaconList = (ListView) findViewById(R.id.beacon_list);
Log.d(TAG, "onCreate: is called");
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
// Detect the main identifier (UID) frame:
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT));
// Detect the telemetry (TLM) frame:
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout(BeaconParser.EDDYSTONE_TLM_LAYOUT));
// Detect the URL frame:
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT));
beaconManager.bind(this);
verifyBluetooth();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (this.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (!this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs background location access");
builder.setMessage("Please grant location access so this app can detect beacons in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#TargetApi(23)
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
PERMISSION_REQUEST_BACKGROUND_LOCATION);
}
});
builder.show();
}
else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons in the background. Please go to Settings -> Applications -> Permissions and grant background location access to this app.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
}
}
} else {
if (!this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION},
PERMISSION_REQUEST_FINE_LOCATION);
}
else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons. Please go to Settings -> Applications -> Permissions and grant location access to this app.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
}
}
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
long tempTime = Integer.MIN_VALUE;
long callInterval = 10000;
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_FINE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "fine location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover nearby devices.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
case PERMISSION_REQUEST_BACKGROUND_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "background location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since background location access has not been granted, this app will not be able to discover devices when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
private void verifyBluetooth() {
try {
if (!BeaconManager.getInstanceForApplication(this).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
//finish();
//System.exit(0);
}
});
builder.show();
}
}
catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
//finish();
//System.exit(0);
}
});
builder.show();
}
}
#Override
public void onBeaconServiceConnect() {
// Set the two identifiers below to null to detect any beacon regardless of identifiers
Identifier myBeaconNamespaceId = Identifier.parse("0x2F234454F4911BA9FFA6");
final Identifier myBeaconInstanceId = Identifier.parse("0x000000000001");
beaconManager.removeAllMonitorNotifiers();
beaconManager.removeAllRangeNotifiers();
beaconManager.addMonitorNotifier(new MonitorNotifier() {
#Override
public void didEnterRegion(Region region) {
Log.i(TAG, "I just saw an beacon for the first time!");
try {
Log.d(TAG, "didEnterRegion");
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void didExitRegion(Region region) {
Log.i(TAG, "I no longer see an beacon");
try {
Log.d(TAG, "didExitRegion");
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
Log.i(TAG, "I have just switched from seeing/not seeing beacons: "+state);
}
});
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
for(Beacon oneBeacon : beacons) {
String beaconInfo = "Namespace id: " + oneBeacon.getId1() + "\nInstance Id: " + oneBeacon.getId2();
Log.d(TAG, beaconInfo);
Toast.makeText(MainActivity.this, beaconInfo, Toast.LENGTH_SHORT).show();
//Write to database every 10 seconds
long currentTime = System.currentTimeMillis();
if(currentTime > tempTime + callInterval){
BeaconModel beaconModel = new BeaconModel();
beaconModel.setBeaconName(oneBeacon.getId2().toString());
beaconModel.setDistance(oneBeacon.getDistance());
beaconModel.setMessage("this is a nice message");
beaconDBRef.child(beaconModel.getBeaconName()).setValue(beaconModel);
//beaconDBRef.push().setValue("beacon detected! - " + oneBeacon.getId2());
tempTime = currentTime;
}
}
}
});
try {
Identifier myBeaconNamespaceId1 = Identifier.parse("0xedd1ebeac04e5defa017");
Identifier myBeaconInstanceId1 = Identifier.parse("0x0e32fea91b13");
Identifier myBeaconInstanceId2 = Identifier.parse("0xa9937b420872");
beaconManager.startMonitoringBeaconsInRegion(new Region("myMonitoringUniqueId", myBeaconNamespaceId1, myBeaconInstanceId1, null));
beaconManager.startMonitoringBeaconsInRegion(new Region("myMonitoringUniqueId2", myBeaconNamespaceId1, myBeaconInstanceId2, null));
beaconManager.startMonitoringBeaconsInRegion(new Region("myMonitoringUniqueId3", null, null, null));
} catch (RemoteException e) {
Log.d(TAG, e.getMessage());
}
}
}
This is weird. I mean, I have strong network, and GPS is turned On, still it asks for Wifi !!
I'm using new Location Api with class FusedLocationProviderClient.
This is how I am checking if Location Settings are enabled or not:
private void checkIfLocationSettingsAreEnabled() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
SettingsClient client = LocationServices.getSettingsClient(context);
Task<LocationSettingsResponse> locationSettingsResponseTask = client.checkLocationSettings(builder.build());
locationSettingsResponseTask.addOnSuccessListener(locationSettingsResponse -> {
getLastKnownLocation();
});
locationSettingsResponseTask.addOnFailureListener(e -> {
if (e instanceof ResolvableApiException) {
myLocationListener.onResolutionNeeded(e);
} else {
myLocationListener.onLocationFailure(e);
}
});
}
With the above code, I am able to get below image:
But then, after clicking OK, again I make call to checkIfSettingsAreEnabled() this shows another popup as below:
I wonder why enabling Wifi is mandatory, even if I am on desert safari, where there is no Wifi to connect to !!
Is there any way to Skip this Wifi option, and work as normal as Google Maps does ?
In fact, Google Maps uses priority PRIORITY_HIGH_ACCURACY and still once, the first settings dialog has been shown, it doesn't ask second time to turn on Wifi.
FusedLocationProvider uses a combo of GPS and WIFI to get your location. Especially when asking for balanced mode, it needs both or won't work (GPS takes power, so it won't rely just on it for balanced). Try max accuracy, its less likely to use it then. Or just use the GPS provider if you actually want GPS.
PRIORITY_BALANCED_POWER_ACCURACY
This priority will go with coarse level accuracy which fetch location only from wi-fi , cellular network or bluetooth and NOT from GPS.
and if device don't have SIM it needs to have wi-fi to get location or it will not call onLocationChanged till won't get location.
With the below solution, I am able to skip this Wifi Settings Dialog. This is not a perfect solution, but just a workaround till I find perfect solution.
Problem was, even after clicking "Ok" on Settings Dialog, it returned result as Activity.RESULT_CANCELLED. Reason was, Wifi was still turned off. So, as a quick fix, made a check in result Activity.RESULT_CANCELLED, that if I could get Location by checking LocationSettingStates.
You can use my MyLocationUtils.java and Base classes LocationActivity.java or LocationFragment.java. Happy Coding..!!
for getting location
MyLocationUtils.java:
public class MyLocationUtils {
public static final int REQUEST_CODE_LOCATION_SETTINGS = 123;
private static final int INTERVAL_IN_MS = 10000;
private static final int FASTEST_INTERVAL_IN_MS = 5000;
private static final int MAX_WAIT_TIME_IN_MS = 5000;
private static final int NUMBER_OF_UPDATES = 1;
private final MyLocationListener myLocationListener;
private final Context context;
private FusedLocationProviderClient mFusedLocationProviderClient;
private LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
Location location = null;
if (locationResult.getLocations().size() > 0) {
location = locationResult.getLocations().get(0);
}
myLocationListener.onLocationSuccess(location);
stopContinuousLocation();
}
};
public MyLocationUtils(Context context, MyLocationListener myLocationListener) {
this.context = context;
this.myLocationListener = myLocationListener;
initializeFusedLocationProviderClient();
}
private boolean checkIfRequiredLocationSettingsAreEnabled(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
private void initializeFusedLocationProviderClient() {
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
}
public void stopContinuousLocation() {
mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback);
}
public void getLocation() {
checkIfLocationSettingsAreEnabled();
}
private void checkIfLocationSettingsAreEnabled() {
if (checkIfRequiredLocationSettingsAreEnabled(context)) {
getLastKnownLocation();
} else {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(getLocationRequest());
builder.setAlwaysShow(true);
SettingsClient client = LocationServices.getSettingsClient(context);
Task<LocationSettingsResponse> locationSettingsResponseTask = client.checkLocationSettings(builder.build());
locationSettingsResponseTask.addOnSuccessListener(locationSettingsResponse -> {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
getLastKnownLocation();
});
locationSettingsResponseTask.addOnFailureListener(e -> {
if (e instanceof ResolvableApiException) {
myLocationListener.onResolutionNeeded(e);
} else {
myLocationListener.onLocationFailure(e);
}
});
}
}
#SuppressLint("MissingPermission")
private void getLastKnownLocation() {
Task<Location> locationTask = mFusedLocationProviderClient.getLastLocation();
locationTask.addOnSuccessListener(location -> {
// Got last known location. In some rare situations this can be null.
if (location != null) {
myLocationListener.onLocationSuccess(location);
} else {
startContinuousLocation();
}
});
locationTask.addOnFailureListener(myLocationListener::onLocationFailure);
}
#SuppressLint("MissingPermission")
private void startContinuousLocation() {
mFusedLocationProviderClient.requestLocationUpdates(getLocationRequest(), mLocationCallback, Looper.getMainLooper())
.addOnFailureListener(myLocationListener::onLocationFailure);
}
private LocationRequest getLocationRequest() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(INTERVAL_IN_MS);
locationRequest.setFastestInterval(FASTEST_INTERVAL_IN_MS);
locationRequest.setNumUpdates(NUMBER_OF_UPDATES);
locationRequest.setMaxWaitTime(MAX_WAIT_TIME_IN_MS);
return locationRequest;
}
public void resolveLocationSettings(FragmentActivity fragmentActivity, Exception exception) {
ResolvableApiException resolvable = (ResolvableApiException) exception;
try {
resolvable.startResolutionForResult(fragmentActivity, MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS);
} catch (IntentSender.SendIntentException e1) {
e1.printStackTrace();
}
}
public interface MyLocationListener {
void onLocationSuccess(Location location);
void onResolutionNeeded(Exception exception);
void onLocationFailure(Exception exception);
}
}
BaseLocationActivity.java:
public abstract class LocationActivity extends AppCompatActivity {
private MyLocationUtils myLocationUtils;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myLocationUtils = new MyLocationUtils(this, new MyLocationUtils.MyLocationListener() {
#Override
public void onLocationSuccess(Location location) {
if (shouldBeAllowedToProceed())
LocationActivity.this.onLocationSuccess(location);
}
#Override
public void onResolutionNeeded(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationActivity.this.onResolutionNeeded(exception);
}
#Override
public void onLocationFailure(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationActivity.this.onLocationFailure(exception);
}
});
}
protected void getLocation() {
myLocationUtils.getLocation();
}
protected void resolveLocationSettings(Exception exception) {
myLocationUtils.resolveLocationSettings(this, exception);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS) {
final LocationSettingsStates locationSettingsStates = LocationSettingsStates.fromIntent(data);
switch (resultCode) {
case Activity.RESULT_OK:
onResolveLocationSettingOk();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to,
// or on Android Oreo 8.1 Wifi Settings were not satisfied inspite of clicking OK, that results on Activity.RESULT_CANCELED
onResolveLocationSettingCancelled(locationSettingsStates);
break;
default:
break;
}
}
}
protected abstract void onResolveLocationSettingOk();
protected void onResolveLocationSettingCancelled(LocationSettingsStates locationSettingsStates) {
if (locationSettingsStates.isLocationPresent() && locationSettingsStates.isLocationUsable()) {
onResolveLocationSettingOk();
}
}
private boolean shouldBeAllowedToProceed() {
return getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
}
public abstract void onLocationSuccess(Location location);
public abstract void onResolutionNeeded(Exception exception);
public abstract void onLocationFailure(Exception exception);
#Override
public void onDestroy() {
super.onDestroy();
myLocationUtils.stopContinuousLocation();
}
}
LocationFragment.java:
public abstract class LocationFragment extends Fragment {
private MyLocationUtils myLocationUtils;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myLocationUtils = new MyLocationUtils(context, new MyLocationUtils.MyLocationListener() {
#Override
public void onLocationSuccess(Location location) {
if (shouldBeAllowedToProceed())
LocationFragment.this.onLocationSuccess(location);
}
#Override
public void onResolutionNeeded(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationFragment.this.onResolutionNeeded(exception);
}
#Override
public void onLocationFailure(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationFragment.this.onLocationFailure(exception);
}
});
}
protected void resolveLocationSettings(FragmentActivity appCompatActivity, Exception exception) {
myLocationUtils.resolveLocationSettings(appCompatActivity, exception);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS) {
final LocationSettingsStates locationSettingsStates = LocationSettingsStates.fromIntent(data);
switch (resultCode) {
case Activity.RESULT_OK:
onResolveLocationSettingOk();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
onResolveLocationSettingCancelled(locationSettingsStates);
break;
default:
break;
}
}
}
protected abstract void onResolveLocationSettingOk();
protected void onResolveLocationSettingCancelled(LocationSettingsStates locationSettingsStates) {
if (locationSettingsStates.isLocationPresent() && locationSettingsStates.isLocationUsable()) {
onResolveLocationSettingOk();
}
}
public void getLocation() {
myLocationUtils.getLocation();
}
private boolean shouldBeAllowedToProceed() {
return getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
}
public abstract void onLocationSuccess(Location location);
public abstract void onResolutionNeeded(Exception exception);
public abstract void onLocationFailure(Exception exception);
#Override
public void onDestroy() {
super.onDestroy();
myLocationUtils.stopContinuousLocation();
}
}
I have this android app which connects to an mqtt broker and listens for instructions to play/pause a ringtone or open/close the flashlight.
It runs as supposed to until i change my settings and call the function flashOnOff after this. Then i get a null pointer exception but i can not understand why.
This is my code (i did not include my imports to save some space):
public class MainActivity extends AppCompatActivity {
// Layout related parameters
Toolbar myToolbar;
Spinner mySpinner;
ImageButton flashlightButton;
Button ringtone;
EditText message;
// Camera/flashlight related parameters
Camera camera;
Camera.Parameters parameters;
// MQTT related parameters
private String BrokerIp = "tcp://192.168.1.3:1883";
private int qos = 2;
static String Username = "user1";
static String Password = "user1";
String topicStr = "commands";
String clientId = "AndroidClient";
MqttConnectOptions options;
MqttAndroidClient client;
Vibrator vibrator;
// Ringtone related parameters
Ringtone myRingtone;
MediaPlayer ringtoneMP ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
myRingtone = RingtoneManager.getRingtone(getApplicationContext(),uri);
myToolbar = (Toolbar) findViewById(R.id.toolbar);
mySpinner = (Spinner) findViewById(R.id.spinner);
flashlightButton = (ImageButton) findViewById(R.id.image);
myToolbar.setLogo(R.drawable.twoguyswatchmrrobot);
myToolbar.setTitle(getResources().getString(R.string.app_name));
ArrayAdapter<String> myAdapter = new ArrayAdapter<String>(MainActivity.this,
R.layout.custom_spinner_itam,
getResources().getStringArray(R.array.Toolbar_dropdown_entries));
myAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(myAdapter);
ringtoneMP = MediaPlayer.create(this,R.raw.games_of_thrones);
ringtone = (Button) this.findViewById(R.id.ringtone);
message = (EditText)findViewById(R.id.messagePublish);
mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(MainActivity.this,
mySpinner.getSelectedItem().toString(),
Toast.LENGTH_SHORT)
.show();
if (mySpinner.getSelectedItem().toString().equals("Exit App")){
exit();
}else if(mySpinner.getSelectedItem().toString().equals("Settings"))
{
Intent intent;
intent = new Intent(MainActivity.this, SettingsActivity.class);
intent.putExtra("CURRENT_IP",client.getServerURI());
intent.putExtra("CURRENT_QOS", Integer.toString(qos));
intent.putExtra("CURRENT_TOPIC",topicStr);
startActivityForResult(intent,1); // this is so we can take the results back to mainActivity later
}else{
System.out.println("ara3e, den exw diale3ei tipota");
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
//Flashlight on Create start
if(isFlashAvailable()) // check if flash is available on this device, if it is open camera (module) and make button clickable
{
camera = Camera.open();
parameters = camera.getParameters();
}else
{ // if flashlight is not supported dont let the user click the button
flashlightButton.setEnabled(false);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Error.");
builder.setMessage("Flashlight not available on this device. \nExit?"); // inform the user and let him choose how to continue
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
exit();
}
});
builder.setNegativeButton("Stay without flashlight", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
flashlightButton.setOnClickListener(new View.OnClickListener() { // listen for flash button clicks
#Override
public void onClick(View view) {
flashOnOff();
}
});
ringtone.setOnClickListener(new View.OnClickListener() { // Ringtone listener
#Override
public void onClick(View view) {
ringtoneOnOff(ringtoneMP);
}
});
client = new MqttAndroidClient(MainActivity.this, BrokerIp, clientId);
// client = pahoMqttClient.getMqttClient(MainActivity.this,BrokerIp,clientId);
options = new MqttConnectOptions();
options.setUserName(Username);
options.setPassword(Password.toCharArray());
try {
IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(MainActivity.this, "connected", Toast.LENGTH_SHORT).show();
setSubscription(client,topicStr,qos);
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Log.w("Mqtt","Failed to connect to:"+ BrokerIp + exception.toString());
Toast.makeText(MainActivity.this, "Failed to connect to:" +exception.toString(), Toast.LENGTH_SHORT).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable throwable) {
Log.d("Connection:"," Lost");
}
#Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
myMessageArrived(s,mqttMessage);
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
Log.d("Delivery"," completed with iMqttDeliveryToken: " + iMqttDeliveryToken);
}
});
}
//Flashlight start
#Override
protected void onStop() {
super.onStop();
if(camera!=null)
{
camera.release();
camera = null;
}
}
//Flashlight end
//Backkey exit confirmation
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exitByBackKey();
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void exitByBackKey() {
AlertDialog alertbox = new AlertDialog.Builder(this)
.setMessage("Do you want to exit application?")
.setPositiveButton("Yes", new
DialogInterface.OnClickListener() {
// when yes is clicked exit the application
public void onClick(DialogInterface arg0, int arg1) {
exit();
}
})
.setNegativeButton("No", new
DialogInterface.OnClickListener() {
// when no is clicked do nothing
public void onClick(DialogInterface arg0, int arg1) {
}
})
.show();
}
//Backkey end
// PUBLISH MESSAGE
private void setSubscription(MqttAndroidClient client, String topic, int qos){
try{
client.subscribe(topic, qos);
}
catch (MqttException e){
e.printStackTrace();
}
}
private void unsetSubscription(MqttAndroidClient client,String topic){
try{
client.unsubscribe(topic);
}catch (MqttException e){
e.printStackTrace();
}
}
public void conn(View v){
try {
IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(MainActivity.this, "connected", Toast.LENGTH_SHORT).show();
setSubscription(client,topicStr,qos);
// pub();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Toast.makeText(MainActivity.this, "not connected", Toast.LENGTH_SHORT).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
public void disconn(View v){
if (client.isConnected()) {
try {
IMqttToken token = client.disconnect();
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(MainActivity.this, "disconnected", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Toast.makeText(MainActivity.this, "could not disconnect", Toast.LENGTH_SHORT).show();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}else {
Toast.makeText(MainActivity.this, "Client is already disconnected", Toast.LENGTH_LONG).show();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void pub(View v) {
String topic = topicStr;
try {
client.publish(topic, String.valueOf(message.getText()).getBytes(),qos,false);
} catch (MqttException e) {
e.printStackTrace();
}
}
private void ringtoneOnOff(MediaPlayer ringtoneMP){
if (ringtoneMP.isPlaying()){
ringtoneMP.pause();
}else{
ringtoneMP.start();
}
}
private void myMessageArrived(String s,MqttMessage mqttMessage){
if ((mqttMessage.toString()).equals("Flash on")) {
if (isFlashOn()) {
Toast.makeText(MainActivity.this, "Flashlight already on", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Turning flashlight on", Toast.LENGTH_SHORT).show();
flashOnOff();
}
} else if ((mqttMessage.toString()).equals("Flash off")) {
if (isFlashOn()) {
Toast.makeText(MainActivity.this, "Turning flashlight off", Toast.LENGTH_SHORT).show();
flashOnOff();
} else {
Toast.makeText(MainActivity.this, "Flashlight already off", Toast.LENGTH_SHORT).show();
}
} else if ((mqttMessage.toString()).equals("Ringtone on")) {
if (ringtoneMP.isPlaying()) {
Toast.makeText(MainActivity.this, "Ringtone already playing", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Playing ringtone", Toast.LENGTH_SHORT).show();
ringtoneMP.start();
}
} else if ((mqttMessage.toString()).equals("Ringtone off")) {
if (ringtoneMP.isPlaying()) {
ringtoneMP.pause();
} else {
Toast.makeText(MainActivity.this, "Ringtone already not being played", Toast.LENGTH_SHORT).show();
}
} else {
Log.d("INFO:", "This Command does not exist");
}
vibrator.vibrate(500);
myRingtone.play();
}
public void exit(){
finish();
System.exit(0);
}
public boolean isFlashAvailable(){ // boolean function that returns true if flash is supported on this device
return getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
}
public void flashOnOff(){ // self explanatory
if (this.parameters.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_ON) || this.parameters.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_TORCH)){ // if the flash is on torch mode
Log.d("BHKE","408");
this.flashlightButton.setImageResource(R.drawable.off);
this.parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); // turn it off
}else{
Log.d("BHKE","412");
this.flashlightButton.setImageResource(R.drawable.on);
this.parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); // else turn it on
}
this.camera.setParameters(this.parameters);
this.camera.startPreview();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
String tempBrokerIp;
String temptopic="";
Integer tempqos;
Boolean BrokerIpChanged = true;
Boolean qosChanged = true;
Boolean topicChanged = true;
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case (1) : {
if (resultCode == Activity.RESULT_OK) {
tempBrokerIp = data.getStringExtra("CURRENT_IP");
tempqos = Integer.parseInt(data.getStringExtra("CURRENT_QOS"));
temptopic = data.getStringExtra("CURRENT_TOPIC");
Log.d("Info BROKER, TOPIC, QOS", ":"+ tempBrokerIp+ " " + temptopic+ " " + tempqos);
if (tempBrokerIp.equals(BrokerIp)) {
BrokerIpChanged=false;
Log.i("BrokerIpChanged =", BrokerIpChanged.toString());
}
if (tempqos.equals(qos)) {
qosChanged=false;
Log.i("qosChanged =", qosChanged.toString());
}else {
qos = tempqos;
}
if (temptopic.equals(topicStr)){
topicChanged=false;
Log.i("topicChanged =", topicChanged.toString());
}else{
topicStr = temptopic;
}
if (!BrokerIpChanged && !qosChanged && !topicChanged) return;
if (BrokerIpChanged){
try {
client.disconnect();
BrokerIp = tempBrokerIp;
topicStr = temptopic;
qos = tempqos;
// final String clientId = MqttClient.generateClientId();
client = new MqttAndroidClient(MainActivity.this, BrokerIp, clientId);
options = new MqttConnectOptions();
options.setUserName(Username);
options.setPassword(Password.toCharArray());
// options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1); // to user the latest mqtt version
try {
IMqttToken token = client.connect(options);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Toast.makeText(MainActivity.this, "connected", Toast.LENGTH_SHORT).show();
Log.w("Mqtt","Connected to:"+ BrokerIp);
try{
Log.v("INFO 11111:", "about to subscribe with: "+ topicStr + qos);
client.subscribe(topicStr,qos);
}catch (MqttException e){
e.printStackTrace();
}
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Log.w("Mqtt","Failed to connect to:"+ BrokerIp + exception.toString());
Toast.makeText(MainActivity.this, "Failed to connect to:" +exception.toString(), Toast.LENGTH_SHORT).show();
}
});
System.out.println(client.isConnected());
// if (client.isConnected()){
// Log.v("INFO 22222:", "about to subscribe with: "+ temptopic + tempqos);
// client.subscribe(temptopic,tempqos);
// }
} catch (MqttException e) {
e.printStackTrace();
}
client.setCallback(new MqttCallback() {
#Override
public void connectionLost(Throwable throwable) {
}
#Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
myMessageArrived(s,mqttMessage);
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
});
}catch (MqttException e){
e.printStackTrace();
}
}else
{
try {
client.unsubscribe(topicStr);
client.subscribe(temptopic,tempqos);
topicStr = temptopic;
qos = tempqos;
} catch (MqttException e) {
e.printStackTrace();
}
}
}
break;
}
}
}
public boolean isFlashOn(){
return (this.parameters.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_ON) || this.parameters.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_TORCH));
}
I can provide the settings activity code too is needed
It seems that the two variables needed for the flashOnOff where not initiallized after i returned from the settings activity.
Ι added :
if (isFlashAvailable()){
camera = Camera.open();
parameters = camera.getParameters();
}
at the onActivityResult start and it works like a charm.
I checking when the activity starts up whether Location Services are turned on or not, if not I am opening a dialog that starts the "Enable Location Activity" intent. Once I am returning from it I am checking if the location has really been enabled or not, if so I am dismissing the alert dialog.
In theory this should work, but when my activity resumes and call dialog.dismiss() absolutely nothing happens.
My code is as follows-:
public class LocationUtils {
private static AlertDialog dialog_ = null;
public static void checkAndEnableLocationServices(final Activity context) {
LocationManager lm = (LocationManager) context.getSystemService(context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("gps_enabled = " + gps_enabled);
System.out.println("network_enabled = " + network_enabled);
if (!gps_enabled && !network_enabled) {
// notify user
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Location services are disabled");
builder.setPositiveButton("Enable Location Services", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
// TODO Auto-generated method stub
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(myIntent);
//get gps
}
});
builder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
context.finish();
}
});
//For future reference.
AlertDialog dialog = builder.create();
dialog_ = dialog;
dialog.show();
} else {
if(dialog_!=null) {
dialog_.dismiss();
}
}
}
}
In my main activity I have a onResume callback that does the following-:
#Override
protected void onResume() {
super.onResume();
System.out.println("Activity resume()");
LocationUtils.checkAndEnableLocationServices(this);
}
What am I missing ? Why is this is dialog not closing ? The code is not throwing any errors. This a WTF moment for me.
Your are calling alertDialog.show method for the local alert dialog.
Replace code,
AlertDialog dialog = builder.create();
dialog_ = dialog;
with
dialog_ = builder.create();
dialog_.show
and onResume()
if(dialog_!=null) {
dialog_.dismiss();
}
Yo can dismiss dialog when positive button clicked and show it in OnResume if Location Service not enambled
android I finding more but none of get solution..
when occur time out in loopj , I want print Time-out message..
Follow code for time-out which I used.
private static final int DEFAULT_TIMEOUT = 15 * 1000;
private static AsyncHttpClient client = new AsyncHttpClient();
public static void setTimeOutTime() {
client.setTimeout(DEFAULT_TIMEOUT);
System.out.println("timeout");
}
try {
response = client.newCall(request).execute();
jsonObj = new JSONObject(response.body().string());
} catch (IOException e) {
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (getStatus() == Status.RUNNING) {
cancel(true);
if(!hiddenDialog) {
if (pDialog.isShowing())
pDialog.dismiss();
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle("Timeout error")
.setMessage("Sorry server doesn't response!\nCheck your internet connection and try again.")
.setCancelable(true)
.setPositiveButton("Try again", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
Log.d(TAG, "load again");
}
}).setIcon(R.drawable.ic_dialog_alert_dark);
AlertDialog alert = builder.create();
alert.show();
}
});
} catch (JSONException e) {}
EDIT
for your case it should be the same way
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
// make toast
}
});