2010-12-23 85 views
2

嘿,我試圖在我的Android應用程序上實現一項服務。服務必須完成活動的相同任務。 IE,如果CallLog.Calls內容提供者發生了一些變化,那麼即使應用程序沒有運行,也必須通知服務並將數據插入數據庫中,也就是說,應用程序啓動後服務將運行,因此如果應用程序被終止,服務將繼續運行,直到操作系統停止它,對吧?Android應用程序無法啓動服務

因此,它將在後臺運行,收集所有在CallLog.Calls服務中更改的數據。但是,該服務沒有運行。我將它放在Activity的onCreate()方法中。在服務內部,我實現了一個ContentObserver類,該類使用onChange()方法來防止CallLog.Calls內容提供者發生某些變化。

我不知道服務未啓動的原因,以及爲什麼即使我在DDMS視角中殺死應用程序也無法正常工作。

這是代碼。

的活動稱爲RatedCalls.java

public class RatedCalls extends ListActivity { 

private static final String LOG_TAG = "RATEDCALLSOBSERVER"; 
private Handler handler = new Handler(); 
private SQLiteDatabase db; 
private CallDataHelper cdh; 
StringBuilder sb = new StringBuilder(); 
OpenHelper openHelper = new OpenHelper(RatedCalls.this); 
private Integer contentProviderLastSize; 
private Integer contentProviderCurrentSize; 

@Override 
public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

    cdh = new CallDataHelper(this); 
    db = openHelper.getWritableDatabase(); 

    startService(new Intent(this, RatedCallsService.class)); 
    registerContentObservers(); 

    Log.i("FILLLIST", "calling from onCreate()"); 

    Cursor cursor = getContentResolver().query(
      android.provider.CallLog.Calls.CONTENT_URI, null, null, null, 
      android.provider.CallLog.Calls.DATE + " DESC "); 

    contentProviderLastSize = cursor.getCount(); 

} 

class RatedCallsContentObserver extends ContentObserver { 
    public RatedCallsContentObserver(Handler h) { 
     super(h); 
    } 

    @Override 
    public boolean deliverSelfNotifications() { 
     return true; 

    } 

    @Override 
    public void onChange(boolean selfChange) { 
     Log.d(LOG_TAG, "RatedCallsContentObserver.onChange(" + selfChange 
       + ")"); 
     super.onChange(selfChange); 
     searchInsert(); 

    } 
} 

private void searchInsert() { 

    Cursor cursor = getContentResolver().query(
      android.provider.CallLog.Calls.CONTENT_URI, null, null, null, 
      android.provider.CallLog.Calls.DATE + " DESC "); 

    Log.i("FILLLIST", "Calling from searchInsert"); 

    startManagingCursor(cursor); 
    int numberColumnId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.NUMBER); 
    int durationId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.DURATION); 
    int contactNameId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME); 
    int numTypeId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.CACHED_NUMBER_TYPE); 

    Date dt = new Date(); 
    int hours = dt.getHours(); 
    int minutes = dt.getMinutes(); 
    int seconds = dt.getSeconds(); 
    String currTime = hours + ":" + minutes + ":" + seconds; 

    SimpleDateFormat dateFormat = new SimpleDateFormat("M/dd/yyyy"); 
    Date date = new Date(); 

    cursor.moveToFirst();   

      String contactNumber = cursor.getString(numberColumnId); 
      String contactName = cursor.getString(contactNameId); 
      String duration = cursor.getString(durationId); 
      String numType = cursor.getString(numTypeId); 
      stopManagingCursor(cursor); 
      ContentValues values = new ContentValues(); 

      values.put("contact_id", 1); 
      values.put("contact_name", contactName); 
      values.put("number_type", numType); 
      values.put("contact_number", contactNumber); 
      values.put("duration", duration); 
      values.put("date", dateFormat.format(date)); 
      values.put("current_time", currTime); 
      values.put("cont", 1); 

      db.insert(CallDataHelper.TABLE_NAME, null, values);   
} 
    public void registerContentObservers() { 

    this.getApplicationContext() 
      .getContentResolver() 
      .registerContentObserver(
        android.provider.CallLog.Calls.CONTENT_URI, true, 
        new RatedCallsContentObserver(handler)); 

} 

而且這是服務稱爲RatedCallsService.java

public class RatedCallsService extends Service { 

private static final String TAG = "RatedCallsService"; 
private static final String LOG_TAG = "RatedCallsService"; 
private Handler handler = new Handler(); 
private SQLiteDatabase db; 
private CallDataHelper cdh; 
OpenHelper openHelper = new OpenHelper(RatedCallsService.this); 

class RatedCallsContentObserver extends ContentObserver { 
    public RatedCallsContentObserver(Handler h) { 
     super(h); 
    } 

    @Override 
    public boolean deliverSelfNotifications() { 
     return true; 

    } 

