Android位置服务和应用权限

Github:https://github.com/MADMAX110/Odometer

一、使用位置服务

之前的Odometer应用是显示一个随机数,现在要使用Android的位置服务返回走过的距离。
修改getDiatance方法使其返回走过的距离,为此要用Android的位置服务。这些服务允许你得到用户的当前位置,请求定期更新,并在用户进入一个特定位置指定半径范围内时请求触发一个意图。
步骤:
1、声明需要又使用位置服务的权限
2、创建服务时建立一个位置监听器
3、请求位置更新
4、计算走过的距离
5、在撤销服务之前删除位置更新

1、声明你需要的权限

Android默认地允许你完成很多动作,不过有些动作需要的得到用户的许可才能完成。这可能是因为它们使用了用户的个人信息,或者可能会影响存储的数据,也可能会影响其他应用的工作。
位置服务就是需要得到用户授予应用权限才能使用的服务之一。
修改AndroidManifest.xml增加以下声明:
分别是请求精确位置和模糊位置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><application>.......</application></manifest>

2、为OdometerService增加位置监听器

要实现LocationListener接口来创建位置监听器。
这个接口有4个方法需要你定义:
onLocationChanged, onPreviderEnabled, onProviderDisabled, onStatusChanged。
要在第一次创建OdometerService时建立一个位置监听器,所以要在OdometerService的onCreate方法中实现这个接口。
将下列代码加入OdometerService

    private LocationListener listener;@Overridepublic void onCreate() {super.onCreate();listener = new LocationListener() {@Overridepublic void onLocationChanged(@NonNull Location location) {}};}

3、请求位置更新

要得到位置更新需要做三件事:
创建一个位置管理器来访问Android的位置服务;
指定一个位置提供器;
请求这个位置提供者将用户当前位置的定期更新发送到我们在上一页增加的位置监听器。

创建位置管理器

要使用getSystemService方法来创建

locManager = (LocationManager) getSystemService(Context.LOCALE_SERVICE);
指定位置提供者

指定位置提供者用来确定用户的位置。有两个主要选项GPS和network。
GPS选项使用设备的GPS传感器确定用户的位置,网络选项会利用Wifi、蓝牙或移动网络。
并不是所有设备都同时又这两类位置提供者,所以可以使用位置管理器的getBestProvider方法得到设备上最准确的位置提供者,这个方法有两个参数:一个Criteria对象(可以用来指定电量需求之类的标准),以及一个标志(指示当前是否应当在设备上启用)。

String provider = locManager.getBestProvider(new Criteria(), true);
请求位置更新

要用位置管理器的requestLocationUpdates方法让位置提供者将更新发送到位置监听器。
这个方法有4个参数:位置提供者、更新的最小时间间隔,位置更新之间的最小距离,你希望接收这些更新的位置监听器。

//检查是否有权限
if (ContextCompat.checkSelfPermission(this, PERMISSION_STRIMG)== PackageManager.PERMISSION_GRANTED){String provider = locManager.getBestProvider(new Criteria(), true);if (provider != null)locManager.requestLocationUpdates(provider, 1000, 1, listener);}
更新的OdometerService代码
package com.hafd.odometer;import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.IBinder;import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.content.PackageManagerCompat;import java.util.Random;public class OdometerService extends Service {private final IBinder binder = new OdometerBinder();private final Random random = new Random();//创建一个绑定式服务时,需要提供一个Binder实现public class OdometerBinder extends Binder {//活动将使用这个方法得到OdometerService的一个引用OdometerService getOdometer() {return OdometerService.this;}}@Overridepublic IBinder onBind(Intent intent) {return binder;}public double getDistance() {return random.nextDouble();}private LocationListener listener;private LocationManager locManager;public static final String PERMISSION_STRIMG =Manifest.permission.ACCESS_FINE_LOCATION;@SuppressLint("ServiceCast")@Overridepublic void onCreate() {super.onCreate();listener = new LocationListener() {@Overridepublic void onLocationChanged(@NonNull Location location) {}};locManager = (LocationManager) getSystemService(Context.LOCALE_SERVICE);if (ContextCompat.checkSelfPermission(this, PERMISSION_STRIMG)== PackageManager.PERMISSION_GRANTED){String provider = locManager.getBestProvider(new Criteria(), true);if (provider != null)locManager.requestLocationUpdates(provider, 1000, 1, listener);}}
}

