oppo和小米手机后台定位服务不工作
Posted
技术标签:
【中文标题】oppo和小米手机后台定位服务不工作【英文标题】:Background location service is not working in oppo and MI phones 【发布时间】:2018-08-30 03:47:59 【问题描述】:在我的 android 应用程序中,定位服务是作为后台服务实现的。我已经用不同的手机(如 samsung、micromax、Moto、lenovo、nexus)对其进行了测试,它适用于所有手机。但是当我在 Oppo(colorOS)中运行时和 MI(MIUI OS),我的服务在一段时间后停止。我已经用 MainActivity.this.finish() 完成了 MainActivity。
【问题讨论】:
你能解决这个问题吗?因为我也遇到了同样的问题。 我的后台服务没有在 Oppo 真我设备中运行 任何建议或解决方案 【参考方案1】:在 oncreate() 方法上方的活动中添加以下代码:
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));
;
从 oncreate method() 调用上述代码:-
EasyPermissionsLocation.requestPermissions(this, permissionCallbacks, getString(R.string.location_message), 100, Manifest.permission_group.LOCATION);
创建这个类:
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 回调 = (PermissionCallbacks) 对象;
// 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);
在清单中添加:-
<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" />
在应用程序的 gradle 文件中添加以下内容:
implementation 'com.google.android.gms:play-services-location:11.8.0'
【讨论】:
此活动代码中的 SurveyApp 是什么?实际上我的代码已经准备好了位置捕获服务。它只需要在 oppo 和 MI 上运行以上是关于oppo和小米手机后台定位服务不工作的主要内容,如果未能解决你的问题,请参考以下文章
oppo-coloros、vivo-funtouch os、小米-MIUI os等定制操作系统新推出的设备,如何保护后台服务/报警被杀?
在小米或 Oppo 或 Vivo 手机上 - 应用程序任务未按预期工作
Android AndroidQ 小米 oppo等后台启动界面问题 解决方案