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.rhkb.cn/news/157163.html

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

相关文章

milvus和相似度检索

流程 milvus的使用流程是 创建collection -> 创建partition -> 创建索引(如果需要检索) -> 插入数据 -> 检索 这里以Python为例, 使用的milvus版本为2.3.x 首先按照库&#xff0c; python3 -m pip install pymilvus Connect from pymilvus import connections c…

12.SpringBoot之RestTemplate的使用

SpringBoot之RestTemplate的使用 初识RestTemplate RestTemplate是Spring框架提供用于调用Rest接口的一个应用&#xff0c;它简化了与http服务通信方式。RestTemplate统一Restfull调用的标准&#xff0c;封装HTTP链接&#xff0c;只要需提供URL及返回值类型即可完成调用。相比…

工业互联网系列1 - 智能制造中有哪些数据在传输

工业互联网以网络为基础&#xff0c;需要传输的数据种类多种多样&#xff0c;这些数据对于实时监控、生产优化、设备维护和决策支持等方面都至关重要。 以下是一些常见智能制造业中需要传输的数据类型&#xff1a; 传感器数据&#xff1a;制造设备上安装的传感器&#xff08;如…

原理:用UE5制作一个2D游戏

选中资产图片右键--Sprite Actions--Apply Paper2D Texture Settings 制作场景 把它丢到场景里&#xff0c;并把坐标归零 创建图块集tileset 打开新建的tile set&#xff0c;根据最小图块设置最小尺寸单元 选择需要的图块单元&#xff0c;add box 对新建的tile set右键创建til…

简单实现接口自动化测试(基于python+unittest)

简介 本文通过从Postman获取基本的接口测试Code简单的接口测试入手&#xff0c;一步步调整优化接口调用&#xff0c;以及增加基本的结果判断&#xff0c;讲解Python自带的Unittest框架调用&#xff0c;期望各位可以通过本文对接口自动化测试有一个大致的了解。 引言 为什么要…

深度学习中的激活函数

给定一个线性变换可以把x的值映射到一条直线上&#xff0c;如下图 输出结果就是y1w1xb1 如果y1经过一个线性变换得到一个y2&#xff0c;那么x和y2的关系是什么&#xff1f; 答案&#xff0c;毫无疑问是一条直线&#xff0c;不管如何的线性变换&#xff0c;依旧是一个线性的问…

关于网络协议的若干问题(三)

1、当发送的报文出问题的时候&#xff0c;会发送一个 ICMP 的差错报文来报告错误&#xff0c;但是如果 ICMP 的差错报文也出问题了呢&#xff1f; 答&#xff1a;不会导致产生 ICMP 差错报文的有&#xff1a; ICMP 差错报文&#xff08;ICMP 查询报文可能会产生 ICMP 差错报文…

UI自动化测试:Selenium+PO模式+Pytest+Allure整合

本人目前工作中未涉及到WebUI自动化测试&#xff0c;但为了提升自己的技术&#xff0c;多学习一点还是没有坏处的&#xff0c;废话不多说了&#xff0c;目前主流的webUI测试框架应该还是selenium&#xff0c;考虑到可维护性、拓展性、复用性等&#xff0c;我们采用PO模式去写我…

【ElasticSearch】更新es索引生命周期策略,策略何时对索引生效

大家好&#xff0c;我是好学的小师弟&#xff0c;今天和大家讨论下更新es索引生命周期策略后&#xff0c;策略何时对索引生效 结论: 若当前索引已应用策略A(旧)&#xff0c;更新完策略A后&#xff0c;新的策略A会立即对原来的已经应用该策略的索引生效&#xff1b;若当前索引…

OPPO realme 真我 一加 刷机工具下载 ColorOS Upgrade Tool

Download Realme Upgrade Tool for Windows Download ColorOS Upgrade Tool for Windows Realme升级工具是由Realme开发的Windows应用程序&#xff0c;可帮助用户升级其Realme设备上的固件。此工具支持在Realme Ul 3.0或更高版本上运行的Realme 设备。OPPO realme 真我 一加 …

