安卓开发后台应用周期循环获取位置信息上报服务器

这篇具有很好参考价值的文章主要介绍了安卓开发后台应用周期循环获取位置信息上报服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题背景

最近有需求,在APP启动后,退到后台,还要能实现周期获取位置信息上报服务器,研究了一下实现方案。

问题分析

一、APP退到后台后网络请求实现
APP退到后台后,实现周期循环发送网络请求。目前尝试了两种方案是OK,如下:
(1)AlarmManager + 前台服务 +广播的方案,可以正常实现,大体思路是,启动一个前台服务,使用AlarmManager发起一个定时广播,然后广播接收器接收到广播后,循环去执行service的操作。
(2)使用jetpeck库提供的worker实现,基于PeriodicWorkRequest实现一个周期执行的任务,比如周期设置为15分钟,可以在后台稳定执行。
二、APP退到后台后获取地理位置实现
APP申请位置时,用户选择了列表中的始终允许后,APP在后台是可以正常获取到位置信息的。不过这里有个坑,因为安卓11版本后退位置信息管控策略进行了更新,如果APP的target sdk版本大于29时,需要分别申请前台位置权限和后台位置权限,本APPtargetsdk是小于等于29的,可以同时申请前台位置权限和后台位置权限。(compileSdkVersion小于29时,会没有这个后台位置权限,需要最好升级到29)

问题解决

下面展示大概的代码,可以参考实现。
(1)引入依赖

api('androidx.work:work-runtime:2.0.1')

(2)manifest文件中增加申请权限

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 这个权限用于访问GPS定位 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

(3)权限申请(同时申请位置权限和后台位置权限)

        RxPermissionHelper helper = new RxPermissionHelper(this);
        helper.requestEach(new RxPermissionHelper.PermissionCallback() {
            @Override
            public void granted(String permissionName) {
                LogUtil.writerLog("ACCESS_FINE_LOCATION granted");
            }

            @Override
            public void denied(String permissionName, boolean forever) {

            }

            @Override
            public void result(boolean allGranted) {

            }
        }, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION);

(4)work类:去执行前台服务


/**
 * work类执行定时任务
 */
public class SimpleWorker extends Worker {
    private CurPosUtil curPosUtil;

    public SimpleWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }
    @NonNull
    @Override
    public Result doWork() {
        Log.d("baorant", "执行调度任务");
        LogUtil.writerLog("执行调度任务");
        startService();
        return Result.success();
    }

    private void startService() {
//        curPosUtil = new CurPosUtil(getApplicationContext());
        Intent intent = new Intent(getApplicationContext(), RecordService.class);
        getApplicationContext().startService(intent);
    }
}

(5)RecordService前台服务类(需要在manifest文件中配置)

/**
 * 一个定时任务
 *
 * 方案:使用前台服务去执行网络请求,定时发送广播,然后在广播接收器中重新启动服务,实现循环后台服务。
 */
public class RecordService extends Service {
    private CurPosUtil curPosUtil;

    /**
     * 每30秒更新一次数据
     */
    private static final int ONE_Miniute= 30 * 1000;
    private static final int PENDING_REQUEST=0;
    int count = 0;

    public RecordService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        curPosUtil = new CurPosUtil(getApplicationContext());
        LogUtil.writerLog("RecordService onCreate");

        if (Build.VERSION.SDK_INT >=    Build.VERSION_CODES.O) {
            String NOTIFICATION_CHANNEL_ID = "package_name";
            String channelName = "My Background Service";
            NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,channelName, NotificationManager.IMPORTANCE_LOW);
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            manager.createNotificationChannel(channel);
            Notification notification = new Notification.Builder(this,NOTIFICATION_CHANNEL_ID)
                    .setSmallIcon(R.drawable.ic_dial_icon)  // the status icon
                    .setWhen(System.currentTimeMillis())  // the time stamp
                    .setContentText("定时服务正在运行")  // the contents of the entry
                    .build();

            startForeground(2, notification);
        }
    }

    /**
     * 调用Service都会执行到该方法
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtil.writerLog("RecordService:  onStartCommand");

        // 这里模拟后台操作
        initPos();

        return super.onStartCommand(intent, flags, startId);
    }

    private void initPos() {
        curPosUtil = new CurPosUtil(this);
        curPosUtil.getCurPos(new CurPosUtil.CurPosCallback() {
            @Override
            public void getCurPos(double s, double s1, String s2) {
                LogUtil.writerLog(DateUtil.timeToDate(String.valueOf(System.currentTimeMillis())));
                LogUtil.writerLog("getCurPos: " + s + " " + s1 + " " + s2);
                commonLogin(s + " " + s1 + " " + s2);
            }
        });
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    public void commonLogin(String position) {
        RetrofitHelper.getInstance().login(position, "", "", "",
                        "", "", "", "")
                .subscribe(new Observer<Boolean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Boolean aBoolean) {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

(6)activity中启动周期任务,周期15分钟循环执行

 PeriodicWorkRequest.Builder request =
                        new PeriodicWorkRequest.Builder(SimpleWorker.class, 15
                                , TimeUnit.MINUTES).addTag("simpleTask");
                LogUtil.writerLog(DateUtil.timeToDate(String.valueOf(System.currentTimeMillis())));
                LogUtil.writerLog("点击执行task");
                WorkManager.getInstance().enqueue(request.build() );

(7)LogUtil工具类,输出日志到文件,方便定位

/**
 * 日志工具,输出日志到文件
 */
public class LogUtil {

