diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d8500d4c6..0a47b33a9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,10 +1,11 @@ + package="nodomain.freeyourgadget.gadgetbridge" > - + + @@ -12,15 +13,16 @@ android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:theme="@style/AppTheme"> + android:theme="@style/AppTheme" > + android:label="@string/app_name" /> + android:label="@string/app_name" > + @@ -28,29 +30,46 @@ + android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" > - + + - + + + + - + - + - + + - + + + + + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java index 81b8c92d4..f1cf57cc7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/BluetoothCommunicationService.java @@ -42,8 +42,8 @@ public class BluetoothCommunicationService extends Service { = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.notification_sms"; public static final String ACTION_NOTIFICATION_EMAIL = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.notification_email"; - public static final String ACTION_INCOMINGCALL - = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.incomingcall"; + public static final String ACTION_CALLSTATE + = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.callstate"; public static final String ACTION_SETTIME = "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.settime"; @@ -58,6 +58,7 @@ public class BluetoothCommunicationService extends Service { PhoneCallReceiver.class, SMSReceiver.class, K9Receiver.class, + NotificationListener.class, }; int newState; @@ -180,11 +181,17 @@ public class BluetoothCommunicationService extends Service { String body = intent.getStringExtra("notification_body"); byte[] msg = PebbleProtocol.encodeEmail(sender, subject, body); mBtSocketIoThread.write(msg); - } else if (intent.getAction().equals(ACTION_INCOMINGCALL)) { - String phoneNumber = intent.getStringExtra("incomingcall_phonenumber"); - byte phoneState = intent.getByteExtra("incomingcall_state", (byte) 0); - String callerName = getContactDisplayNameByNumber(phoneNumber); - byte[] msg = PebbleProtocol.encodeIncomingCall(phoneNumber, callerName, phoneState); + } else if (intent.getAction().equals(ACTION_CALLSTATE)) { + byte phoneState = intent.getByteExtra("call_state", (byte) 0); + String phoneNumber = null; + if (intent.hasExtra("call_phonenumber")) { + phoneNumber = intent.getStringExtra("call_phonenumber"); + } + String callerName = null; + if (phoneNumber != null) { + callerName = getContactDisplayNameByNumber(phoneNumber); + } + byte[] msg = PebbleProtocol.encodePhoneState(phoneNumber, callerName, phoneState); mBtSocketIoThread.write(msg); } else if (intent.getAction().equals(ACTION_SETTIME)) { byte[] msg = PebbleProtocol.encodeSetTime(-1); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java index 2aabf9c32..091de3e50 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java @@ -14,19 +14,13 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; -import android.widget.EditText; public class ControlCenter extends ActionBarActivity { public static final String ACTION_QUIT = "nodomain.freeyourgadget.gadgetbride.controlcenter.action.quit"; - Button sendButton; - Button testNotificationButton; Button startServiceButton; - Button setTimeButton; - EditText editTitle; - EditText editContent; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -44,8 +38,6 @@ public class ControlCenter extends ActionBarActivity { registerReceiver(mReceiver, new IntentFilter(ACTION_QUIT)); - editTitle = (EditText) findViewById(R.id.editTitle); - editContent = (EditText) findViewById(R.id.editContent); startServiceButton = (Button) findViewById(R.id.startServiceButton); startServiceButton.setOnClickListener(new View.OnClickListener() { @Override @@ -55,35 +47,6 @@ public class ControlCenter extends ActionBarActivity { startService(startIntent); } }); - sendButton = (Button) findViewById(R.id.sendButton); - sendButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent startIntent = new Intent(ControlCenter.this, BluetoothCommunicationService.class); - startIntent.setAction(BluetoothCommunicationService.ACTION_NOTIFICATION_GENERIC); - startIntent.putExtra("notification_title", editTitle.getText().toString()); - startIntent.putExtra("notification_body", editContent.getText().toString()); - startService(startIntent); - } - }); - setTimeButton = (Button) findViewById(R.id.setTimeButton); - setTimeButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent startIntent = new Intent(ControlCenter.this, BluetoothCommunicationService.class); - startIntent.setAction(BluetoothCommunicationService.ACTION_SETTIME); - startService(startIntent); - } - }); - - testNotificationButton = (Button) findViewById(R.id.testNotificationButton); - testNotificationButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - testNotification(); - } - }); - /* * Ask for permission to intercept notifications on first run. * TODO: allow re-request in preferences @@ -131,9 +94,15 @@ public class ControlCenter extends ActionBarActivity { //startActivity(intent); return true; } + if (id == R.id.action_debug) { + Intent intent = new Intent(this, DebugActivity.class); + startActivity(intent); + return true; + } return super.onOptionsItemSelected(item); } + @Override protected void onDestroy() { super.onDestroy(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/DebugActivity.java new file mode 100644 index 000000000..9c0b975fa --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/DebugActivity.java @@ -0,0 +1,147 @@ +package nodomain.freeyourgadget.gadgetbridge; + +import android.app.NotificationManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat; +import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +public class DebugActivity extends ActionBarActivity { + Button sendSMSButton; + Button sendEmailButton; + Button incomingCallButton; + Button outgoingCallButton; + Button startCallButton; + Button endCallButton; + Button testNotificationButton; + Button setTimeButton; + EditText editContent; + + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(ControlCenter.ACTION_QUIT)) { + finish(); + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_debug); + + registerReceiver(mReceiver, new IntentFilter(ControlCenter.ACTION_QUIT)); + + editContent = (EditText) findViewById(R.id.editContent); + sendSMSButton = (Button) findViewById(R.id.sendSMSButton); + sendSMSButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent = new Intent(DebugActivity.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_NOTIFICATION_GENERIC); + startIntent.putExtra("notification_title", "Gadgetbridge"); + startIntent.putExtra("notification_body", editContent.getText().toString()); + startService(startIntent); + } + }); + sendEmailButton = (Button) findViewById(R.id.sendEmailButton); + sendEmailButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent = new Intent(DebugActivity.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_NOTIFICATION_EMAIL); + startIntent.putExtra("notification_sender", "Gadgetbridge"); + startIntent.putExtra("notification_subject", "Test"); + startIntent.putExtra("notification_body", editContent.getText().toString()); + startService(startIntent); + } + }); + + incomingCallButton = (Button) findViewById(R.id.incomingCallButton); + incomingCallButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent = new Intent(DebugActivity.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_CALLSTATE); + startIntent.putExtra("call_phonenumber", editContent.getText().toString()); + startIntent.putExtra("call_state", PebbleProtocol.PHONECONTROL_INCOMINGCALL); + startService(startIntent); + } + }); + outgoingCallButton = (Button) findViewById(R.id.outgoingCallButton); + outgoingCallButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent = new Intent(DebugActivity.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_CALLSTATE); + startIntent.putExtra("call_phonenumber", editContent.getText().toString()); + startIntent.putExtra("call_state", PebbleProtocol.PHONECONTROL_OUTGOINGCALL); + startService(startIntent); + } + }); + + startCallButton = (Button) findViewById(R.id.startCallButton); + startCallButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent = new Intent(DebugActivity.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_CALLSTATE); + startIntent.putExtra("call_state", PebbleProtocol.PHONECONTROL_START); + startService(startIntent); + } + }); + endCallButton = (Button) findViewById(R.id.endCallButton); + endCallButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent = new Intent(DebugActivity.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_CALLSTATE); + startIntent.putExtra("call_state", PebbleProtocol.PHONECONTROL_END); + startService(startIntent); + } + }); + + setTimeButton = (Button) findViewById(R.id.setTimeButton); + setTimeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent startIntent = new Intent(DebugActivity.this, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_SETTIME); + startService(startIntent); + } + }); + + testNotificationButton = (Button) findViewById(R.id.testNotificationButton); + testNotificationButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + testNotification(); + } + }); + } + + private void testNotification() { + NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this); + ncomp.setContentTitle("Test Notification"); + ncomp.setContentText("This is a Test Notification from Gadgetbridge"); + ncomp.setTicker("This is a Test Notification from Gadgetbridge"); + ncomp.setSmallIcon(R.drawable.ic_launcher); + ncomp.setAutoCancel(true); + nManager.notify((int) System.currentTimeMillis(), ncomp.build()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(mReceiver); + } + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java index e7adbb4d5..d0206cd39 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PebbleProtocol.java @@ -133,7 +133,7 @@ public class PebbleProtocol { return buf.array(); } - public static byte[] encodeIncomingCall(String number, String name, byte state) { + public static byte[] encodePhoneState(String number, String name, byte state) { String cookie = "000"; // That's a dirty trick to make the cookie part 4 bytes long :P String[] parts = {cookie, number, name}; return encodeMessage(ENDPOINT_PHONECONTROL, state, parts); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PhoneCallReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PhoneCallReceiver.java index 3244e801d..bb6986aa9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PhoneCallReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/PhoneCallReceiver.java @@ -5,26 +5,61 @@ import android.content.Context; import android.content.Intent; import android.telephony.TelephonyManager; + public class PhoneCallReceiver extends BroadcastReceiver { + private static int mLastState = TelephonyManager.CALL_STATE_IDLE; + private static String mSavedNumber; + @Override public void onReceive(Context context, Intent intent) { - String phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); - byte state = 0; - if (phoneState.equals(TelephonyManager.EXTRA_STATE_RINGING)) { - state = PebbleProtocol.PHONECONTROL_INCOMINGCALL; - } else if (phoneState.equals(TelephonyManager.EXTRA_STATE_IDLE) || phoneState.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { - state = PebbleProtocol.PHONECONTROL_END; - } + if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { + mSavedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"); + } else { + String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE); + String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER); + int state = 0; + if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) { + state = TelephonyManager.CALL_STATE_IDLE; + } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { + state = TelephonyManager.CALL_STATE_OFFHOOK; + } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) { + state = TelephonyManager.CALL_STATE_RINGING; + } - if (state != 0) { - String phoneNumber = intent.hasExtra(TelephonyManager.EXTRA_INCOMING_NUMBER) ? intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER) : ""; - Intent startIntent = new Intent(context, BluetoothCommunicationService.class); - startIntent.setAction(BluetoothCommunicationService.ACTION_INCOMINGCALL); - startIntent.putExtra("incomingcall_phonenumber", phoneNumber); - startIntent.putExtra("incomingcall_state", state); - context.startService(startIntent); + onCallStateChanged(context, state, number); } } + public void onCallStateChanged(Context context, int state, String number) { + if (mLastState == state) { + return; + } + + byte pebblePhoneCommand = -1; // TODO: dont assume Pebble here + switch (state) { + case TelephonyManager.CALL_STATE_RINGING: + mSavedNumber = number; + pebblePhoneCommand = PebbleProtocol.PHONECONTROL_INCOMINGCALL; + break; + case TelephonyManager.CALL_STATE_OFFHOOK: + if (mLastState == TelephonyManager.CALL_STATE_RINGING) { + pebblePhoneCommand = PebbleProtocol.PHONECONTROL_START; + } else { + pebblePhoneCommand = PebbleProtocol.PHONECONTROL_OUTGOINGCALL; + } + break; + case TelephonyManager.CALL_STATE_IDLE: + pebblePhoneCommand = PebbleProtocol.PHONECONTROL_END; + break; + } + if (pebblePhoneCommand != -1) { + Intent startIntent = new Intent(context, BluetoothCommunicationService.class); + startIntent.setAction(BluetoothCommunicationService.ACTION_CALLSTATE); + startIntent.putExtra("call_phonenumber", mSavedNumber); + startIntent.putExtra("call_state", pebblePhoneCommand); + context.startService(startIntent); + } + mLastState = state; + } } diff --git a/app/src/main/res/layout/activity_controlcenter.xml b/app/src/main/res/layout/activity_controlcenter.xml index c03600e38..cb4f86891 100644 --- a/app/src/main/res/layout/activity_controlcenter.xml +++ b/app/src/main/res/layout/activity_controlcenter.xml @@ -6,67 +6,13 @@ android:paddingBottom="@dimen/activity_vertical_margin" tools:context="nodomain.freeyourgadget.gadgetbridge.ControlCenter"> - - - - -