2010-12-23 84 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">

我的服务没有启动,并为我工作。