嘿,我正在尝试在我的Android应用程序上实现一项服务。服务必须执行活动的相同任务。 IE,如果在CallLog.Calls内容提供程序上发生某些更改,则必须通知服务并将数据插入数据库,即使应用程序未运行,我的意思是,服务将在应用程序启动后运行,因此如果应用程序被终止,服务将继续运行,直到操作系统停止它,对吧?
因此它将在后台运行,收集CallLog.Calls服务上所有更改的数据。但是,该服务没有运行。我在Activity的onCreate()方法中加注它。在Service中,我实现了一个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));
}
}
答案 0 :(得分:19)
看看您是否在清单文件中添加了此服务.......
感谢.......
答案 1 :(得分:5)
在清单中声明服务时,请尝试在清单中使用服务类的完整包位置。
例如。 <service android:name="com.company.project.package.MyService">
我的服务没有启动,这对我有用。
答案 2 :(得分:1)
您可能需要查看service lifecycle文档。如果你调用Context.startService(),服务应该启动并保持运行,直到有人告诉它停止。
从您的代码示例中,看起来您正在这样做。是什么让你认为服务没有启动?
我不确定当你杀了应用程序时你会发生什么......这听起来是一个不能工作的好理由。
答案 3 :(得分: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>