    /**
     * 路径 "/data/data/com包名/files/backLogTest"
     *
     * @param msg 需要打印的内容
     */
    public static void writerLog(String msg) {
        Log.d("baorant", msg);
        // 保存到的文件路径
        final String filePath = App.getContext().getFilesDir().getPath();
        FileWriter fileWriter;
        BufferedWriter bufferedWriter = null;

        try {
            // 创建文件夹
            File dir = new File(filePath, "backLogTest");
            if (!dir.exists()) {
                dir.mkdir();
            }
            // 创建文件
            File file = new File(dir, "lowTemperature.txt");
            if (!file.exists()) {
                file.createNewFile();
            }
            // 写入日志文件
            fileWriter = new FileWriter(file, true);
            bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write( msg + "=======时间 :"+ getCurrentTime()+ "\n");
            bufferedWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bufferedWriter != null) {
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }


    }

    private static String getCurrentTime() {
        Calendar calendar = Calendar.getInstance();
        @SuppressLint("SimpleDateFormat")
        SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return  sdf.format(calendar.getTime());
    }
}

问题总结

运行结果如下:
安卓开发后台应用周期循环获取位置信息上报服务器,移动开发,android,服务器,运维
安卓开发后台应用周期循环获取位置信息上报服务器,移动开发,android,服务器,运维
如结果所示,基于该方案可以实现APP在后台,周期循环获取位置信息并进行上报,有兴趣的同学可以进一步深入研究。文章来源地址https://www.toymoban.com/news/detail-603555.html

到了这里,关于安卓开发后台应用周期循环获取位置信息上报服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • uniapp开发小程序解析经纬度获取当前位置信息(高德地图三)

    选择了高德地图定位 高德地图官网 小程序步骤如下:      1.首先创建应用       2.点击增添key按钮申请小程序key         3.然后下载它的微信小程序版 SDK:微信小程序 SDK         4.把下载的sdk放在公共的文件里,这里我放在了utils文件目录下          5.使用页面导入此

    2024年02月02日
    浏览(60)
  • 安卓实战开发之——使用 WIFI 进行设备搜索并获取相应信息

    目录 一、前言 二、准备条件 三、功能要求 四、显示效果 五、关键代码  此玩意是本人很早很早(记不清有多早了,反正很早)做过的一个课程任务了,无意之中翻到了,所以把它放上来。不愿再找以前写的代码了,所以放的文档里的截图。 首先需要安装配置好Java开发环境

    2024年02月09日
    浏览(38)
  • uni.app开发小程序如何获取当前经纬度、位置信息以及如何重新发起授权定位

    amap-wx.js 文件 (也可去高德官网下载)

    2024年02月16日
    浏览(60)
  • pyautogui获取鼠标位置及循环点击指定位置按钮

    pip install pyautogui可能会安装失败,需要先下载包再按照。 由于本机利用的是anconda里的python环境,所以下载后的安装步骤为: 下载包至本地:PyAutoGUI-0.9.53.tar.gz 下载地址 cd 至包下载目录下 执行命令 conda install --use-local PyAutoGUI-0.9.53.tar.gz -n base 对应含义: conda install --use-local 包文

    2024年02月11日
    浏览(103)
  • GPT应用开发:编写插件获取实时天气信息

    欢迎阅读本系列文章!我将带你一起探索如何利用OpenAI API开发GPT应用。无论你是编程新手还是资深开发者,都能在这里获得灵感和收获。 本文,我们将继续展示聊天API中插件的使用方法,让你能够轻松驾驭这个强大的工具。 首先给大家展示下插件的运行效果,如下图所示:

    2024年01月20日
    浏览(44)
  • 通过ip获取地理位置信息

    GeoLite2-City.mmdb 文件是 MaxMind 公司提供的一个免费的 IP 地址与城市地理位置映射数据库文件。它包含了 IP 地址范围与对应的城市、地区、国家、经纬度等地理位置信息的映射。这种数据库文件可以用于识别访问您的应用程序或网站的用户的地理位置,从而实现针对不同地区的

    2024年02月12日
    浏览(47)
  • 微信小程序—获取用户位置信息

    代码: 结果示例: 接下来我们需要经度(longitude)和纬度(latitude)两个属性

    2024年02月08日
    浏览(62)
  • Unity 获取手机地理位置信息

    在游戏的开发过程中,有时候会遇到需要获取玩家位置信息的需求,比如显示玩家所在的国家城市等。 有一下方法可以参考: 可以根据手机的地区和语言来做判断。 根据IP来判断所处的位置,阿里云啥的都有对应的接口服务。 根据GPS来判断。 以上方法都各有利弊吧,这里简

    2024年02月12日
    浏览(50)
  • uniapp获取用户当前位置信息(第一节)

    本篇文章分享一下我在实际开发小程序时遇到的需要获取用户当前位置的问题,在小程序开发过程中经常使用到的获取定位功能。uniapp官方也提供了相应的API供我们使用。 官网地址:uni.getLocation(OBJECT)) 首先根据官网uni.getLocation(OBJECT))来获取地理位置信息 注意:这里面有个大

    2024年02月17日
    浏览(57)
  • Golang — 根据IP获取地理位置信息

    1 ip2region 2 geoip2-golang ip2region 是一个离线IP地址定位库和IP定位数据管理框架,10微秒级别的查询效率,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现。 特点: 是一个开源的IP地理位置库。 标准化的数据格式 每个 ip 数据段的 region 信息都固定了格式:国家|区域|省

    2024年02月14日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包