一、开发环境:
VS2019-16.10.0
Xamarin-16.10.000.228
Xamarin.Android SDK-11.3.0.1
荣耀20Pro真机调试
二、预实现目的
使程序可以一直保持后台运行,进行定位,并且程序可以开机自启。
三、详细方法
原理:通过创建前台服务的方式保持App处于活动状态。
1.AndroidManifest.xml配置权限
<application android:label="MyTest" android:theme="@style/MainTheme" android:icon="@drawable/icon" android:debuggable="true" android:allowBackup="true">
<!--前台服务想要调用定位功能,必须加上这个;服务名字前面要加上命名空间,MyTest.Droid就是我的服务类所在命名空间-->
<service android:name="MyTest.Droid.GaodeService" android:foregroundServiceType="location" />
</application>
<!--允许程序打开网络套接字-->
<uses-permission android:name="android.permission.INTERNET" />
<!--允许程序设置内置sd卡的写权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--允许程序获取网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--允许程序访问WiFi网络信息-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许程序读写手机状态和身份-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--允许程序访问CellID或WiFi热点来获取粗略的位置-->
<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.CHANGE_WIFI_STATE" />
<!--这个权限用于允许程序在手机屏幕关闭后后台进程仍然运行-->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--用于申请获取蓝牙信息进行室内定位-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!--用于申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!--用于创建前台服务-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
2.创建通知管道
创建最简单最粗略的通知管道的方法,主要的参数是管道id,创建通知时要使用
public static void CreateNotificationChannel(Context context, string channelID, string channelName)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
((NotificationManager)context.GetSystemService(Context.NotificationService))
.CreateNotificationChannel(new NotificationChannel(channelID, channelName, NotificationImportance.Default));
}
}
3.创建通知
下面是创建通知的简化方法, 一个通知标题,文本,图标,一个前台服务貌似必须设置为True的项, 通知管道id在NotificationCompat.Builder构造函数填入
public static Notification CreateServerNotification(string contentTitle, string contentText, Context context, string channelID)
{
return new NotificationCompat.Builder(context, channelID)
.SetContentTitle(contentTitle)
.SetContentText(contentText)
.SetSmallIcon(Resource.Mipmap.icon)
.SetOngoing(true)
.Build();
}
4.开启服务的方法
android 8.0及以上版本开启前台服务需要使用StartForegroundService,这个方法可以放在你想要调用服务的类中,比如MainActivity
public static void StartServer(Context context, Intent intent)
{
context.StartForegroundService(intent);
}
5.声明服务
[Service] //此处Service不可写成Service(IsolatedProcess=true),否则普通调用服务方法不起作用
public sealed class MyServer : Service
{
public override void OnCreate()
{
base.OnCreate();
//此处在第一次调用服务,即服务创建时触发,第二次及以后再调用不会再触发
const int NOTIFICATION_ID = 345;
const string CHANNEL_ID = "自己起一个id";
const string CHANNEL_NAME = "自己起一个name";
CreateNotificationChannel(this, CHANNEL_ID, CHANNEL_NAME);
var notification = CreateServerNotification("标题", "内容", this, CHANNEL_ID);
StartForeground(NOTIFICATION_ID, notification);
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
//此处可添加自己想要通过前台服务做的事情,比如后台定位功能,每次调用服务都会触发
//startlocation()
return StartCommandResult.RedeliverIntent; //此返回值可以在服务被终止时尝试重启服务,并可传回当时的Intent
}
public override void OnDestroy()
{
base.OnDestroy();
}
public override IBinder OnBind(Intent intent)
{
return null;
}
}
6.在MainActivity中调用服务
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IAMapLocationListener
{
//...
protected override void OnStart()
{
base.OnStart();
Intent serviceToStart = new Intent(this, typeof(MyServer));
StartServer(this, serviceToStart);
}
public static void StartServer(ContextWrapper context, Intent intent)
{
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
context.StartForegroundService(intent);
}
else
{
context.StartService(intent);
}
}
//...
}
四、注意事项
服务本身还会受到下面一些因素的影响
1.是否允许后台活动,
2.是否忽略电池优化
3.针对荣耀机型,
1>可以在“手机管家-应用启动管理”中设置应用手动管理,允许后台运行。
2>打开应用后,在手机任务列表视图中,下拉app界面,app右上角会有小锁图标出现,手机就会把app加入保护列表,不会随便杀死该app。
参考连接:
Xamarin Android 创建前台服务的个人粗略总结 - 雷开封 - 博客园 (cnblogs.com)
服务概览 | Android 开发者 | Android Developers (google.cn)
Foreground services | Android 开发者 | Android Developers (google.cn)
Xamarin.Android服务的实现 - y-z-f - 博客园 (cnblogs.com)