2013-03-24 113 views
2

我創建了一個應用程序,可以啓動後臺服務。此服務旨在監視手機上使用的應用程序,並將此數據與時間戳和座標一起保存到手機上的SQLite。android後臺服務獲取位置

找到應用程序並用時間戳保存的部分可以正常工作。但與位置的部分可以解決問題。我之前曾與地點聽衆合作過,但經過許多小時和多次嘗試後,我放棄了。 林不知道放置在哪裏我的locationlistener?現在我已經創建了一個新的內部類,但是當我運行它時,我得到一個錯誤,說我需要運行Looper.prepare(),但是有幫助。然後它說每個線程只能創建一個活套。

我現在覺得無論我嘗試別的什麼都是錯的,所以我希望你們中的一些人能幫助我。

package com.dtu.applogger; 

import java.util.Calendar; 
import java.util.Timer; 
import java.util.TimerTask; 

import android.app.Activity; 
import android.app.ActivityManager; 
import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Context; 
import android.content.Intent; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.location.LocationProvider; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.Looper; 
import android.util.Log; 
import android.widget.Toast; 


public class loggerService extends Service{ 
DBAdapter dbadapter; 
public MyLocationListener mMyLocationListener; 
private NotificationManager mNM; 
private int NOTIFICATION = 10002; //Any unique number for this notification 
protected String latitude; 
protected String longitude; 
int counter= 0; 
static final int UPDATE_INTERVAL= 5000; 
private Timer timer= new Timer(); 
public loggerService() { 
    // TODO Auto-generated constructor stub 

} 

@Override 
public IBinder onBind(Intent intent) { 
    // TODO Auto-generated method stub 

    return null; 
} 
private void showNotification() { 
    // In this sample, we'll use the same text for the ticker and the expanded notification 
    CharSequence text = "TITLE"; 

    // Set the icon, scrolling text and timestamp 
    Notification notification = new Notification(R.drawable.call_log, text, System.currentTimeMillis()); 

    // The PendingIntent to launch our activity if the user selects this notification 
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, 
      new Intent(this, MainActivity.class), 0); 

    // Set the info for the views that show in the notification panel. 
    notification.setLatestEventInfo(this, "Service is running", text, contentIntent); 

    // Send the notification. 
    mNM.notify(NOTIFICATION, notification); 
} 
public int onStartCommand(Intent intent, int flags, int startId){ 
    //showNotification(); 
    new DoBackgroundTask().execute(); 
    Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show(); 
    return START_STICKY; 

} 

private class DoBackgroundTask extends AsyncTask{ 
    String oldPackageName = "com.dtu.applogger"; 
    DBAdapter dbadapter = new DBAdapter(loggerService.this); 

    public DoBackgroundTask() { 

    } 
    protected String findApp(){ 
     final LocationManager lm = (LocationManager) loggerService.this.getSystemService(Context.LOCATION_SERVICE); 
     ActivityManager am = (ActivityManager) loggerService.this.getSystemService(Activity.ACTIVITY_SERVICE); 
     String packageName = am.getRunningTasks(1).get(0).topActivity.getPackageName(); 

     if(!packageName.equals(oldPackageName) && !packageName.equals("com.dtu.applogger")){ 
      //save oldPackageName and packageName in DB  
      mMyLocationListener = new MyLocationListener(); 
      lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, mMyLocationListener); 
      String lat = latitude; 
      String lng = longitude; 

      String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime()); 
      String txt = packageName + " : " + mydate; 
      dbadapter.open(); 
      if(packageName.equals("com.android.launcher")){ 
       dbadapter.saveLog(mydate, oldPackageName, lat, lng); 
      }else{ 
       dbadapter.saveLog(mydate, packageName, lat, lng); 
      } 

      dbadapter.close(); 
      oldPackageName = packageName; 
      return txt; 
     } 
     if(packageName.equals(oldPackageName)){ 
      return null; 
     } 
     return null; 
    } 
    @Override 
    protected Object doInBackground(Object... params) { 
     timer.scheduleAtFixedRate(new TimerTask() { 
      public void run() { 
       String txt = findApp(); 
       if(txt != null){ 
        Log.d("APP OPEN", "===== " + txt.toString()); 
       } 
      Log.d("loggerService", String.valueOf(++counter)); 
      } 
      }, 0, UPDATE_INTERVAL); 

     // TODO Auto-generated method stub 
     return null; 
    } 
} 

private class MyLocationListener implements android.location.LocationListener{ 

    @Override 
    public void onLocationChanged(Location location) { 
     int lat = (int) (location.getLatitude()*1E6); 
     int lng = (int) (location.getLongitude()*1E6); 
     latitude = Integer.toString(lat); 
     longitude = Integer.toString(lng); 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onProviderDisabled(String provider) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onProviderEnabled(String provider) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onStatusChanged(String provider, int status, Bundle extras) { 
     // TODO Auto-generated method stub 

    } 

} 

public void onDestroy(){ 
    super.onDestroy(); 
    timer.cancel(); 

    Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show(); 

} 

} 

回答

1

你做的事情太複雜,doInBackground是在一個線程了,所以下面的代碼應該沒問題。