    @Override 
    public void onChange(boolean selfChange) { 
     Log.d(LOG_TAG, "RatedCallsContentObserver.onChange(" + selfChange 
       + ")"); 
     super.onChange(selfChange); 
     searchInsert(); 

    } 
} 

@Override 
public IBinder onBind(Intent arg0) { 
    // TODO Auto-generated method stub 
    return null; 
} 

@Override 
public void onCreate() { 

    Toast.makeText(this, "Rated Calls Service Created", Toast.LENGTH_LONG).show(); 
    Log.i(TAG, "onCreate"); 
    registerContentObservers(); 

} 

@Override 
public void onDestroy() { 

    Toast.makeText(this, "Rated Calls Service Stopped", Toast.LENGTH_LONG).show(); 
    Log.i(TAG, "onDestroy"); 
    cdh = new CallDataHelper(this); 
    db = openHelper.getWritableDatabase(); 

} 

@Override 
public void onStart(Intent intent, int startid) { 

    Toast.makeText(this, "Rated Calls Service Started", Toast.LENGTH_LONG).show(); 
    Log.d(TAG, "onStart");  
    registerContentObservers(); 

} 

private void searchInsert() { 

    Cursor cursor = getContentResolver().query(
      android.provider.CallLog.Calls.CONTENT_URI, null, null, null, 
      android.provider.CallLog.Calls.DATE + " DESC "); 

    Log.i("FILLLIST", "Calling from searchInsert"); 

    int numberColumnId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.NUMBER); 
    int durationId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.DURATION); 
    int contactNameId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME); 
    int numTypeId = cursor 
      .getColumnIndex(android.provider.CallLog.Calls.CACHED_NUMBER_TYPE); 

    Date dt = new Date(); 
    int hours = dt.getHours(); 
    int minutes = dt.getMinutes(); 
    int seconds = dt.getSeconds(); 
    String currTime = hours + ":" + minutes + ":" + seconds; 

    SimpleDateFormat dateFormat = new SimpleDateFormat("M/dd/yyyy"); 
    Date date = new Date(); 

    if (cursor.moveToFirst()) { 
     do { 

      String contactNumber = cursor.getString(numberColumnId); 
      String contactName = cursor.getString(contactNameId); 
      String duration = cursor.getString(durationId); 
      String numType = cursor.getString(numTypeId);   
      ContentValues values = new ContentValues(); 

      values.put("contact_id", 1); 
      values.put("contact_name", contactName); 
      values.put("number_type", numType); 
      values.put("contact_number", contactNumber); 
      values.put("duration", duration); 
      values.put("date", dateFormat.format(date)); 
      values.put("current_time", currTime); 
      values.put("cont", 1); 

      db.insert(CallDataHelper.TABLE_NAME, null, values); 

     } while (cursor.moveToNext()); 
     cursor.close(); 
    } 
} 


public void registerContentObservers() { 

    this.getApplicationContext() 
      .getContentResolver() 
      .registerContentObserver(
        android.provider.CallLog.Calls.CONTENT_URI, true, 
        new RatedCallsContentObserver(handler)); 

} 

} 

回答

18

只是看你是否已經在你的清單文件中添加了這個服務.......

謝謝.......

1

您可能要檢查出service lifecycle文檔。如果你調用Context.startService(),服務應該啓動並保持運行,直到有人告訴它停止。

從你的代碼示例中,它看起來像你這樣做。是什麼讓你覺得這項服務沒有啓動?

我不確定當你殺死應用程序時你會發生什麼......這聽起來像是它不起作用的一個很好的理由。

1

嗨,而不是使用服務和內容觀察員我會觀察電話狀態。觀察電話狀態可以觸發您的更新服務。

您需要

android.permission.READ_PHONE_STATE

許可。這不是一件大事。

的廣播接收器的代碼是

public class CallStateWatcher extends BroadcastReceiver 
{ 



    @Override 
    public void onReceive(Context context, Intent intent) 
    { 

     if (intent.getAction().equals(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED)) 
     { 
      String extra = intent.getStringExtra(android.telephony.TelephonyManager.EXTRA_STATE); 

      if (extra.equals(android.telephony.TelephonyManager.EXTRA_STATE_OFFHOOK)) 
      { 
       // do something 
      } 
      if (extra.equals(android.telephony.TelephonyManager.EXTRA_STATE_IDLE)) 
      { 
       // do something 

      } 

     } 
    } 
} 

你必須定義接收器

<receiver 
     android:name=".core.watcher.CallStateWatcher"> 
     <intent-filter> 
      <action 
       android:name="android.intent.action.PHONE_STATE"></action> 

     </intent-filter> 
    </receiver> 
5

在清單中聲明服務時,請嘗試使用g清單中服務類的完整包裝位置。

例如。<service android:name="com.company.project.package.MyService">

我的服務沒有啓動,併爲我工作。