草庐IT

屏幕关闭时,Android 后台位置更新不会到来

coder 2023-12-16 原文

我们正在开发移动跟踪应用程序。对于位置更新,Fused location API 以高精度为优先级。

即使在屏幕关闭时也需要更新位置。因此,我们正在使用后台 Service。后台 Service 也在获取部分 WakeLock,这样设备就不会进入休眠状态。 在后台 Service 中,我们通过 Service 的未决更新请求位置更新。

问题是我们只在屏幕打开时接收位置更新。一旦屏幕关闭,位置更新就会停止。还有一个 ThreadService 运行,它在任何时候都不会被杀死。

在屏幕关闭时通过 BroadcastReceiver 再次创建位置请求也不起作用。

这里是后台Service类(RouteExecution):

private static final String TAG = "RouteExecution";

private static RouteExecution routeExecution = null;

private static GoogleApiClient mGoogleApiClient;
private static PendingIntent pendingIntent = null;
private PowerManager.WakeLock waitLock;
/**
 * Creates an IntentService.  Invoked by your subclass's constructor.
 */
public RouteExecution() {
    super(TAG);

    RouteExecution.routeExecution = this;
}

@Override
public void onCreate() {
    super.onCreate();

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

    mGoogleApiClient.connect();

    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new PowerButtonReceiver();
    registerReceiver(mReceiver, filter);

    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    waitLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    waitLock.acquire();
}

@Override
protected void onHandleIntent(Intent intent) {

    if (LocationResult.hasResult(intent)) {

        LocationResult locationResult = LocationResult.extractResult(intent);
        Location location = locationResult.getLastLocation();

        GPSLocation gpsLocation = new GPSLocation(location);

        Log.d(TAG, "Location Accuracy: " + location.getAccuracy() + " "
                + " has: " + location.hasAccuracy() + " Provider: " + location.getProvider()
                + " long: " + location.getLongitude() + " lat: " + location.getLatitude());
    }
}



public boolean checkLocationPermission() {

    if (ActivityCompat.checkSelfPermission(routeExecution, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(routeExecution, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        //    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 false;
    }

    return true;
}

public void createLocationListener() {

    if (!this.checkLocationPermission()) {
        return;
    }

    LocationRequest mLocationRequest = LocationRequest.create();
    mLocationRequest.setInterval(5000);
    mLocationRequest.setFastestInterval(5000);
    mLocationRequest.setSmallestDisplacement(0);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    PendingResult<Status> statusPendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
            mLocationRequest, pendingIntent);
}

@Override
public void onConnected(@Nullable Bundle bundle) {

    Log.d(TAG, mGoogleApiClient.isConnected() + "   On Connected");
    synchronized (this) {

            createLocationListener();
    }
}


public static GoogleApiClient getmGoogleApiClient() {
    return mGoogleApiClient;
}

@Override
public void onDestroy() {
    super.onDestroy();


    waitLock.release();
    mGoogleApiClient.disconnect();
}

public static RouteExecution getRouteExecution() {
    return routeExecution;
}

public static void setPendingIntent(PendingIntent pendingIntent) {
    RouteExecution.pendingIntent = pendingIntent;
}

Service 使用 AlarmManager 启动。这是提取:

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent updateServiceIntent = new Intent(context, RouteExecution.class);
PendingIntent pendingUpdateIntent = PendingIntent.getService(context, 0, updateServiceIntent, 0);
RouteExecution.setPendingIntent(pendingUpdateIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP, 50000, pendingUpdateIntent);

广播接收器:

public class PowerButtonReceiver extends BroadcastReceiver {
    private static final String TAG = "PowerButton";

    @Override
    public void onReceive(Context context, Intent intent) {

        Log.d(TAG, "Power Button");
        if (RouteExecution.getRouteExecution() != null) {
            RouteExecution.getRouteExecution().createLocationListener();
        }
    }
}

如何在屏幕关闭时继续获取位置更新。

感谢您的帮助。

最佳答案

首先,获取 WakeLockService一点都不可靠。设备可以在该代码执行之前返回休眠状态。

我会调用 PendingIntent.getBroadcast()而不是 PendingIntent.getService() , 因为 WakeLock onReceive()期间技术保证, 并启动 Service从那里开始。

要么获得 WakeLockonReceive() , 开始你的 Service并释放 WakeLock来自 Service , 在适当的时候

使用 WakefulBroadcastReceiver ,它基本上做同样的事情,而不必自己实现大部分逻辑。

另一个可能的问题是使用 AlarmManager.set()在 Marshmallow 设备上。

如果 Doze,通过此方法设置的警报将不会在这些设备上触发处于 Activity 状态。

使用 setAndAllowWhileIdle()而不是 set() API 级别 23+。

关于屏幕关闭时,Android 后台位置更新不会到来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39343632/

有关屏幕关闭时,Android 后台位置更新不会到来的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  4. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  5. ruby - 如何关闭 ruby​​ gem "Spreadsheet?"中的文件 - 2

    下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11

  6. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  7. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  8. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  9. ruby - 如何在 ruby​​ 中运行后台线程? - 2

    我是ruby​​的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp

  10. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

随机推荐