4、计算走过的距离

可以使用Location对象的diatanceTo方法来得到两个位置之间的距离

    private static double distanceInMeters;private static Location lastLocation = null;public void onCreate() {super.onCreate();listener = new LocationListener() {@Overridepublic void onLocationChanged(@NonNull Location location) {if (location == null)lastLocation = location;distanceInMeters += location.distanceTo(lastLocation);lastLocation = location;}};}public double getDistance() {return this.distanceInMeters;}

5、停止监听器继续获取位置更新

    public void onDestroy() {super.onDestroy();if (locManager != null && listener != null) {if (ContextCompat.checkSelfPermission(this, PERMISSION_STRIMG) == PackageManager.PERMISSION_GRANTED){locManager.removeUpdates(listener);}locManager = null;listener = null;}}

完整的OdometerService.java

package com.hafd.odometer;import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.IBinder;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;public class OdometerService extends Service {private static double distanceInMeters;private static Location lastLocation = null;private final IBinder binder = new OdometerBinder();private LocationListener listener;private LocationManager locManager;public static final String PERMISSION_STRIMG =Manifest.permission.ACCESS_FINE_LOCATION;//创建一个绑定式服务时,需要提供一个Binder实现public class OdometerBinder extends Binder {//活动将使用这个方法得到OdometerService的一个引用OdometerService getOdometer() {return OdometerService.this;}}@Overridepublic IBinder onBind(Intent intent) {return binder;}public double getDistance() {return this.distanceInMeters;}@SuppressLint("ServiceCast")@Overridepublic void onCreate() {super.onCreate();listener = new LocationListener() {@Overridepublic void onLocationChanged(@NonNull Location location) {if (location == null)lastLocation = location;distanceInMeters += location.distanceTo(lastLocation);lastLocation = location;}};locManager = (LocationManager) getSystemService(Context.LOCALE_SERVICE);if (ContextCompat.checkSelfPermission(this, PERMISSION_STRIMG)== PackageManager.PERMISSION_GRANTED){String provider = locManager.getBestProvider(new Criteria(), true);if (provider != null)locManager.requestLocationUpdates(provider, 1000, 1, listener);}}@Overridepublic void onDestroy() {super.onDestroy();if (locManager != null && listener != null) {if (ContextCompat.checkSelfPermission(this, PERMISSION_STRIMG)== PackageManager.PERMISSION_GRANTED){locManager.removeUpdates(listener);}locManager = null;listener = null;}}
}

二、让应用请求权限

现在的应用必须在系统设置里面手动为这个应用开启位置权限,如何要让应用自己请求权限呢?

检查并请求权限

修改代码使得只有当用户授予了必要的权限时MainActivity才绑定到这个服务,这个权限由OdometerService中定义的PERMISSION_STRING常量指定。如果没有授予权限就请求这个权限。
在MainActivity更新onStart方法。

    @Overrideprotected void onStart() {super.onStart();//如果没有授权就请求权限if (ContextCompat.checkSelfPermission(this, OdometerService.PERMISSION_STRIMG) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this,new String[]{OdometerService.PERMISSION_STRIMG}, PERMISSION_REQUEST_CODE);}else {Intent intent = new Intent(this, OdometerService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE); }}

检查用户对权限请求的响应

使用requestPermissions方法请求用户授予一个权限时,不能通过检查它的返回值来确定是否授予了权限。这是因为权限请求是异步发生的,当你等待用户响应时并不会阻塞当前线程。
正确的做法是要检查用户的响应,需要覆盖活动的onRequestPermissionsResult方法。这个方法有3个参数:
一个标识权限请求的int请求代码、
一个权限String数组、
以及一个对应请求结果的int数组。
使用这个方法时,首先检查int请求代码是否与requestPermissions方法中使用的代码一致。如果一致则检查是否已经授予这个权限。

    @SuppressLint("MissingSuperCall")public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){switch (requestCode) {case PERMISSION_REQUEST_CODE: {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {Intent intent = new Intent(this, OdometerService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE);}else {}}}}

