Android 停止运行的前台服务
我正在编写的应用程序有问题。该应用程序应该记录网络的数据-lac、小区Id和接收功率到一个文件中,只要其中一个发生变化。为了在应用程序未聚焦或设备睡眠时继续录制,我使用了foregound服务。屏幕一关闭,我的服务就停止录制。屏幕打开时,录制将恢复 这是我的密码: 谢谢你打电话来-Android 停止运行的前台服务,android,android-service,Android,Android Service,我正在编写的应用程序有问题。该应用程序应该记录网络的数据-lac、小区Id和接收功率到一个文件中,只要其中一个发生变化。为了在应用程序未聚焦或设备睡眠时继续录制,我使用了foregound服务。屏幕一关闭,我的服务就停止录制。屏幕打开时,录制将恢复 这是我的密码: 谢谢你打电话来- i = new Intent(this, WriteToFileService.class); startService(i); private PhoneStateListener MyServiceListen
i = new Intent(this, WriteToFileService.class);
startService(i);
private PhoneStateListener MyServiceListener;
private TelephonyManager tm;
private int lac ,cellId, signal;
private String phoneState;
private File outFile;
private final static int myID = 10;
//PowerManager.WakeLock wl;
@Override
public int onStartCommand(Intent senderIntent, int flags, int startId) {
Intent localIntent = new Intent(this, MainActivity.class);
localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendIntent = PendingIntent.getActivity(this, 0, localIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setTicker("Starting to record data").setContentTitle("NetInfo").setContentText("Recording data").setWhen(System.currentTimeMillis())
.setAutoCancel(false).setOngoing(true).setContentIntent(pendIntent).setSmallIcon(R.drawable.hexagon); //.setPriority(Notification.PRIORITY_HIGH)
Notification notification = builder.build();
notification.flags |= Notification.FLAG_NO_CLEAR;
startForeground(myID, notification);
//PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
//wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
//wl.acquire();
outFile = new File(getApplicationContext().getFilesDir(), senderIntent.getStringExtra("name"));
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
MyServiceListener = new PhoneStateListener() {
@Override
public void onCellLocationChanged(CellLocation location){
super.onCellLocationChanged(location);
if ((tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSDPA) || (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS)) {
GsmCellLocation MyLocation = (GsmCellLocation)tm.getCellLocation();
lac = MyLocation.getLac();
cellId = MyLocation.getCid();
}
if (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_CDMA) {
CdmaCellLocation MyLocation = (CdmaCellLocation)tm.getCellLocation();
lac = 0;
cellId = MyLocation.getBaseStationId();
}
WriteDataToFile(lac, cellId, signal, phoneState);
}
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
signal = 2 * signalStrength.getGsmSignalStrength() - 113;
WriteDataToFile(lac, cellId, signal, phoneState);
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
phoneState = "Idle";
break;
case TelephonyManager.CALL_STATE_RINGING:
phoneState = "Ringing";
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
phoneState = "On-going call";
break;
default:
phoneState = "";
break;
}
WriteDataToFile(lac, cellId, signal, phoneState);
}
};
tm.listen(MyServiceListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_CALL_STATE);
return Service.START_STICKY;
}
private void WriteDataToFile(int lac, int cellId, int signal, String phoneState)
{
try {
FileWriter fw = new FileWriter(outFile.getAbsolutePath(), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.append(new SimpleDateFormat("ddMMyyyy_HHmmss").format(Calendar.getInstance().getTime()) + " ");
bw.append(String.valueOf(lac) + " ");
bw.append(String.valueOf(cellId) + " ");
bw.append(String.valueOf(signal) + " ");
bw.append(phoneState + "\n");
bw.close();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
Toast.makeText(getApplicationContext(), "stopped recording", Toast.LENGTH_LONG).show();
tm.listen(MyServiceListener, PhoneStateListener.LISTEN_NONE);
//wl.release();
stopForeground(true);
来自服务的代码-
i = new Intent(this, WriteToFileService.class);
startService(i);
private PhoneStateListener MyServiceListener;
private TelephonyManager tm;
private int lac ,cellId, signal;
private String phoneState;
private File outFile;
private final static int myID = 10;
//PowerManager.WakeLock wl;
@Override
public int onStartCommand(Intent senderIntent, int flags, int startId) {
Intent localIntent = new Intent(this, MainActivity.class);
localIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendIntent = PendingIntent.getActivity(this, 0, localIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setTicker("Starting to record data").setContentTitle("NetInfo").setContentText("Recording data").setWhen(System.currentTimeMillis())
.setAutoCancel(false).setOngoing(true).setContentIntent(pendIntent).setSmallIcon(R.drawable.hexagon); //.setPriority(Notification.PRIORITY_HIGH)
Notification notification = builder.build();
notification.flags |= Notification.FLAG_NO_CLEAR;
startForeground(myID, notification);
//PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
//wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
//wl.acquire();
outFile = new File(getApplicationContext().getFilesDir(), senderIntent.getStringExtra("name"));
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
MyServiceListener = new PhoneStateListener() {
@Override
public void onCellLocationChanged(CellLocation location){
super.onCellLocationChanged(location);
if ((tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSDPA) || (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS)) {
GsmCellLocation MyLocation = (GsmCellLocation)tm.getCellLocation();
lac = MyLocation.getLac();
cellId = MyLocation.getCid();
}
if (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_CDMA) {
CdmaCellLocation MyLocation = (CdmaCellLocation)tm.getCellLocation();
lac = 0;
cellId = MyLocation.getBaseStationId();
}
WriteDataToFile(lac, cellId, signal, phoneState);
}
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
signal = 2 * signalStrength.getGsmSignalStrength() - 113;
WriteDataToFile(lac, cellId, signal, phoneState);
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
phoneState = "Idle";
break;
case TelephonyManager.CALL_STATE_RINGING:
phoneState = "Ringing";
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
phoneState = "On-going call";
break;
default:
phoneState = "";
break;
}
WriteDataToFile(lac, cellId, signal, phoneState);
}
};
tm.listen(MyServiceListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_CALL_STATE);
return Service.START_STICKY;
}
private void WriteDataToFile(int lac, int cellId, int signal, String phoneState)
{
try {
FileWriter fw = new FileWriter(outFile.getAbsolutePath(), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.append(new SimpleDateFormat("ddMMyyyy_HHmmss").format(Calendar.getInstance().getTime()) + " ");
bw.append(String.valueOf(lac) + " ");
bw.append(String.valueOf(cellId) + " ");
bw.append(String.valueOf(signal) + " ");
bw.append(phoneState + "\n");
bw.close();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
Toast.makeText(getApplicationContext(), "stopped recording", Toast.LENGTH_LONG).show();
tm.listen(MyServiceListener, PhoneStateListener.LISTEN_NONE);
//wl.release();
stopForeground(true);
当然,OnDestroy()
以stopForeground(true)结尾代码>
在某个阶段,当服务被销毁时,我在文件中添加了一条消息,但它只发生了一次——当我结束服务时,所以我确信它没有被操作系统杀死。
有没有办法用前台服务实现这一点,或者我应该尝试另一种方法
我已经在两种不同的设备上试用过了——LG P500和android 2.2,三星S3 mini和android 4.1。他们两人都有同样的行为
谢谢 您可能需要从
唤醒锁定级别:确保CPU正在运行;屏幕和键盘背光将允许熄灭
如果用户按下电源按钮,则屏幕将关闭,但CPU将保持打开,直到所有部分唤醒锁释放
OnStart命令中的伪代码
startForeground(myID, notification);
...
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOC, "My Tag");
wl.acquire();
return Service.START_STICKY;
在您的服务onDestroy中(或当您完成前台操作时),执行以下操作:
可能发生的情况是设备的CPU也将进入睡眠状态;) 谢谢,我试试看。我只是想,由于设备即使在睡眠时也会监听网络事件,因此我的服务将不断获得更新。不,它仍然会在设备睡眠时停止录制,并在设备醒来时恢复。我只在我的LG上测试过。明天我将在S3 mini上测试它,但我有点怀疑。好吧,在这种情况下,你可能想告诉我们你在做什么/什么/谁,因为我认为问题不在于你的服务本身。@MartinMarconcini这个问题出现在一些设备上,而不是所有设备上。例如,在三星j5 api24中,NeigeOS可以正常工作。但不是在荣誉8-24
中。感谢分享链接,我将对此进行研究。@Mehran请记住,文档中说明了特定的供应商实施(换句话说,每个供应商可能会修改某些行为…)。这是一个坏主意(我责怪谷歌),但请记住这一点。并非所有设备都是平等创建的:/