问题
In my android application,location service is implemented as background service.I have tested it with different phones(like samsung,micromax,Moto,lenovo,nexus) it works fine with all.But when i run in Oppo (colorOS) and MI (MIUI OS),my service is get stopped after some time interval.I have finished MainActivity with MainActivity.this.finish().
回答1:
put following code on your activity above oncreate() method:
private FusedLocationProviderClient mFusedLocationClient;
EasyPermissionsLocation.PermissionCallbacks permissionCallbacks = new EasyPermissionsLocation.PermissionCallbacks() {
@Override
public void onPermissionsGranted(int requestCode, List perms) {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
SettingsClient client = LocationServices.getSettingsClient(SurveyActivity.this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(SurveyActivity.this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(SurveyActivity.this);
if (ActivityCompat.checkSelfPermission(SurveyActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(SurveyActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(SurveyActivity.this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
((SurveyApp)getApplication()).getUser().getCurrentSurvey().setLat(""+location.getLatitude());
((SurveyApp)getApplication()).getUser().getCurrentSurvey().setLng(""+location.getLongitude());
Toast.makeText(SurveyActivity.this, "Location Captured", Toast.LENGTH_SHORT).show();
}
}
});
}
});
task.addOnFailureListener(SurveyActivity.this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ResolvableApiException) {
try {
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(SurveyActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
}
}
}
});
}
@Override
public void onPermissionsDenied(int requestCode, List perms, final boolean isAutoDenied) {
if (isAutoDenied) {
showDialog(getString(R.string.permanently_deny_location));
}
}
@Override
public void onPermissionsPermanentlyDeclined(int requestCode, List perms) {
showDialog(getString(R.string.permanently_deny_location));
}
};
call above code from oncreate method():-
EasyPermissionsLocation.requestPermissions(this, permissionCallbacks, getString(R.string.location_message), 100, Manifest.permission_group.LOCATION);
create this class:
public class EasyPermissionsLocation {
private static final String TAG = "EasyPermissions";
private static long timeWhenRequestingStart;
private static Object object;
private static AlertDialog dialog;
private static PermissionCallbacks callbacks;
private static HashMap<String, String[]> permissionGroups;
private static boolean shouldShowRationale = false;
public static boolean hasPermissions(Context context, String... perms) {
// Always return true for SDK < M, let the system deal with the permissions
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log.w(TAG, "hasPermissions: API version < M, returning true by default");
return true;
}
for (String perm : perms) {
boolean hasPerm = (ContextCompat.checkSelfPermission(context, perm) ==
PackageManager.PERMISSION_GRANTED);
if (!hasPerm) {
return false;
}
}
return true;
}
public static void requestPermissions(final Object object, PermissionCallbacks callback, String rationale,
final int requestCode, final String... perms) {
requestPermissions(object, callback, rationale,
android.R.string.ok,
android.R.string.cancel,
requestCode, perms);
}
public static void requestPermissions(final Object obj, final PermissionCallbacks callback, String rationale,
@StringRes int positiveButton,
@StringRes int negativeButton,
final int requestCode, final String... permission) {
callbacks = callback;
object = obj;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// only for lower of M
callbacks.onPermissionsGranted(requestCode, new ArrayList<String>(Arrays.asList(permission)));
return;
}
checkCallingObjectSuitability(object);
final String[] perms = getActualPermissions(object,
permission);
if (perms.length <= 0) {
callbacks.onPermissionsGranted(requestCode, new ArrayList<String>(Arrays.asList(permission)));
return;
}
shouldShowRationale = false;
for (String perm : perms) {
shouldShowRationale = shouldShowRationale || shouldShowRequestPermissionRationale(object, perm);
}
if (shouldShowRationale) {
if (!TextUtils.isEmpty(rationale)) {
if (dialog == null) {
dialog = new AlertDialog.Builder(getActivity(object))
.setMessage(rationale)
.setCancelable(false)
.setPositiveButton(positiveButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog1, int which) {
executePermissionsRequest(object, perms, requestCode);
dialog.dismiss();
}
})
.create();
} else {
dialog.setMessage(rationale);
}
dialog.show();
} else {
executePermissionsRequest(object, perms, requestCode);
}
} else {
timeWhenRequestingStart = System.currentTimeMillis();
executePermissionsRequest(object, perms, requestCode);
}
}
private static String[] getActualPermissions(Object object, String[] permission) {
initPermissionGroups();
ArrayList<String> permissionList = new ArrayList<String>();
for (String indiPerm : permission) {
if (permissionGroups.containsKey(indiPerm)) {
String[] arr = permissionGroups.get(indiPerm);
for (String s : arr) {
if (!EasyPermissionsLocation.hasPermissions(getActivity(object), s)) {
permissionList.add(s);
}
}
} else {
if (!EasyPermissionsLocation.hasPermissions(getActivity(object), indiPerm)) {
permissionList.add(indiPerm);
}
}
}
Set<String> set = new LinkedHashSet<String>(permissionList);
return set.toArray(new String[set.size()]);
}
private static void initPermissionGroups() {
if (permissionGroups == null) {
permissionGroups = new HashMap<String, String[]>();
permissionGroups.put(Manifest.permission_group.CALENDAR, new String[]{Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR});
permissionGroups.put(Manifest.permission_group.CAMERA, new String[]{Manifest.permission.CAMERA});
permissionGroups.put(Manifest.permission_group.CONTACTS, new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS, Manifest.permission.GET_ACCOUNTS});
permissionGroups.put(Manifest.permission_group.LOCATION, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION});
permissionGroups.put(Manifest.permission_group.MICROPHONE, new String[]{Manifest.permission.RECORD_AUDIO});
permissionGroups.put(Manifest.permission_group.PHONE, new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.CALL_PHONE, Manifest.permission.READ_CALL_LOG, Manifest.permission.WRITE_CALL_LOG, Manifest.permission.ADD_VOICEMAIL, Manifest.permission.USE_SIP, Manifest.permission.PROCESS_OUTGOING_CALLS});
permissionGroups.put(Manifest.permission_group.SENSORS, new String[]{Manifest.permission.BODY_SENSORS});
permissionGroups.put(Manifest.permission_group.SMS, new String[]{Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_WAP_PUSH, Manifest.permission.RECEIVE_MMS});
permissionGroups.put(Manifest.permission_group.STORAGE, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
}
}
public static void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
// checkCallingObjectSuitability(object); // PermissionCallbacks callbacks = (PermissionCallbacks) object;
// Make a collection of granted and denied permissions from the request.
boolean showRationale = false;
ArrayList<String> granted = new ArrayList<>();
ArrayList<String> denied = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
String perm = permissions[i];
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
granted.add(perm);
} else {
showRationale = shouldShowRequestPermissionRationale(object, perm);
if (!showRationale) {
timeWhenRequestingStart = System.currentTimeMillis() - 2;
}
denied.add(perm);
}
}
boolean isPermenantlyDisabled = false;
// Report granted permissions, if any.
if (!granted.isEmpty() && denied.isEmpty()) {
// Notify callbacks
callbacks.onPermissionsGranted(requestCode, granted);
}
//if 100% fail then check for whether timing
else if (granted.isEmpty() && !denied.isEmpty()) {
if (!shouldShowRationale && !showRationale) {
if (callbacks != null) {
callbacks.onPermissionsDenied(requestCode, denied, true);
}
} else {
long diff = System.currentTimeMillis() - timeWhenRequestingStart;
if (diff < 150) {
//means it is permenantly disabled
isPermenantlyDisabled = true;
if (callbacks != null) {
callbacks.onPermissionsPermanentlyDeclined(requestCode, denied);
}
}
Log.i("TAG", diff + "");
}
}
else if (!denied.isEmpty() && !isPermenantlyDisabled) {
callbacks.onPermissionsDenied(requestCode, denied, false);
}
}
@TargetApi(23)
private static boolean shouldShowRequestPermissionRationale(Object object, String perm) {
if (object instanceof Activity) {
return ActivityCompat.shouldShowRequestPermissionRationale((Activity) object, perm);
} else if (object instanceof Fragment) {
return ((Fragment) object).shouldShowRequestPermissionRationale(perm);
} else if (object instanceof android.app.Fragment) {
return ((android.app.Fragment) object).shouldShowRequestPermissionRationale(perm);
} else {
return false;
}
}
@TargetApi(23)
private static void executePermissionsRequest(Object object, String[] perms, int requestCode) {
checkCallingObjectSuitability(object);
if (object instanceof Activity) {
ActivityCompat.requestPermissions((Activity) object, perms, requestCode);
} else if (object instanceof Fragment) {
((Fragment) object).requestPermissions(perms, requestCode);
} else if (object instanceof android.app.Fragment) {
((android.app.Fragment) object).requestPermissions(perms, requestCode);
}
}
@TargetApi(11)
private static Activity getActivity(Object object) {
if (object instanceof Activity) {
return ((Activity) object);
} else if (object instanceof Fragment) {
return ((Fragment) object).getActivity();
} else if (object instanceof android.app.Fragment) {
return ((android.app.Fragment) object).getActivity();
} else {
return null;
}
}
private static void checkCallingObjectSuitability(Object object) {
// Make sure Object is an Activity or Fragment
boolean isActivity = object instanceof Activity;
boolean isSupportFragment = object instanceof Fragment;
boolean isAppFragment = object instanceof android.app.Fragment;
boolean isMinSdkM = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
if (!(isSupportFragment || isActivity || (isAppFragment && isMinSdkM))) {
if (isAppFragment) {
throw new IllegalArgumentException(
"Target SDK needs to be greater than 23 if caller is android.app.Fragment");
} else {
throw new IllegalArgumentException("Caller must be an Activity or a Fragment.");
}
}
}
public interface PermissionCallbacks {
void onPermissionsGranted(int requestCode, List<String> perms);
void onPermissionsDenied(int requestCode, List<String> perms, boolean isAutoDenied);
void onPermissionsPermanentlyDeclined(int requestCode, List<String> perms);
}
}
add in manifest:-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
add following in app gradle file:
implementation 'com.google.android.gms:play-services-location:11.8.0'
来源:https://stackoverflow.com/questions/49399308/background-location-service-is-not-working-in-oppo-and-mi-phones