@Override 
protected Object doInBackground(Object... params) 
{ 
      while (!isCancelled()) 
      { 
       String txt = findApp(); 
       if(txt != null) 
       { 
        Log.d("APP OPEN", "===== " + txt.toString()); 
       } 
       Log.d("loggerService", String.valueOf(++counter)); 
       try 
       { 
        Thread.sleep(UPDATE_INTERVAL); 
       } 
       catch (InterruptedException e1) 
       { 

       } 
      } 
    return null; 
} 
+0

THX對於這一點,但不解決我的問題,在這種情況下運行的另一個內部類「MyLocationListener」 – freddy 2013-03-24 22:59:25

+0

相反的AsyncTask的,只要運行整個事情在一個線程。 – 2013-03-25 01:35:29

0

我已經用工具LocationListener的關於「DoOnBackgroundTasK」現在解決了它,並刪除了其他內部類MyLocationListener。雖然我已經嘗試過,但現在它起作用了。儘管只使用NETWORK_PROVIDER,但如果使用PASSIVE_PROVIDER,我會得到一個RuntimeException。這是什麼解釋?

我已經將代碼粘貼

public class loggerService extends Service{ 
DBAdapter dbadapter; 

private NotificationManager mNM; 
private int NOTIFICATION = 10002; //Any unique number for this notification 
protected String latitude; 
protected String longitude; 
int counter= 0; 
static final int UPDATE_INTERVAL= 5000; 
private Timer timer= new Timer(); 
public loggerService() { 
    // TODO Auto-generated constructor stub 

} 

@Override 
public IBinder onBind(Intent intent) { 
    // TODO Auto-generated method stub 

    return null; 
} 
private void showNotification() { 
    // In this sample, we'll use the same text for the ticker and the expanded notification 
    CharSequence text = "TITLE"; 

    // Set the icon, scrolling text and timestamp 
    Notification notification = new Notification(R.drawable.call_log, text, System.currentTimeMillis()); 

    // The PendingIntent to launch our activity if the user selects this notification 
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, 
      new Intent(this, MainActivity.class), 0); 

    // Set the info for the views that show in the notification panel. 
    notification.setLatestEventInfo(this, "Service is running", text, contentIntent); 

    // Send the notification. 
    mNM.notify(NOTIFICATION, notification); 
} 
public int onStartCommand(Intent intent, int flags, int startId){ 
    //showNotification(); 
    new DoBackgroundTask().execute(); 
    Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show(); 
    return START_STICKY; 

} 

private class DoBackgroundTask extends AsyncTask implements LocationListener{ 
    String oldPackageName = "com.dtu.applogger"; 
    DBAdapter dbadapter = new DBAdapter(loggerService.this); 

    public DoBackgroundTask() { 

    } 
    protected String findApp(){ 

     ActivityManager am = (ActivityManager) loggerService.this.getSystemService(Activity.ACTIVITY_SERVICE); 
     String packageName = am.getRunningTasks(1).get(0).topActivity.getPackageName(); 

     if(!packageName.equals(oldPackageName) && !packageName.equals("com.dtu.applogger")){ 
      //save oldPackageName and packageName in DB  
      String lat = latitude; 
      String lng = longitude; 

      String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime()); 
      String txt = packageName + " : " + mydate; 
      dbadapter.open(); 
      if(packageName.equals("com.android.launcher")){ 
       dbadapter.saveLog(mydate, oldPackageName, lat, lng); 
       Log.d("LATITUDE ", lat.toString()); 
       Log.d("LONGITUDE ", lng.toString()); 
      }else{ 
       dbadapter.saveLog(mydate, packageName, lat, lng); 
      } 

      dbadapter.close(); 
      oldPackageName = packageName; 
      return txt; 
     } 
     if(packageName.equals(oldPackageName) || packageName.equals("com.dtu.applogger")){ 
      return null; 
     } 
     return null; 
    } 
    protected void onPreExecute() 
    { 
     final LocationManager lm = (LocationManager) loggerService.this.getSystemService(Context.LOCATION_SERVICE); 

// 
//REQUEST LOCATION UPDATE WORKS WITH NETWORK BUT NOT WITH PASSIVE??? 
// 

     lm.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, this); 
    } 
    @Override 
    protected Object doInBackground(Object... params) { 
     while (!isCancelled()){ 
       String txt = findApp(); 
       if(txt != null){ 
        Log.d("APP OPEN", "===== " + txt.toString()); 
       } 
      Log.d("loggerService", String.valueOf(++counter)); 
      try 
      { 
       Thread.sleep(UPDATE_INTERVAL); 
      } 
      catch (InterruptedException e1){ 
      } 
     } 

     // TODO Auto-generated method stub 
     return null; 
    } 
    @Override 
    public void onLocationChanged(Location location) { 

     latitude = String.valueOf(location.getLatitude()); 
     longitude = String.valueOf(location.getLongitude()); 

    } 
    @Override 
    public void onProviderDisabled(String provider) { 
     // TODO Auto-generated method stub 

    } 
    @Override 
    public void onProviderEnabled(String provider) { 
     // TODO Auto-generated method stub 

    } 
    @Override 
    public void onStatusChanged(String provider, int status, Bundle extras) { 
     // TODO Auto-generated method stub 

    } 
} 


public void onDestroy(){ 
    super.onDestroy(); 
    timer.cancel(); 

    Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show(); 

} 

}