【问题标题】:Automatically start an app through GPS events on iOS and Android with Xamarin.Forms使用 Xamarin.Forms 在 iOS 和 Android 上通过 GPS 事件自动启动应用程序
【发布时间】:2016-11-28 14:03:43
【问题描述】:

在工作中,我们创建了一个应用程序来跟踪用户上下班的路线,并且我们内置了自动记录功能,但它的行为方式并不符合我们的预期。似乎这个自动系统在一两天不活动后被操作系统关闭(手机在那段时间甚至不移动,它们基本上只用于测试)。

在 iOS 上,我们使用 CLRegions 在用户当前位置周围创建几个区域,在用户的确切位置创建了 5 个具有不同半径的区域,并在距离用户 10 处的圆周上创建了 12 个区域米(这些半径为 80 米)。还指示 CLLocationManager 对象开始监视重大更改和访问(尽管它们甚至还没有被触发一次)。

在 Android 上,我们通过 LocationServices API 使用地理围栏,这里我们只有用户当前位置周围的 5 个增量半径。如果用户在 Android 上关闭应用程序或重新启动手机,它将启动一个后台服务,该服务将重新初始化地理围栏并开始监控它们。

当我通过在外面走一点来测试它们时,这两个系统运行得非常好,但似乎在一两天不活动后(也就是周末)它们停止工作了。我已经调试了很长时间了,尽管它变得更好了,但它仍然不完美。

是否有一个可靠的系统在触发地理围栏/区域时在后台自动启动应用程序,无论应用程序关闭多长时间?我知道这两个操作系统处理后台任务的方式非常不同,但我不太确定这种方式使用 GPS 的长期限制。

我们正在制作的应用程序是用 Xamarin Forms 编写的,但这些系统是在其本机项目中编写的(仍然使用 C#,但可以完全访问整个本机平台)

【问题讨论】:

    标签: android ios xamarin.forms android-geofence clregion


    【解决方案1】:

    Android 服务的问题在于,操作系统会终止后台服务,因为它被认为是低优先级,然后按时间间隔重新启动。这可能会在几天内发生多次,每次都会增加重新启动服务之前的时间长度(有些手机只是使用设定的时间,没有增加)。

    我的建议是,如果您想要始终在线服务,则需要将其设置为 foreground service。我会给出一些代码示例来说明如何实现这一点,但我对 Xamarin 不是很了解,所以我不想给你任何不好的例子。

    另一种方法是使用AlarmManagerPendingIntent 来检查服务是否正在运行并在未运行时启动它。请注意,如果您经常这样做,可能会导致明显的电池消耗,但如果您不经常这样做,您可能会错过地理围栏事件。

    希望这会有所帮助,祝你好运!

    更新 #1

    以下是在前台运行服务和运行 AlarmManager 的代码示例。

    前景

    这确实是让您的应用保持活力的最简单方法。

    public class ForegroundService extends Service{
        @Override
        public int onStartCommand(Intent intent, int flags, int startId){
            Notification notification = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.mipmap.icon)
                    .setContentTitle("TITLE")
                    .setContentText("This is an example notification!")
                    .build();
            startForeground(ID, notification);
            //Do your stuff here
        }
    
        @Override
        public void onDestroy(){
            super.onDestroy();
            stopForeground(true);
            //If you have anything else you want done here...
        }
    }
    

    报警管理器

    这将按照您设置的时间间隔(本示例为 10 分钟)不断尝试创建此服务。不过,这里有一些陷阱。首先,由于 Android 6.0 引入了 Doze Mode,AlarmManager 可能不会在手机处于睡眠状态时启动,这意味着服务可能会死掉一段时间。其次,这会多次调用onStartCommand 函数,所以你需要逻辑来处理它。

    public class AlwaysOnService extends Service{
        @Override
        public int onStartCommand(Intent intent, int flags, int startId){
    
            AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
            PendingIntent pi = PendingIntent.getService(this, requestCode, new Intent(this, AlwaysOnService.class), PendingIntent.FLAG_UPDATE_CURRENT);
            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + MIN_10_IN_MILLIS, pi);
            //Do your stuff here
            return START_STICKY;
        }
    
        @Override
        public void onDestroy(){
            super.onDestroy();
            AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
            PendingIntent pi = PendingIntent.getService(this, requestCode, new Intent(this, AlwaysOnService.class), PendingIntent.FLAG_NO_CREATE);
            if(pi != null){
                am.cancel(pi);
                pi.cancel();
            }
            //If you have anything else you want done here...
        }
    }
    

    在这两者中,将服务设置为前台服务可能是最简单的事情,除非你真的做不到,否则 AlarmManager 是采取的路线。

    【讨论】:

    • 感谢您提供的信息,我并不完全意识到在 Android 上运行一段时间后系统甚至会停止后台服务。您是否认为有一种方法可以检测 Intent 何时停止并采取行动?哦,你可以很容易地给出一个 Java 示例,在大多数情况下,它是一种不同的语法,而不是实际上与 Xamarin 不同的语言(尽管清单选项是在 C# 代码中定义的,编译器会处理清单 XML)
    • 至于检测服务是否被停止,您需要一个进程来检查它,这反过来也可能被杀死,这让我们回到第一点。我已经用前台服务的代码示例和定期重新启动服务的警报管理器更新了我的答案。希望这对你有用!
    猜你喜欢
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    相关资源
    最近更新 更多