停止运行的前台服务

时间:2014-03-16 18:02:56

标签: android android-service

我的应用程序出现问题我正在写作。应用程序应记录网络的数据 - lac,cell Id和接收功率到文件中,只要其中一个发生变化。要在应用程序未对焦或设备休眠时继续录制,我使用了foregound服务。屏幕一旦关闭,我的服务就会停止录制。屏幕开启时,录制将恢复。

这是我的代码: 用于呼叫服务 -

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);结尾 在服务被销毁时,我在某个阶段向文件添加了一条消息,但它只发生了一次 - 当我结束服务时,所以我确信它没有被操作系统杀死。 有没有办法用前台服务来实现这个,或者我应该尝试不同的方法吗?

我已经在两个不同的设备上试过了 - 带有Android 2.2的LG P500和带有android 4.1的三星S3 mini。他们两个都有相同的行为。

谢谢!

1 个答案:

答案 0 :(得分:1)

您可能需要从PowerManager

获取PARTIAL_WAKE_LOC
  

唤醒锁定级别:确保CPU正在运行;屏幕和键盘背光将被允许熄灭。

     

如果用户按下电源按钮,屏幕将关闭,但CPU将保持打开状态,直到所有部分唤醒锁定都被释放。

onStartCommand中的PseudoCode ......

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中(或当你完成前景时)做一个:

 wl.release();

可能发生的事情是设备的CPU也会睡觉;)