如何总是在后台运行一个服务?

我正在创build一个类似于内置短信应用程序的应用程序。

我需要的:

  • 一个始终在后台运行的服务
  • 每5分钟。 该服务检查设备的当前位置并调用Web服务
  • 如果符合某些标准,服务应该生成通知(就像短信应用程序一样)
  • 当通知被点击时,用户被带到应用程序(就像短信应用程序)
  • 当应用程序安装时,服务应该启动
  • 当设备重新启动时,服务应该启动

我曾经尝试过:
– 运行一个正常的服务,直到Android杀死该服务才工作得很好
– 使用AlarmManager进行5分钟。 间隔呼叫服务。 但我无法做到这一点。

一个始终在后台运行的服务

正如你所发现的,这是不可能的 。 这也是不好的devise 。

每5分钟。 该服务检查设备的当前位置并调用Web服务

使用AlarmManager

使用AlarmManager进行5分钟。 间隔呼叫服务。 但我无法做到这一点。

下面是一个示例项目,展示了如何使用它以及使用WakefulIntentService以便在尝试执行整个Web服务时保持清醒状态。

如果您仍然遇到问题,请打开一个关于您遇到的与AlarmManager的具体问题的新问题,这些问题会给您带来悲伤。

我的一个应用程序做了非常相似的事情。 为了在特定时间后唤醒服务,我推荐postDelayed()

有一个处理程序字段:

 private final Handler handler = new Handler(); 

和一个进入Runnable

 private final Runnable refresher = new Runnable() { public void run() { // some action } }; 

您可以在可运行的情况下激活您的通知。

在服务build设上,每次执行之后就像这样开始:

 handler.postDelayed(refresher, /* some delay in ms*/); 

onDestroy()删除post

 handler.removeCallbacks(refresher); 

要在开机时启动服务,您需要一个自动启动器。 这在你的清单

 <receiver android:name="com.example.ServiceAutoStarter"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> 

ServiceAutoStarter看起来像这样:

 public class ServiceAutoStarter extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { context.startService(new Intent(context, UpdateService.class)); } } 

停止操作系统从杀死服务是棘手的。 此外,您的应用程序可能会有RuntimeException和崩溃,或者您的逻辑可能会停滞。

在我的情况下,它似乎有助于始终使用BroadcastReceiver刷新屏幕上的服务。 因此,如果更新链停滞,用户使用手机将会复活。

在服务中:

 private BroadcastReceiver screenOnReceiver; 

在你的服务onCreate()

 screenOnReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Some action } }; registerReceiver(screenOnReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON)); 

然后用onDestroy()取消注册你的服务

 unregisterReceiver(screenOnReceiver); 

你可以做一些简单的实现:

 public class LocationTrace extends Service implements LocationListener{ // The minimum distance to change Updates in meters private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters private static final int TWO_MINUTES = 100 * 10; // The minimum time between updates in milliseconds private static final long MIN_TIME_BW_UPDATES = 1000 * 10; // 30 seconds private Context context; double latitude; double longitude; Location location = null; boolean isGPSEnabled = false; boolean isNetworkEnabled = false; protected LocationManager locationManager; @Override public int onStartCommand(Intent intent, int flags, int startId) { this.context = this; get_current_location(); // Toast.makeText(context, "Lat"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show(); return START_STICKY; } @Override public void onLocationChanged(Location location) { if((location != null) && (location.getLatitude() != 0) && (location.getLongitude() != 0)){ latitude = location.getLatitude(); longitude = location.getLongitude(); if (!Utils.getuserid(context).equalsIgnoreCase("")) { Double[] arr = { location.getLatitude(), location.getLongitude() }; // DO ASYNCTASK } } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } /* * Get Current Location */ public Location get_current_location(){ locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); if(!isGPSEnabled && !isNetworkEnabled){ }else{ if (isGPSEnabled) { if (location == null) { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); // Toast.makeText(context, "Latgps"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show(); } } } } if (isNetworkEnabled) { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); if (locationManager != null) { if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); // Toast.makeText(context, "Latgps1"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show(); } } } } return location; } public double getLatitude() { if(location != null){ latitude = location.getLatitude(); } return latitude; } public double getLongitude() { if(location != null){ longitude = location.getLongitude(); } return longitude; } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { if(locationManager != null){ locationManager.removeUpdates(this); } super.onDestroy(); } } 

您可以通过以下方式启动服务:

 /*--Start Service--*/ startService(new Intent(Splash.this, LocationTrace.class)); 

在清单中:

  <service android:name=".LocationTrace"> <intent-filter android:priority="1000"> <action android:name="android.location.PROVIDERS_CHANGED"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>