我正在创建一个类似于内置短信应用的应用。
我需要什么:
我的尝试:
- 运行常规服务,直到Android杀死服务为止
- 使用AlarmManager进行5分钟。间隔呼叫服务。但我无法做到这一点。
答案 0 :(得分:33)
始终在运行的服务 背景
正如您所发现的那样,这个术语的任何真正含义都是not possible。它也是bad design。
每5分钟一次。服务检查 设备的当前位置和 调用Web服务
使用AlarmManager
。
使用AlarmManager制作5 分钟。间隔呼叫服务。但是我 无法完成这项工作。
这是一个sample project,展示了如何使用WakefulIntentService
,以及{{3}}的使用,以便您在尝试执行整个Web服务时保持清醒。
如果您一直遇到问题,请打开一个新问题,了解您遇到的让您感到悲伤的AlarmManager
具体事项。
答案 1 :(得分:26)
我的一个应用程序做了非常相似的事情。要在一段时间后唤醒服务,我建议postDelayed()
有一个处理程序字段:
private final Handler handler = new Handler();
和复习Runnable
private final Runnable refresher = new Runnable() {
public void run() {
// some action
}
};
您可以在runnable中触发通知。
在服务构建上,每次执行后都会这样开始:
handler.postDelayed(refresher, /* some delay in ms*/);
在onDestroy()
删除帖子
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);
答案 2 :(得分:3)
您可以通过一些简单的实现来完成此任务:
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>
答案 3 :(得分:0)
通过这三个步骤,您可以每5分钟唤醒大部分Android设备:
<强> 1。为不同的API设置替代AlarmManager:
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(getApplicationContext(), OwnReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);
if (Build.VERSION.SDK_INT >= 23) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
else if (Build.VERSION.SDK_INT >= 19) {
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
<强> 2。构建自己的静态BroadcastReceiver:
public static class OwnReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//do all of your jobs here
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OwnReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
if (Build.VERSION.SDK_INT >= 23) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
else if (Build.VERSION.SDK_INT >= 19) {
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
}
}
第3。将<receiver>
添加到AndroidManifest.xml
:
<receiver android:name=".OwnReceiver" />
答案 4 :(得分:0)
根据我的说法,当您希望您的服务运行时,始终意味着该应用程序被杀死时不应停止,因为如果您的应用程序正在运行或处于后台,则您的服务将一直在运行。在服务运行时终止应用程序时,会触发onTaskRemoved函数。
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.d(TAG, "onTaskRemoved: removed");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis() + 10000);
((AlarmManager) getSystemService(Context.ALARM_SERVICE)).setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), PendingIntent.getService(getApplicationContext(), 0, new Intent(getApplicationContext(), RegisterReceiverService.class), 0));
super.onTaskRemoved(rootIntent);
}
因此,基本上,一旦您杀死了该应用程序,该服务将在10秒钟后启动。 注意:如果您想使用
AlarmManager.ELAPSED_REALTIME_WAKEUP
重新启动服务的最短时间为15分钟。
请记住,您还需要在重新启动时使用BroadcastReceiver启动服务。