如果拒绝授予就发出一个通知

如果用户不授予权限,不允许使用他们当前位置,OdometerService就无法得出他们走了多远。这里使用通知告知用户。
先增加两个字符串:

    <string name="app_name">Odometer</string><string name="permission_denied">Location permission required</string>

再将下列代码增加到上一节空白的else语句中:

NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(android.R.drawable.ic_menu_compass).setContentTitle(getResources().getString(R.string.app_name)).setContentText(getResources().getString(R.string.permission_denied)).setPriority(NotificationCompat.PRIORITY_HIGH).setVibrate(new long[] {1000, 1000}).setAutoCancel(true);Intent actionIntent = new Intent(this, MainActivity.class);PendingIntent actionPendingIntent = PendingIntent.getActivity(this,0,actionIntent,PendingIntent.FLAG_UPDATE_CURRENT);builder.setContentIntent(actionPendingIntent);NotificationManager notificationManager =(NotificationManager) getSystemService(NOTIFICATION_SERVICE);notificationManager.notify(NOTIFICATION_ID, builder.build());

完整的MainActivity

package com.hafd.odometer;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.widget.TextView;import java.util.Locale;public class MainActivity extends AppCompatActivity {private OdometerService odometer;private boolean bound = false;private final int PERMISSION_REQUEST_CODE = 698;private final int NOTIFICATION_ID = 423;private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {OdometerService.OdometerBinder odometerBinder = (OdometerService.OdometerBinder) iBinder;odometer = odometerBinder.getOdometer(); //使用IBinder得到服务的一个引用bound = true;}@Overridepublic void onServiceDisconnected(ComponentName componentName) {bound = false;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);displayDistance();}@SuppressLint({"MissingSuperCall", "NotificationPermission"})public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){switch (requestCode) {case PERMISSION_REQUEST_CODE: {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {Intent intent = new Intent(this, OdometerService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE);}else {NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(android.R.drawable.ic_menu_compass).setContentTitle(getResources().getString(R.string.app_name)).setContentText(getResources().getString(R.string.permission_denied)).setPriority(NotificationCompat.PRIORITY_HIGH).setVibrate(new long[] {1000, 1000}).setAutoCancel(true);Intent actionIntent = new Intent(this, MainActivity.class);PendingIntent actionPendingIntent = PendingIntent.getActivity(this,0,actionIntent,PendingIntent.FLAG_UPDATE_CURRENT);builder.setContentIntent(actionPendingIntent);NotificationManager notificationManager =(NotificationManager) getSystemService(NOTIFICATION_SERVICE);notificationManager.notify(NOTIFICATION_ID, builder.build());}}}}@Overrideprotected void onStart() {super.onStart();//如果没有授权就请求权限if (ContextCompat.checkSelfPermission(this, OdometerService.PERMISSION_STRIMG) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this,new String[]{OdometerService.PERMISSION_STRIMG}, PERMISSION_REQUEST_CODE);}else {Intent intent = new Intent(this, OdometerService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE);}}protected void onStop() {super.onStop();if (bound) {unbindService(connection);bound = false;}}private void displayDistance() {final TextView distanceView = (TextView) findViewById(R.id.distance);final Handler handler = new Handler();handler.post(new Runnable() {@Overridepublic void run() {double distance = 0.0;//如果得到OdometerService的一个引用,而且绑定到这个服务,则调用getDistance。if (bound && odometer != null)distance = odometer.getDistance();String distanceStr = String.format(Locale.getDefault(), "%1$,.2f miles", distance);distanceView.setText(distanceStr);//每秒运行一次handler.postDelayed(this, 1000);}});}
}

试一试

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/106126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

巧用正则表达式

文章目录 题目巧用正则表达式&#xff0c;题目将十进制转为16进制&#xff0c;可以采用Java的语法来表示 题目 巧用正则表达式&#xff0c;题目将十进制转为16进制&#xff0c;可以采用Java的语法来表示 String nInteger.toString(num,16); 那如何确定是否都是字母呢a-f呢&…

车载多源融合定位

终端硬件由两部分组成&#xff0c;组合导航处理板和地磁导航处理板。 组合导航处理板负责采集加速度计、陀螺、GNSS和轮速计等数据进行组合导航解算&#xff0c;差分数据通过6Q主板获取到后通过串口发送至组合导航处理板。地磁导航处理板负责地磁数据采集&#xff0c;保存至数…

Rxjava3 全新详解及常用操作符

简介 RxJava 是一个基于 Java 的响应式编程库&#xff0c;用于处理异步事件流和数据流。它是由 Netflix 开发并开源&#xff0c;现在广泛用于 Android 和 Java 后端开发。RxJava 提供了一种用于组合和处理异步数据的丰富工具集&#xff0c;它的核心思想是将数据流视为一系列事…

微信发红包(各种红包类型)-测试用例设计

微信发红包&#xff08;各种红包类型&#xff09;

总结10.15

项目进展 登陆注册&#xff0c;连接了数据库&#xff0c;找回密码写到了通过给邮箱发送验证码&#xff0c;然后重新输入密码 项目看法 之后俩天加紧把这个登陆注册这些搞完&#xff0c;注册用到的随机生成一个账号且不重复&#xff0c;且设置一个邮箱作为之后找回密码时候的…

CVPR 2023 | 数据驱动的解释对分布外数据具有鲁棒性吗?

论文链接&#xff1a; https://arxiv.org/abs/2303.16390 代码链接&#xff1a; https://github.com/tangli-udel/DRE 01. 研究背景&#xff1a;数据驱动的解释对分布外数据具有鲁棒性吗&#xff1f; 近年来&#xff0c;将黑盒机器学习&#xff08;ML&#xff09;模型用于高风…

CentOS 7 编译安装Boost

1、前提条件 linux平台/CentOS 7 下要编译安装Boost除gcc和gcc-c之外&#xff0c;还需要两个开发库&#xff1a;bzip2-devel 和python-devel &#xff0c;因此在安装前应该先保证这两个库已经安装。 安装指令: yum install bzip2 bzip2-devel bzip2-libs python-devel Cent…

zookeeper源码学习笔记(一)

一、缘起 1、CP还是AP 作为一个在大数据行业工作了7&#xff5e;8年的老兵&#xff0c;在被问到zookeeper和CAP时&#xff0c;竟然有些恍惚&#xff0c;AP还是CP&#xff1f; 看了一些博文&#xff0c;答案几乎都是CP&#xff1f; zookeeper的实现中&#xff0c;P是一定的&…

低代码提速应用开发

低代码介绍 低代码平台是指一种能够帮助企业快速交付业务应用的平台。自2000年以来&#xff0c;低代码市场一直充斥着40大大小小的各种玩家&#xff0c;比如国外的Appian、K2、Pega Systems、Salesforce和Ultimus&#xff0c;国内的H3 BPM。 2015年以后&#xff0c;这个市场更是…

2023年厦门市高等职业院校技能竞赛软件测试竞赛规程

2023年厦门市高等职业院校技能竞赛 软件测试竞赛规程 一、赛项名称 赛项名称&#xff1a;软件测试 竞赛形式&#xff1a;团体赛 赛项专业大类&#xff1a;电子信息 二、竞赛目的 &#xff08;一&#xff09;检验教学成效 本赛项竞赛内容以《国家职业教育改革实施方案》为设计方…

Docker逃逸---procfs文件挂载

一、产生原因 将宿主机/proc目录挂载进了容器&#xff0c;而该目录内的/proc/sys/kernel/core_pattern文件是负责进程奔溃时内存数据转储的&#xff0c;当第一个字符是| 管道符时&#xff0c;后面的部分会以命令行的方式进行解析并运行&#xff0c;攻击者可以将恶意文件写入该…

【Python数据分析工具】

文章目录 概要整体架构流程技术名词解释 概要 数据分析是一种通过收集、处理、分析和解释大量数据&#xff0c;以发现有价值信息、洞察趋势、制定决策并解决问题的过程。在现代科技和互联网的推动下&#xff0c;数据分析变得日益重要。它不仅仅是对数字和图表的简单解释&#…

MacOS ventura跳过配置锁

Macbook pro 2021跳配置锁 1.什么是配置锁&#xff1f; 配置锁顾名思义就是美国一些企业和公司向苹果工公司定制采购的机器&#xff0c;这些机器一般供应内部员工使用&#xff0c;这种机器和正常机没有什么区别&#xff0c;也是无锁三网机器&#xff0c;功能和正常机器一摸一…

如何用精准测试来搞垮团队?

测试行业每年会冒出来一些新鲜词&#xff1a;混沌工程、精准测试、AI测试…… 这些新概念、新技术让我们感到很焦虑&#xff0c;逼着自己去学习和了解这些新玩意&#xff0c;担心哪一天被淘汰掉。 以至于给我这样的错觉&#xff0c;当「回归测试」、「精准测试」这两个词摆在一…

解决git在window11操作很慢,占用很大cpu的问题

【git在window11操作很慢&#xff0c;占用很大cpu&#xff0c;最后也执行失败】 在谷歌输入&#xff1a;git very slow in window 11。通过下面链接终于找到了解决方案&#xff1a; https://www.reddit.com/r/vscode/comments/sulebx/slow_git_in_wsl_after_updating_to_window…

怒刷LeetCode的第26天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;动态规划 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;有限状态自动机 方法二&#xff1a;正则表达式 第三题 题目来源 题目内容 解决方法 方法一&#xff1a;从最后一位向前遍历 方法二…

测试除了点点点,还有哪些内容呢?

今天和一个网友讨论了一下关于互联网行业中测试的情况&#xff0c;希望能够了解现在的互联网行业主要的测试工作内容。小编根据以往的工作经历和经验情况&#xff0c;来做一个总结和整理。 1、岗位分类 现在的岗位划分主要是分为两大类&#xff1a;测试工程师 和 测试开发工程…

matlab相机标定实验

实验原理 1. 相机标定坐标系 相机的参数对目标的识别、定位精度有很大的影响&#xff0c;相机标定就是为了求出相机的内外参数。标定中有3个不同层次的坐标系&#xff1a;世界坐标系、相机坐标系和图像坐标系&#xff08;图像物理坐标系和图像像素坐标系&#xff09;。世界坐…

数据结构--》掌握数据结构中的排序算法

当我们面对海量数据时&#xff0c;如何高效地将其排序是数据结构领域中一个重要的问题。排序算法作为其中的关键部分&#xff0c;扮演着至关重要的角色。 无论你是初学者还是进阶者&#xff0c;本文将为你提供简单易懂、实用可行的知识点&#xff0c;帮助你更好地掌握排序算法在…

pdf怎么压缩?pdf文件缩小的方法在这里

PDF文件由于其跨平台、可打印性强等特点&#xff0c;成为了我们日常工作中经常使用的一种文件格式。然而&#xff0c;这种格式的文件有时候会因为过于庞大而给我们的存储和传输带来困扰&#xff0c;其实&#xff0c;这种情况只需要通过一些工具对PDF文件进行压缩&#xff0c;即…