I am trying to track phone call states and log. I need phone numbers, name(if it is a saved contact) and time of the call and duration. The problem is that getContentResolver() method cannot be called, its commented in code.
public class PhoneStateBroadcastReciever extends BroadcastReceiver {
Context m_context;
String m_number = null;
String m_startTime = null;
String m_endTime = null;
SharedPreferences m_sharedPrefs;
Editor editor;
static String PREFS_NUMBER;
static String PREFS_START_TIME;
static String PREFS_END_TIME;
#Override
public void onReceive(Context context, Intent intent) {
m_sharedPrefs = m_context.getSharedPreferences("MyPrefs", 0);
editor = m_sharedPrefs.edit();
Bundle bundle = intent.getExtras();
if (bundle == null)
return;
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if ((state != null) &&
(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))) {
Log.i("TAG", "incoming call");
Uri contactUri = intent.getData();
String[] projection = { Phone.DISPLAY_NAME };
//i cannot use getContentResolver()
Cursor cursor = getContentResolver()..query(contactUri, projection, null,
null, null);
int columnName = cursor.getColumnIndex(Phone.DISPLAY_NAME);
String contactName = cursor.getString(columnName);
m_number = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
editor.putString(PREFS_NUMBER, m_number);
editor.commit();
} else if(state == null) {
Log.i("TAG", "outgoing call");
Uri contactUri = intent.getData();
String[] projection = { Phone.DISPLAY_NAME };
//i cannot use getContentResolver()
Cursor cursor = getContentResolver()..query(contactUri, projection, null,
null, null);
int columnName = cursor.getColumnIndex(Phone.DISPLAY_NAME);
String contactName = cursor.getString(columnName);
m_number = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
editor.putString(PREFS_NUMBER, m_number);
editor.commit();
} else if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
Log.i("TAG", "off hook");
Time dtstart = new Time(Time.getCurrentTimezone());
dtstart.setToNow();
m_startTime = dtstart.format("%k:%M:%S");
editor.putString(PREFS_START_TIME, m_startTime);
editor.commit();
} else if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)) {
Log.i("TAG", "on idle");
Time dtend = new Time(Time.getCurrentTimezone());
dtend.setToNow();
m_endTime = dtend.format("%k:%M:%S");
editor.putString(PREFS_END_TIME, m_endTime);
editor.commit();
}
}
this is the service class:
public class TrackerService extends Service {
PhoneStateBroadcastReciever receiver;
#Override
public void onCreate() {
receiver = new PhoneStateBroadcastReciever();
IntentFilter filter = new IntentFilter();
filter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
registerReceiver(receiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "starting service", Toast.LENGTH_SHORT).show();
return Service.START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
Use the Context to invoke the contentResolver(). Something like that:
context.getContentResolver()....
Related
I have some activities that call a Service that uses a custom ContentProvider to insert/update/delete entries in a table. Now all these operations work but the activities do not receive any result from them. What I want now is to also implement the query operation but in this case I want the results to get back to the caller Activity. How do I do that?
The ContentProvider itself works as I was using it synchronously, so its code doesn't matter.
Here's the Service:
public class TaskService extends IntentService {
private static final String TAG = TaskService.class.getSimpleName();
//Intent actions
public static final String ACTION_INSERT = TAG + ".INSERT";
public static final String ACTION_UPDATE = TAG + ".UPDATE";
public static final String ACTION_DELETE = TAG + ".DELETE";
public static final String ACTION_QUERY = TAG + ".QUERY";
public static final String EXTRA_VALUES = TAG + ".ContentValues";
public static void queryTasks(Context context, ContentValues values) {
Intent intent = new Intent(context, TaskService.class);
intent.setAction(ACTION_QUERY);
intent.putExtra(EXTRA_VALUES, values);
context.startService(intent);
}
public static void insertNewTask(Context context, ContentValues values) {
Intent intent = new Intent(context, TaskService.class);
intent.setAction(ACTION_INSERT);
intent.putExtra(EXTRA_VALUES, values);
context.startService(intent);
}
public static void updateTask(Context context, Uri uri, ContentValues values) {
Intent intent = new Intent(context, TaskService.class);
intent.setAction(ACTION_UPDATE);
intent.setData(uri);
intent.putExtra(EXTRA_VALUES, values);
context.startService(intent);
}
public static void deleteTask(Context context, Uri uri) {
Intent intent = new Intent(context, TaskService.class);
intent.setAction(ACTION_DELETE);
intent.setData(uri);
context.startService(intent);
}
public TaskService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
if (ACTION_INSERT.equals(intent.getAction())) {
ContentValues values = intent.getParcelableExtra(EXTRA_VALUES);
performInsert(values);
} else if (ACTION_UPDATE.equals(intent.getAction())) {
ContentValues values = intent.getParcelableExtra(EXTRA_VALUES);
performUpdate(intent.getData(), values);
} else if (ACTION_DELETE.equals(intent.getAction())) {
performDelete(intent.getData());
} else if (ACTION_QUERY.equals(intent.getAction())) {
performQuery(intent.getData());
}
}
private void performInsert(ContentValues values) {
if (getContentResolver().insert(DatabaseContract.CONTENT_URI, values) != null) {
Log.d(TAG, "Inserted new task");
} else {
Log.w(TAG, "Error inserting new task");
}
}
private void performQuery(Uri uri, ContentValues values) {
//TODO
}
private void performUpdate(Uri uri, ContentValues values) {
int count = getContentResolver().update(uri, values, null, null);
Log.d(TAG, "Updated " + count + " task items");
}
private void performDelete(Uri uri) {
int count = getContentResolver().delete(uri, null, null);
Log.d(TAG, "Deleted "+count+" tasks");
}
The query() method of course returns a Cursor. How do I send this Cursor back to the Activity?
I have this function which is called when there is any change in Contacts in Phone, Now the problem here is that this code works fine on HTC Desire 620 (KitKat) but crashes on Moto G (Lollipop) and other devices.
Error : java.lang.IllegalStateException: Illegal State: object is no longer valid to operate on. Was it deleted?
Also: It works fine with Moto G2 if contacts are less like < 500 but if more it crashes!
Logcat details:
E/AndroidRuntime: Process: com.advisualinc.echo:SwitchService, PID: 16972
E/AndroidRuntime: java.lang.IllegalStateException: Illegal State: Object is no longer valid to operate on. Was it deleted by another thread?
E/AndroidRuntime: at io.realm.internal.UncheckedRow.nativeGetString(Native Method)
E/AndroidRuntime: at java.lang.Thread.run(Thread.java:818)
My service class:
public class ContactsSyncService extends Service {
public static int count = 0;
int k = 0;
Realm realmFresh;
public static boolean contactUpdated = false;
ContentObserver mObserver;
public Context contextService = ContactsSyncService.this;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mObserver = new ContentObserver(new Handler()) {
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
k++;
// Toast.makeText(ApplicationController.getInstance(), "Starting Change: " , Toast.LENGTH_SHORT).show();
if (!contactUpdated) {
contactUpdated = true;
Logger.debug("Contact Update to start -->");
// Toast.makeText(ApplicationController.getInstance(), "Changing: " , Toast.LENGTH_SHORT).show();
FetchLocalContacts.refreshingContactsDB(contextService);
// Toast.makeText(ApplicationController.getInstance(), "Changed: " , Toast.LENGTH_SHORT).show();
}
}
};
getContentResolver().registerContentObserver(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, true, mObserver);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(mObserver);
}
}
The Function called by Service is refreshingContactsDB():
public static void parseContactstoContactsDB()
{
Thread background = new Thread(new Runnable()
{
public void run()
{
Realm realmFetchFirstTime = Realm.getInstance(ApplicationController.getInstance());
ContentResolver cr = ApplicationController.getInstance()
.getContentResolver();
Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION,null,null, null);
String duplicateName = "";
String duplicatePhone = "";
if( phones.getCount() >0)
{
final int nameIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
final int numberIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
while (phones.moveToNext())
{
String name = phones.getString(nameIndex);
String phoneNo = phones.getString(numberIndex);
if(phoneNo!=null&&!phoneNo.isEmpty())
{
phoneNo = phoneNo.replace(" ", "");
phoneNo = phoneNo.replace("(", "");
phoneNo = phoneNo.replace(")", "");
phoneNo = phoneNo.replace("-", "");
phoneNo = phoneNo.replace("\u00a0", "");
phoneNo = phoneNo.replace("\u202c", "");
phoneNo = phoneNo.replace("\u2011", "");
phoneNo = phoneNo.replace("\u202a", "");
phoneNo = phoneNo.replace("*", "");
phoneNo = phoneNo.replace("#", "");
if (phoneNo.length() >= 5)
{
if(name.equalsIgnoreCase(duplicateName)&&phoneNo.equalsIgnoreCase(duplicatePhone))
{
continue;
}
duplicateName = name;
duplicatePhone = phoneNo;
String formattedPhoneNumber;
formattedPhoneNumber = parseNumber(phoneNo);
realmFetchFirstTime.beginTransaction();
R_LocalContactDB rContacts = realmFetchFirstTime.createObject(R_LocalContactDB.class);
rContacts.setName(name);
rContacts.setPhone(formattedPhoneNumber);
realmFetchFirstTime.commitTransaction();
Logger.debug("Formatted Contacts --> Name: "
+ name
+ " -- Phone No: "
+ formattedPhoneNumber);
}
}
}
phones.close();
}
realmFetchFirstTime.close();
// getNumbersFromDBAndUpdate();
}
});
background.start();
}
public static void getNumbersFromDBAndUpdate()
{
Realm realmServer = Realm.getInstance(ApplicationController.getInstance());
RealmResults<R_LocalContactDB> query = realmServer.where(R_LocalContactDB.class).findAll();
Logger.debug("Contact Update updating to server -->");
for (int i = 0; i < query.size(); i++)
{
phoneNumberJsonArray.put(query.get(i).getPhone());
}
try
{
uploadContactJsonBody.put("phone_numbers", phoneNumberJsonArray);
Logger.debug("LocalContacts RequestJson ---> "
+ uploadContactJsonBody.toString());
AppPreferenceManager.getInstance().setContactPref(1);
UploadLocalContactsToServerAsynTask test = new UploadLocalContactsToServerAsynTask(
uploadContactJsonBody.toString(),
new LocalContactsSyncCallBack()
{
#Override
public void didFinishProfileSync(boolean bool,
String result) {
Logger.debug("Is ContactUpdated FetchContacts --> "
+ bool);
setMatchedStatusToFalse();
AppPreferenceManager.getInstance().setContactUpdate(bool);
Intent roomIntent = new Intent();
roomIntent
.setAction("com.advisualinc.echo.fetch.local_contacts");
ApplicationController.getInstance().sendBroadcast(roomIntent);
}
});
test.execute();
}
catch (JSONException e)
{
e.printStackTrace();
}
realmServer.close();
}
public static void refreshingContactsDB()
{
Thread background = new Thread(new Runnable()
{
public void run()
{
realmFresh = Realm.getInstance(ApplicationController.getInstance());
createCountryDetailsArrayModel();
R_LocalContactDB rCont;
TelephonyManager tm = (TelephonyManager) ApplicationController.getInstance()
.getSystemService(Context.TELEPHONY_SERVICE);
String simCountryISO = tm.getSimCountryIso();
for (int i = 0; i < countryDetailsList.size(); i++)
{
if (simCountryISO.equalsIgnoreCase(countryDetailsList.get(i)
.getCode()))
{
dialCodePrefix = countryDetailsList.get(i).getDial_code();
}
}
AppPreferenceManager.getInstance().setContactUpdate(false);
Logger.debug("Contact Update Refreshing Contact Started -->");
ContentResolver cr = ApplicationController.getInstance()
.getContentResolver();
Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
String duplicateName = "";
String duplicatePhone = "";
if (phones.getCount() > 0)
{
final int nameIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
final int numberIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
while (phones.moveToNext())
{
String name = phones.getString(nameIndex);
String phoneNo = phones.getString(numberIndex);
if (phoneNo != null && !phoneNo.isEmpty())
{
phoneNo = phoneNo.replace(" ", "");
phoneNo = phoneNo.replace("(", "");
phoneNo = phoneNo.replace(")", "");
phoneNo = phoneNo.replace("-", "");
phoneNo = phoneNo.replace("\u00a0", "");
phoneNo = phoneNo.replace("\u202c", "");
phoneNo = phoneNo.replace("\u2011", "");
phoneNo = phoneNo.replace("\u202a", "");
phoneNo = phoneNo.replace("*", "");
phoneNo = phoneNo.replace("#", "");
if (phoneNo.length() >= 5)
{
if (name.equalsIgnoreCase(duplicateName) && phoneNo.equalsIgnoreCase(duplicatePhone)) {
continue;
}
duplicateName = name;
duplicatePhone = phoneNo;
String formattedPhoneNumber;
formattedPhoneNumber = parseNumber(phoneNo);
R_LocalContactDB realmResults = realmFresh.where(R_LocalContactDB.class).equalTo("phone", formattedPhoneNumber).findFirst();
Logger.debug("Size: " + realmResults);
R_LocalContactDB rContacts = new R_LocalContactDB(null, null, false, 0);
if (realmResults == null)
{
i++;
realmFresh.beginTransaction();
rCont = realmFresh.copyToRealm(rContacts);
rCont.setName(name);
rCont.setPhone(formattedPhoneNumber);
rCont.setStatus(0);
rCont.setMatchedWithRecent(true);
// Logger.debug("New Size: " + query.size());
realmFresh.commitTransaction();
}
else if( realmResults.isValid())
{
realmFresh.beginTransaction();
if (!name.equalsIgnoreCase(realmResults.getName()))
{
realmResults.setName(name);
}
realmResults.setMatchedWithRecent(true);
// Logger.debug("New Size Else Condition: " + query.size());
realmFresh.commitTransaction();
}
}
}
}
ContactsSyncService.contactUpdated = false;
}
realmFresh.close();
deleteExtraContacts();
getNumbersFromDBAndUpdate();
}
});
background.start();
}
I count the number of missed calls in the log when state is in the Rigging state. Then Count the number of miss call of the Ideal state. Then compare them. But in the ideal state call log is give the same number of miss call. Can some one help me to validate a to recieved call is a miss call or a not.
public class CustomPhoneStateListener extends PhoneStateListener {
Context context;
String callState;
private static boolean wasRiging;
private static int previousNoOfMissCall;
private static int UDF;
public CustomPhoneStateListener(Context context) {
super();
this.context = context;
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
callState = "IDEAL";
if (UDF != TelephonyManager.CALL_STATE_IDLE) {
sendSMSToMissNo(incomingNumber, "Test");
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
callState = "OFFHOOK";
break;
case TelephonyManager.CALL_STATE_RINGING:
callState = "RIGING";
previousNoOfMissCall = this.getMisscallCount();
wasRiging = true;
break;
default:
break;
}
UDF = state;
Log.i(">>>Broadcast", "onCallStateChanged " + callState);
}
public int getMisscallCount() {
String[] projection = { CallLog.Calls.CACHED_NAME,
CallLog.Calls.CACHED_NUMBER_LABEL, CallLog.Calls.TYPE };
String where = CallLog.Calls.TYPE + "=" + CallLog.Calls.MISSED_TYPE;
Cursor c = context.getContentResolver().query(
CallLog.Calls.CONTENT_URI, projection, where, null, null);
c.moveToFirst();
Log.d("CALL", "" + c.getCount()); // do some other operation
return c.getCount();
}
private void sendSMSToMissNo(String phoneNumber, String message) {
if (this.validateMissCall(previousNoOfMissCall)) {
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, null, null);
}
}
private boolean validateMissCall(int preNoOfMissCall) {
int crtNoOfMissCall = this.getMisscallCount();
Log.d("CALL", "" + "In validate"+crtNoOfMissCall);
if (preNoOfMissCall == crtNoOfMissCall) {
return false;
}
return true;
}
}
public class PhoneStateBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(new CustomPhoneStateListener(context), PhoneStateListener.LISTEN_CALL_STATE);
}
}
I want perform a easy task in android, which when receiving a call the phonenumber will be matched to a number in my database. However I already read that sqlite and BroadcastReceiver are not that easy to combine. Below is the code:
public class incomingcall extends BroadcastReceiver{
String caller;
Cursor c;
#Override
public void onReceive(Context context, Intent intent) {
sqlitedatabase search = new sqlitedatabase(context);
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
Log.i("IncomingCallReceiver",bundle.toString());
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
Log.i("IncomingCallReceiver","State: "+ state);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))
{
String phonenumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.i("IncomingCallReceiver","Incomng Number: " + phonenumber);
try{
search.open();
c = search.callinfo(phonenumber);
if(c != null){
int iFN = c.getColumnIndex("firstname");
int iLN = c.getColumnIndex("lastname");
String FN = c.getString(iFN);
String LN = c.getString(iLN);
caller = FN + " " + LN;
}
else{
caller = "Unknown";
}
search.close();
}
catch (Exception e){
Toast.makeText(context, "error"+e.toString(), Toast.LENGTH_LONG).show();
}
Toast.makeText(context, caller, Toast.LENGTH_LONG).show();
}
}
}
I don't think the problem lies with the methode ".callinfo()", nonetheless I posted it below:
public Cursor callinfo(String l) {
// TODO Auto-generated method stub
String[] columns = new String[]{"phonenumber", "homenumber"};
Cursor c = db.query("mycontacts", columns, "phonenumber = " + l + " OR " + "homenumber = " + l, null, null, null, null);
return c;
}
The Catch returns : errorandroid.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1.
Thank you in advance for any help you can give me.
Cheers
Because the initial cursor position is -1, try to use if(c.moveToNext()) instead of if(c != null).
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));
}
}
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.
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
android.permission.READ_PHONE_STATE
permission. which isn't a big affair.
The code for the broadcast receiver is
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
}
}
}
}
You have to define that receiver
<receiver
android:name=".core.watcher.CallStateWatcher">
<intent-filter>
<action
android:name="android.intent.action.PHONE_STATE"></action>
</intent-filter>
</receiver>