Android 应用程序无法启动服务
嘿,我正在尝试在我的 Android 应用程序上实现一项服务。而Service必须完成与Activity相同的任务。 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));
}
}
Hey, I'm trying to implement a service on my Android Application. And the Service must do the same task of the Activity. IE, if some change happen on the CallLog.Calls content provider the service must be notified and insert the data in the database even if the application is not running, I mean, a service will be running after the application is started, so if the application is killed, the service will keep running until the OS stop it, right?
So it will be running on background collecting all data that changes on the CallLog.Calls service. But, the service is not running. I star it in onCreate() method of the Activity. And inside the Service I implemented a ContentObserver class that uses the method onChange() in case somethind changes in the CallLog.Calls content provider.
What I don't know is why the Service is not started, and why it doesn't work even if I kill the app on the DDMS perspective.
Here is the code.
The Activity called 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));
}
And this is the Service called 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));
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
只需查看您是否已在清单文件中添加此服务......
谢谢......
Just see if you have added this Service in your manifest file.......
Thanks.......
在清单中声明服务时,请尝试使用清单中服务类的完整包位置。
例如。
我的服务没有启动,但这对我有用。
When declaring the service in your manifest, try using the full package location of your service class in your manifest.
eg.
<service android:name="com.company.project.package.MyService">
My service wasn't starting and that worked for me.
您可能需要查看服务生命周期文档。如果您调用 Context.startService(),服务应该启动并保持运行,直到有人告诉它停止。
从您的代码示例来看,您似乎正在这样做。是什么让您认为该服务未启动?
我不确定当你杀死该应用程序时你期望发生什么......这听起来像是它不起作用的一个很好的理由。
You might want to check out the service lifecycle documentation. If you call Context.startService() the service should start and stay running until someone tells it to stop.
From your code sample, it looks like you are doing that. What makes you think that the service isn't starting?
I'm not sure what you expect to happen when you kill the app... That sounds like a good reason for it not to work.
您好,我不使用服务和内容观察器,而是观察手机状态。观察手机状态可以触发您的更新服务。
你需要
权限。这不是什么大事。
广播接收器的代码是
您必须定义该接收器
Hi instead of using a service and a content observer i would observe the phone state. Observing the phone state can trigger your update service.
You need the
permission. which isn't a big affair.
The code for the broadcast receiver is
You have to define that receiver