GienTech动态|入选软件和信息技术服务竞争力百强;参展世界计算大会、网络安全博览会

———— GienTech动态 ———— 中电金信参展广东省网络安全博览会、世界计算机大会 近期&#xff0c;中电金信跟随中国电子参展2023年广东省网络安全博览会&#xff08;下简称“博览会”&#xff09;和2023世界计算大会。在两大峰会上&#xff0c;中电金信展出了金融级数字底…

【虹科干货】Redis Enterprise 自动分层技术:大数据集高性能解决方案

越来越多的应用程序依赖于庞大的数据集合&#xff0c;而这些应用程序必须快速响应。借助自动分层&#xff0c;Redis Enterprise 7.2 帮助开发人员轻松创建超快的应用程序。何乐而不为&#xff1f; Redis将数据存储在内存中&#xff0c;因此应用程序能以最快的速度检索和处理数…

“过度炒作”的大模型巨亏,Copilot每月收10刀,倒赔20刀

大模型无论是训练还是使用&#xff0c;都比较“烧钱”&#xff0c;只是其背后的成本究竟高到何处&#xff1f;已经推出大模型商用产品的公司到底有没有赚到钱&#xff1f;事实上&#xff0c;即使微软、亚马逊、Adobe 这些大厂&#xff0c;距离盈利之路还有很远&#xff01;同时…

精品Python的计算机科学研究话题管理系统-可视化大屏

《[含文档PPT源码等]精品Python的计算机科学研究话题管理系统设计与实现-爬虫》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技术…

Vue 中 KeepAlive 内置缓存使用

KeepAlive 介绍及使用场景 KeepAlive 是 vue 中的内置组件&#xff0c;当多个组件动态切换时可以对实例状态进行缓存&#xff0c;用法如下 <router-view v-slot"{ Component }"><keep-alive><component :is"Component" /></keep-al…

让 Visual Studio 用上 ChatGPT

一、简介 Visual chatGPT Studio 是 Visual Studio 的一个免费扩展&#xff0c;它直接在 IDE 中添加了 chatGPT 功能。它允许用户以可以根据菜单功能的方式使用 chatGPT。 二、功能介绍 该扩展提供了一组使用 ChatGPT 命令&#xff0c;可以在编辑器中选择你需要处理的代码或…

火伞云Web应用防火墙的特点与优势

在前文中&#xff0c;我们已经介绍了Web应用防火墙&#xff08;WAF&#xff09;的基本原理和重要性。接下来&#xff0c;我们将深入探讨火伞云Web应用防火墙的特点与优势&#xff0c;了解它如何为企业提供更为完善和专业的网络安全保障。 一、强大的防御能力 火伞云Web应用防火…

SSM - Springboot - MyBatis-Plus 全栈体系(二十六)

第六章 SpringBoot 快速启动框架&#xff1a;SpringBoot3 实战 一、SpringBoot3 介绍 1. SpringBoot3 简介 SpringBoot 版本&#xff1a;3.0.5 到目前为止已经学习了多种配置 Spring 程序的方式。但是无论使用 XML、注解、Java 配置类还是他们的混合用法&#xff0c;都会觉…

Git版本控制管理

Git基础_环境配置 当安装Git后首先要做的事情是设置用户名称和email地址。这是非常重要的&#xff0c;因为每次Git提交都会使用该用户信息。 设置用户信息 git config --global user.name "Bandits" git config --global user.email "gb010704163.com"查…

【安全】linux audit审计使用入门

文章目录 1 audit简介2 auditctl的使用2 audit配置和规则3 工作原理4 audit接口调用4.1 获取和修改配置4.2 获取和修改规则4.3 获取审计日志 5 audit存在的问题5.1 内核版本5.2 审计日志过多造成的缓存队列和磁盘问题5.2 容器环境下同一个命令的日志存在差异 6 参考文档 1 audi…