我试图跟踪电话状态,并记录电话号码、姓名(如果存在于联系人中)以及开始和结束的日期。我想在后台做,所以我把它写成服务,这是我第一次使用服务,我得到了一个 RuntimeException。我在本地将数据保存在 SharedPreferences 中(将来它将被推送到服务器),并且只想在可能的情况下用 toast 显示它。以下是课程:
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;
public String PREFS_NUMBER;
public String PREFS_START_TIME;
public String PREFS_END_TIME;
public String PREFS__NAME;
@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 };
Cursor cursor = m_context.getContentResolver().query(contactUri,
projection, null, null, null);
int columnName = cursor.getColumnIndex(Phone.DISPLAY_NAME);
String contactName = cursor.getString(columnName);
if(contactName != null) {
editor.putString(PREFS__NAME, contactName);
}
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 };
Cursor cursor = m_context.getContentResolver().query(contactUri,
projection, null, null, null);
int columnName = cursor.getColumnIndex(Phone.DISPLAY_NAME);
String contactName = cursor.getString(columnName);
if(contactName != null) {
editor.putString(PREFS__NAME, contactName);
}
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();
}
}
}
服务:
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();
}
}
活动:
public class TrackerSettingsActivity extends Activity {
public static int TIME_DELAY = 0;
PhoneStateBroadcastReciever prefs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tracker_settings);
EditText timerDelay = (EditText) findViewById(R.id.editText_Set_Timer);
String text = timerDelay.getText().toString();
TIME_DELAY = Integer.valueOf(text);
startService(new Intent(this, TrackerService.class));
updateDataLocally();
}
private void updateDataLocally() {
SharedPreferences m_sharedPrefs = getSharedPreferences("MyPrefs", 0);
String number = m_sharedPrefs.getString(prefs.PREFS_NUMBER, "1");
String startTime = m_sharedPrefs.getString(prefs.PREFS_START_TIME, "2");
String endTime = m_sharedPrefs.getString(prefs.PREFS_END_TIME, "3");
Toast.makeText(getApplicationContext(), number + " " + startTime + " " +
endTime, Toast.LENGTH_LONG).show();
}
}
和 settings.xml:
<TextView
android:id="@+id/textView_Set_Timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tv_settimer"
android:textColor="#ffffff" />
<EditText
android:id="@+id/editText_Set_Timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="@+id/textView_Set_Timer"
android:layout_below="@+id/textView_Set_Timer"
android:ems="10"
android:inputType="number"
android:textColorHint="#ffffff" />
<Button
android:id="@+id/button_Confirm"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/editText_Set_Timer"
android:text="@string/bn_confirm" />
10-29 14:51:14.028: D/libc(14050): pt_debug : __thread_entry->func=0x40a1e065
10-29 14:51:14.028: D/libc(14050): , tls=0x6a5e6f00, arg=0x400b3008
10-29 14:51:14.028: D/libc(14050): pt_debug : pthread_create->start_routine=0x40a1e065,
tls=0x6a6e6f00, arg=0x400b4010
10-29 14:51:14.028: D/libc(14050): pt_debug : __thread_entry->func=0x40a1e065
10-29 14:51:14.028: D/libc(14050): , tls=0x6a6e6f00, arg=0x400b4010
10-29 14:51:14.028: D/libc(14050): pt_debug : pthread_create->start_routine=0x40a1e065,
tls=0x6a7e6f00, arg=0x68e691c8
10-29 14:51:14.028: D/libc(14050): pt_debug : __thread_entry->func=0x40a1e065
10-29 14:51:14.028: D/libc(14050): , tls=0x6a7e6f00, arg=0x68e691c8
10-29 14:51:14.048: D/libc(14050): pt_debug : pthread_create->start_routine=0x4017e509,
tls=0x6aae4f00, arg=0x68e698b0
10-29 14:51:14.048: D/libc(14050): pt_debug : __thread_entry->func=0x4017e509
10-29 14:51:14.048: D/libc(14050): , tls=0x6aae4f00, arg=0x68e698b0
10-29 14:51:14.048: D/libc(14050): pt_debug : pthread_create->start_routine=0x4017e509,
tls=0x6abe4f00, arg=0x688b28e8
10-29 14:51:14.048: D/libc(14050): pt_debug : __thread_entry->func=0x4017e509
10-29 14:51:14.048: D/libc(14050): , tls=0x6abe4f00, arg=0x688b28e8
10-29 14:51:14.078: E/Trace(14050): error opening trace file: No such file or directory
(2)
10-29 14:51:14.088: I/System.out(14050): Sending WAIT chunk
10-29 14:51:14.088: W/ActivityThread(14050): Application hr.hyperactive.tracker is
waiting for the debugger on port 8100...
10-29 14:51:14.289: I/System.out(14050): Debugger has connected
10-29 14:51:14.289: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:14.489: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:14.689: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:14.889: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:15.090: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:15.290: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:15.500: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:15.700: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:15.900: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:16.101: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:16.301: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:16.501: I/System.out(14050): waiting for debugger to settle...
10-29 14:51:16.701: I/System.out(14050): debugger has settled (1457)
10-29 14:51:17.072: D/skia(14050): new locale hr_US
10-29 14:51:22.808: W/jdwp(14050): Debugger is telling the VM to exit with code=1