“我正在尝试在后台获取位置,但它显示此错误。无论如何我都无法获取该位置。通知不起作用。我的doMystuff()函数在主活动中应如何显示?有人可以吗?请提供我如何在清单中注册广播接收器以及如何使用onButton Click实现代码。” UPDATE [2]:“在这里,我刚刚编写了要访问的运行时权限。现在,在按钮上单击doStuff函数中的“ startButton”,我应该编写startService还是startForegroundService? “主要活动”
package com.example.locationrunandall;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private TextView textView;
private Button butt1, butt2;
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textview);
butt1 = findViewById(R.id.butt1);
butt2 = findViewById(R.id.butt2);
}
public void startButton(View view) {
fetchCode();
}
private void fetchCode() {
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
new AlertDialog.Builder(this)
.setTitle("Required Location")
.setMessage("You have to get this permission to access the feature.")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create().show();
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
} else {
// Permission has already been granted
doMyStuff();
}
}
private void doMyStuff() {
Toast.makeText(this, "Working", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this,ForeService.class);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
startForegroundService(intent);
}else{
startService(intent);
}
}
public void stopButton(View view) {
Intent intent = new Intent(this,ForeService.class);
stopService(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(requestCode==MY_PERMISSIONS_REQUEST_LOCATION){
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
Intent gpsOptionsIntent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(gpsOptionsIntent);
}else
{
}
}
}
}
答案 0 :(得分:2)
您应该使用ForegroundService而不是Service。要启动它,请调用startForegroundService()。
此onFor方法中新的ForegroundService的下一步调用startForeground()。使用startForeground,您必须传递一条通知以通知用户该服务正在运行。
此外,我发现某些设备(例如HUAWEI)具有称为“功耗密集型应用程序监视器”的功能。除非用户为其授予特殊权限,否则它将杀死长时间在后台运行的每个应用程序。执行此操作的路径:设置->安全和隐私->位置服务->最近的位置请求:您的应用名称->电池->取消选中耗电大的提示,应用启动:手动管理:检查所有三个位置:自动启动,二次启动,在后台运行。
我不知道有没有办法以编程方式执行此操作。我认为最好的方法是创建一种帮助活动,并向用户解释如果应用程序无法运行该怎么办。
答案 1 :(得分:0)
服务代码可每10秒更新一次位置
y
然后在“活动”中添加按钮或切换按钮以启动和停止服务。您也可以通过“通知”中的按钮进行操作。
rect
即使应用被终止,服务也应运行。在小米,OPPO,VIVO等设备中,无论您在服务中做什么,它都可能被杀死。在这些情况下,您可以尝试通过广播再次重新启动服务,以在服务被终止时启动该服务。
public class LocationService extends Service implements com.google.android.gms.location.LocationListener,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private String mChannelId = "my_service";
private int mNotificationId = 1;
private NotificationCompat.Builder mNotifBuilder = new NotificationCompat.Builder(this, mChannelId);
private Notification mNotif;
private NotificationManager mNotificationManager;
private boolean mRestartService = true;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void initGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
@Override
public void onCreate() {
super.onCreate();
initGoogleApiClient();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getAction() != null) {
String mAction = intent.getAction();
if(mAction.equals("start_service")){
startForegroundService();
}else if(mAction.equals("stop_service")){
stopForegroundService();
}
}
return START_NOT_STICKY;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
try {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
} catch (SecurityException e) {
e.printStackTrace();
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
Toast.makeText(this, "Location Updated", Toast.LENGTH_SHORT).show();
//Broadcast Location
}
private void createNotificationChannel(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String description = "Foreground Service Channel";
String name = "My Background Channel";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(mChannelId, name, importance);
channel.setDescription(description);
mNotificationManager.createNotificationChannel(channel);
}
}
private void startForegroundService() {
//Initializing Notifications and intents
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
createNotificationChannel();
mNotifBuilder.setContentText("Notification Content")
.setContentTitle("Notification Title")
.setSmallIcon(R.drawable.ic_notify)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setAutoCancel(true);
mNotif = mNotifBuilder.build();
startForeground(mNotificationId, mNotif);
}
private void stopForegroundService() {
mRestartService = false;
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
stopForeground(true);
}
/*@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Toast.makeText(this, "Task Removed", Toast.LENGTH_SHORT).show();
if (mRestartService){
Intent intent = new Intent(this, RestartService.class);
intent.setAction("restart_service");
sendBroadcast(intent);
}
}*/
}
如果从后台删除活动后服务被杀死,则可以将其添加到private void startService() {
Intent intent = new Intent(MainActivity.this, LocationService.class);
intent.setAction("start_service");
startService(intent);
}
private void stopService() {
Intent intent = new Intent(MainActivity.this, LocationService.class);
intent.setAction("stop_service");
startService(intent);
}
中。如果将活动从后台删除后的某个时间被杀死,则可以将其添加到public class RestartService extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals("restart_service")){
Intent intent1 = new Intent(context, LocationService.class);
intent.setAction("start_service");
context.startService(intent1);
}
}
}
中
onTaskRemoved()
即使如此,该服务也可能在某些手机中被杀死。在这种情况下,您需要要求用户从电池优化中排除该服务,并允许其他例外使其自由运行。