My App Drive Safe can be found here. Drive Safe is a free app to prevent distracted driving. It automatically replies to anyone who calls or texts you while the app is on.
I have 2 test phones and it works perfect on them, and have tested it on friends phones, up to nearly 20 at this stage and it works perfect on them too, But I am getting emails from some people from around the world telling me that Drive Safe doesn't work for them. Either doesn't work at all and only puts the phone on silent, or for other replies to calls but not texts and for others vice versa. I have changed several bits of code which I thought might of been the problem area, but am still getting emails from new people saying they are having problems.
I am not sure the percentage of how many people the app works for, i.e 10% , %50, %80 or %90. I can see that I have had nearly 1000 sessions in the last week and 762 users where Returning users.
My App primarily works in the background, and uses a service. Also a broadcast receiver to listen for texts and calls.
Here's some of my code: Code for the button, that is used to turn the app or off.
// listen for clicks on the main button
buttonToggleDetect.setOnClickListener(new View.OnClickListener() {
@Override
// when the main button is clicked
public void onClick(View v) {
setDetectEnabled(!detectEnabled);
mTracker.send(new HitBuilders.EventBuilder()
.setCategory("Home")
.setAction("Share")
.build());
if (detectEnabled) {
showStatusBarIcon(true);
} else
showStatusBarIcon(false);
}
});
Code used to turn on off service when the main button is pressed
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setDetectEnabled(boolean enable) {
detectEnabled = enable;
Intent intent = new Intent(this, CallDetectService.class); //creating a new intent to be sent to CallDetectService class
SharedPreferences sharedPreferences = getSharedPreferences("driveSafeMode", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("mode", enable);
editor.apply();
if (enable) {
startService(intent);
setRingerSilent();
} else {
// stop detect service
stopService(intent);
setRingerNormal();
}
toggleUI();
}
Call Helper class which looks after calls that are received and sends a text back to the incoming number.`
private String phoneNumber ="0";
private int count=0;
private Boolean messageSent = false;
private final BroadcastReceiver mybroadcast = new IncomingSms();
public CallHelper() {}
// Listener to detect incoming calls.
public class CallStateListener extends PhoneStateListener{
@Override
public void onCallStateChanged (int state, String incomingNumber) {
switch (state){
case TelephonyManager.CALL_STATE_RINGING:
// case when someone is calling the users phone
//Creating a object of the AudioManager Class
AudioManager audioManager = (AudioManager) ctx.getSystemService(Activity.AUDIO_SERVICE);
// Emergency mode code is below till 2nd else statement
// Emergency mode is when a person calls 3 times in a row, on the third time
// the app will be switched off and the phone will ring aloud.
// if the saved variable phoneNumber is == to the current incoming number trigger if
if (phoneNumber.equalsIgnoreCase(incomingNumber)) {
count++;
if (count >=2){
// stop app
ctx.stopService(new Intent(ctx, CallDetectService.class));
stop();
Toast.makeText(ctx, R.string.emergencyModeString, Toast.LENGTH_LONG).show();
phoneNumber = "0";
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
count = 0;
} else {
// this is to prevent the Drive Safe Message being sent muliple times in receipt of one text/call
// Drive safe Message should only be sent once per message or call
if (!messageSent) {
SendMessage();
messageSent = true;
}
}
} else {
phoneNumber = incomingNumber.toString();
if (!messageSent) {
SendMessage();
messageSent = true;
// if the phone is not == to previous incoming call and
// the Drive Safe Message has not already been sent, send it.
}
}
break;
// whent the phone is not ringing and in a idle state set messageSent = to false
case TelephonyManager.CALL_STATE_IDLE:
messageSent = false;
}
}
}
private Context ctx;
private TelephonyManager tm;
private CallStateListener callStateListener;
// Constructor
public CallHelper(Context ctx){
this.ctx = ctx;
tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
callStateListener = new CallStateListener();
}
//Method
public void SendMessage(){
String sms = MainActivity.driveSafeSms;
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNumber, null, sms, null, null);
Toast.makeText(ctx, R.string.receivedCall, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(ctx, R.string.smsFailed, Toast.LENGTH_LONG).show();
}
}
// Start Call Detection.
public void start() {
tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
// Stop Call Dectection
public void stop() {
tm.listen(callStateListener, PhoneStateListener.LISTEN_NONE);
}
} `
CallDetectService this is the service class
// create instance of CallHelper class
private CallHelper callHelper;
private final BroadcastReceiver mybroadcast = new IncomingSms();
IntentFilter filter = new IntentFilter();
private Boolean listeningSms = false;
public CallDetectService() {}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
//Register Broadcast Reciever
//if the sms BroadcastReceiver has not already been registered register it
if (!listeningSms) {
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mybroadcast, filter);
listeningSms = true;
}
callHelper = new CallHelper(this);
int res = super.onStartCommand(intent, flags, startId);
callHelper.start();
return res;
}
@Override
public void onDestroy(){
super.onDestroy();
callHelper.stop();
// if the sms broadcast reciever has been registered, unregister it
if (listeningSms == true) {
unregisterReceiver(mybroadcast);
listeningSms = false;
}
Toast.makeText(getApplicationContext(), R.string.inActive, Toast.LENGTH_SHORT).show();
}
@Override
public IBinder onBind (Intent intent) {
return null;
}
}
I'm sorry to be putting in so much code. but I really cant figure where I'm going wrong especially the fact that I cant not replicate the bugs myself, in order to fix them. all I'm looking for is just a pointer and some advice.