Merge remote-tracking branch 'origin/master' into low_battery_notification

live-activity-data
Daniele Gobbetti 2015-08-21 17:34:11 +02:00
commit dcc988139f
34 changed files with 458 additions and 382 deletions

View File

@ -1,9 +1,12 @@
###Changelog
####Version (next)
####Version 0.5.0
* Mi Band: fix setting wear location
* Pebble: experimental watchapp installation support for FW 3.x/Pebble Time
* Pebble: support Pebble emulator via TCP connection (needs rebuild with INTERNET permission)
* Pebble: use SMS/EMAIL icons for FW 3.x/Pebble Time
* Support going forward/backwards in time in the activy charts
* Various small bugfixes to the App/Fw Installation Activity
####Version 0.4.6
* Mi Band: Fixed negative number of steps displayed (#91)

View File

@ -12,8 +12,8 @@ android {
applicationId "nodomain.freeyourgadget.gadgetbridge"
minSdkVersion 19
targetSdkVersion 21
versionCode 20
versionName "0.4.6"
versionCode 21
versionName "0.5.0"
}
buildTypes {
release {

View File

@ -19,6 +19,9 @@ import java.util.concurrent.locks.ReentrantLock;
import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
public class GBApplication extends Application {
@ -27,12 +30,18 @@ public class GBApplication extends Application {
private static GBApplication context;
private static ActivityDatabaseHandler mActivityDatabaseHandler;
private static final Lock dbLock = new ReentrantLock();
private static DeviceService deviceService;
public GBApplication() {
context = this;
deviceService = createDeviceService();
// don't do anything here, add it to onCreate instead
}
protected DeviceService createDeviceService() {
return new GBDeviceService(this, DeviceCommunicationService.class);
}
@Override
public void onCreate() {
super.onCreate();
@ -82,6 +91,10 @@ public class GBApplication extends Application {
return context;
}
public static DeviceService deviceService() {
return deviceService;
}
/**
* Returns the DBHandler instance for reading/writing or throws GBException
* when that was not successful

View File

@ -23,9 +23,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAppAdapter;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
@ -93,10 +95,7 @@ public class AppManagerActivity extends Activity {
@Override
public void onItemClick(AdapterView parent, View v, int position, long id) {
UUID uuid = appList.get(position).getUUID();
Intent startAppIntent = new Intent(AppManagerActivity.this, DeviceCommunicationService.class);
startAppIntent.setAction(DeviceCommunicationService.ACTION_STARTAPP);
startAppIntent.putExtra("app_uuid", uuid.toString());
startService(startAppIntent);
GBApplication.deviceService().onAppStart(uuid);
}
});
@ -113,9 +112,7 @@ public class AppManagerActivity extends Activity {
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter);
Intent startIntent = new Intent(this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_REQUEST_APPINFO);
startService(startIntent);
GBApplication.deviceService().onAppInfoReq();
}
@Override
@ -133,10 +130,7 @@ public class AppManagerActivity extends Activity {
switch (item.getItemId()) {
case R.id.appmanager_app_delete:
if (selectedApp != null) {
Intent deleteIntent = new Intent(this, DeviceCommunicationService.class);
deleteIntent.setAction(DeviceCommunicationService.ACTION_DELETEAPP);
deleteIntent.putExtra("app_uuid", selectedApp.getUUID().toString());
startService(deleteIntent);
GBApplication.deviceService().onAppDelete(selectedApp.getUUID());
}
return true;
default:

View File

@ -11,6 +11,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.R;
@ -78,9 +79,6 @@ public class ConfigureAlarms extends ListActivity {
}
private void sendAlarmsToDevice() {
Intent startIntent = new Intent(ConfigureAlarms.this, DeviceCommunicationService.class);
startIntent.putParcelableArrayListExtra("alarms", mGBAlarmListAdapter.getAlarmList());
startIntent.setAction(DeviceCommunicationService.ACTION_SET_ALARMS);
startService(startIntent);
GBApplication.deviceService().onSetAlarms(mGBAlarmListAdapter.getAlarmList());
}
}

View File

@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapter;
@ -112,10 +113,7 @@ public class ControlCenter extends Activity {
startActivity(startIntent);
}
} else {
Intent startIntent = new Intent(ControlCenter.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_CONNECT);
startIntent.putExtra(DeviceCommunicationService.EXTRA_DEVICE_ADDRESS, deviceList.get(position).getAddress());
startService(startIntent);
GBApplication.deviceService().connect(deviceList.get(position).getAddress());
}
}
});
@ -141,33 +139,17 @@ public class ControlCenter extends Activity {
Intent enableIntent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(enableIntent);
}
Intent startIntent = new Intent(this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_START);
startService(startIntent);
GBApplication.deviceService().start();
if (GB.isBluetoothEnabled() && deviceList.isEmpty()) {
// start discovery when no devices are present
startActivity(new Intent(this, DiscoveryActivity.class));
} else {
requestDeviceInfo();
GBApplication.deviceService().requestDeviceInfo();
}
}
/**
* Requests information from the {@link DeviceCommunicationService} about the connection state,
* firmware info, etc.
* <p/>
* Note that this will not need a connection to the device -- only the cached information
* from the service will be reported.
*/
private void requestDeviceInfo() {
Intent versionInfoIntent = new Intent(ControlCenter.this, DeviceCommunicationService.class);
versionInfoIntent.setAction(DeviceCommunicationService.ACTION_REQUEST_DEVICEINFO);
startService(versionInfoIntent);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
@ -209,17 +191,13 @@ public class ControlCenter extends Activity {
return true;
case R.id.controlcenter_fetch_activity_data:
if (selectedDevice != null) {
Intent startIntent = new Intent(this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_FETCH_ACTIVITY_DATA);
startService(startIntent);
GBApplication.deviceService().onFetchActivityData();
}
return true;
case R.id.controlcenter_disconnect:
if (selectedDevice != null) {
selectedDevice = null;
Intent startIntent = new Intent(this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_DISCONNECT);
startService(startIntent);
GBApplication.deviceService().disconnect();
}
return true;
case R.id.controlcenter_find_device:
@ -247,9 +225,7 @@ public class ControlCenter extends Activity {
return true;
case R.id.controlcenter_take_screenshot:
if (selectedDevice != null) {
Intent startIntent = new Intent(this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_REQUEST_SCREENSHOT);
startService(startIntent);
GBApplication.deviceService().onScreenshotReq();
}
return true;
default:
@ -258,10 +234,7 @@ public class ControlCenter extends Activity {
}
private void findDevice(boolean start) {
Intent startIntent = new Intent(this, DeviceCommunicationService.class);
startIntent.putExtra("find_start", start);
startIntent.setAction(DeviceCommunicationService.ACTION_FIND_DEVICE);
startService(startIntent);
GBApplication.deviceService().onFindDevice(start);
}
@Override
@ -284,8 +257,7 @@ public class ControlCenter extends Activity {
startActivity(debugIntent);
return true;
case R.id.action_quit:
Intent stopIntent = new Intent(this, DeviceCommunicationService.class);
stopService(stopIntent);
GBApplication.deviceService().quit();
Intent quitIntent = new Intent(ControlCenter.ACTION_QUIT);
LocalBroadcastManager.getInstance(this).sendBroadcast(quitIntent);

View File

@ -21,14 +21,13 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class DebugActivity extends Activity {
@ -70,23 +69,17 @@ public class DebugActivity extends Activity {
sendSMSButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_NOTIFICATION_SMS);
startIntent.putExtra("notification_sender", getResources().getText(R.string.app_name));
startIntent.putExtra("notification_body", editContent.getText().toString());
startService(startIntent);
GBApplication.deviceService().onSMS(getResources().getText(R.string.app_name).toString(), editContent.getText().toString());
}
});
sendEmailButton = (Button) findViewById(R.id.sendEmailButton);
sendEmailButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_NOTIFICATION_EMAIL);
startIntent.putExtra("notification_sender", getResources().getText(R.string.app_name));
startIntent.putExtra("notification_subject", getResources().getText(R.string.test));
startIntent.putExtra("notification_body", editContent.getText().toString());
startService(startIntent);
GBApplication.deviceService().onEmail(
getResources().getText(R.string.app_name).toString(),
getResources().getText(R.string.test).toString(),
editContent.getText().toString());
}
});
@ -94,22 +87,20 @@ public class DebugActivity extends Activity {
incomingCallButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_CALLSTATE);
startIntent.putExtra("call_phonenumber", editContent.getText().toString());
startIntent.putExtra("call_command", ServiceCommand.CALL_INCOMING.ordinal());
startService(startIntent);
GBApplication.deviceService().onSetCallState(
editContent.getText().toString(),
null,
ServiceCommand.CALL_INCOMING);
}
});
outgoingCallButton = (Button) findViewById(R.id.outgoingCallButton);
outgoingCallButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_CALLSTATE);
startIntent.putExtra("call_phonenumber", editContent.getText().toString());
startIntent.putExtra("call_command", ServiceCommand.CALL_OUTGOING.ordinal());
startService(startIntent);
GBApplication.deviceService().onSetCallState(
editContent.getText().toString(),
null,
ServiceCommand.CALL_OUTGOING);
}
});
@ -117,20 +108,20 @@ public class DebugActivity extends Activity {
startCallButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_CALLSTATE);
startIntent.putExtra("call_command", ServiceCommand.CALL_START.ordinal());
startService(startIntent);
GBApplication.deviceService().onSetCallState(
null,
null,
ServiceCommand.CALL_START);
}
});
endCallButton = (Button) findViewById(R.id.endCallButton);
endCallButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_CALLSTATE);
startIntent.putExtra("call_command", ServiceCommand.CALL_END.ordinal());
startService(startIntent);
GBApplication.deviceService().onSetCallState(
null,
null,
ServiceCommand.CALL_END);
}
});
@ -153,9 +144,7 @@ public class DebugActivity extends Activity {
rebootButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_REBOOT);
startService(startIntent);
GBApplication.deviceService().onReboot();
}
});
@ -163,12 +152,10 @@ public class DebugActivity extends Activity {
setMusicInfoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_SETMUSICINFO);
startIntent.putExtra("music_artist", editContent.getText().toString() + "(artist)");
startIntent.putExtra("music_album", editContent.getText().toString() + "(album)");
startIntent.putExtra("music_track", editContent.getText().toString() + "(track)");
startService(startIntent);
GBApplication.deviceService().onSetMusicInfo(
editContent.getText().toString() + "(artist)",
editContent.getText().toString() + "(album)",
editContent.getText().toString() + "(tracl)");
}
});
@ -176,9 +163,7 @@ public class DebugActivity extends Activity {
setTimeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(DebugActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_SETTIME);
startService(startIntent);
GBApplication.deviceService().onSetTime();
}
});

View File

@ -18,11 +18,11 @@ import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -47,7 +47,7 @@ public class FwAppInstallerActivity extends Activity implements InstallActivity
} else if (action.equals(GBDevice.ACTION_DEVICE_CHANGED)) {
device = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
if (device != null) {
if (!device.isConnected()) {
if (!device.isInitialized()) {
setInstallEnabled(false);
if (mayConnect) {
GB.toast(FwAppInstallerActivity.this, getString(R.string.connecting), Toast.LENGTH_SHORT, GB.INFO);
@ -65,12 +65,7 @@ public class FwAppInstallerActivity extends Activity implements InstallActivity
private void connect() {
mayConnect = false; // only do that once per #onCreate
Intent startIntent = new Intent(FwAppInstallerActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_CONNECT);
if (device != null) {
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
}
startService(startIntent);
GBApplication.deviceService().connect(device != null ? device.getAddress() : null);
}
private void validateInstallation() {
@ -102,10 +97,7 @@ public class FwAppInstallerActivity extends Activity implements InstallActivity
public void onClick(View v) {
setInstallEnabled(false);
installHandler.onStartInstall(device);
Intent startIntent = new Intent(FwAppInstallerActivity.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_INSTALL);
startIntent.putExtra("uri", uri);
startService(startIntent);
GBApplication.deviceService().onInstallApp(uri);
}
});
@ -120,9 +112,7 @@ public class FwAppInstallerActivity extends Activity implements InstallActivity
if (device == null || !device.isConnected()) {
connect();
} else {
Intent deviceInfoIntent = new Intent(this, DeviceCommunicationService.class);
deviceInfoIntent.setAction(DeviceCommunicationService.ACTION_REQUEST_DEVICEINFO);
startService(deviceInfoIntent);
GBApplication.deviceService().requestDeviceInfo();
}
}
}

View File

@ -24,10 +24,10 @@ import org.slf4j.LoggerFactory;
import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
public class ChartsActivity extends FragmentActivity implements ChartsHost {
@ -147,9 +147,7 @@ public class ChartsActivity extends FragmentActivity implements ChartsHost {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.charts_fetch_activity_data:
Intent startIntent = new Intent(this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_FETCH_ACTIVITY_DATA);
startService(startIntent);
GBApplication.deviceService().onFetchActivityData();
return true;
default:
break;

View File

@ -57,7 +57,7 @@ public class GBAlarmListAdapter extends ArrayAdapter<GBAlarm> {
Collections.sort(alarmList);
}
public ArrayList<GBAlarm> getAlarmList() {
public ArrayList<? extends Alarm> getAlarmList() {
return alarmList;
}

View File

@ -1,6 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.devices;
import android.net.Uri;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.UUID;
@ -20,16 +21,14 @@ public interface EventHandler {
void onGenericNotification(String title, String details);
void onSetTime(long ts);
void onSetTime();
void onSetAlarms(ArrayList<Alarm> alarms);
void onSetAlarms(ArrayList<? extends Alarm> alarms);
void onSetCallState(String number, String name, ServiceCommand command);
void onSetCallState(@Nullable String number, @Nullable String name, ServiceCommand command);
void onSetMusicInfo(String artist, String album, String track);
void onBatteryInfoReq();
void onInstallApp(Uri uri);
void onAppInfoReq();
@ -38,8 +37,6 @@ public interface EventHandler {
void onAppDelete(UUID uuid);
void onPhoneVersion(byte os);
void onFetchActivityData();
void onReboot();

View File

@ -120,7 +120,7 @@ public class MiBandCoordinator implements DeviceCoordinator {
public static int getWearLocation(String miBandAddress) throws IllegalArgumentException {
int location = 0; //left hand
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GBApplication.getContext());
if (prefs.getString(MiBandConst.PREF_MIBAND_WEARSIDE, "left") == "right") {
if ("right".equals(prefs.getString(MiBandConst.PREF_MIBAND_WEARSIDE, "left"))) {
location = 1; // right hand
}
return location;

View File

@ -12,6 +12,7 @@ import android.support.v4.content.LocalBroadcastManager;
import android.widget.TextView;
import android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
@ -105,11 +106,7 @@ public class MiBandPairingActivity extends Activity {
IntentFilter filter = new IntentFilter(GBDevice.ACTION_DEVICE_CHANGED);
LocalBroadcastManager.getInstance(this).registerReceiver(mPairingReceiver, filter);
Intent serviceIntent = new Intent(this, DeviceCommunicationService.class);
serviceIntent.setAction(DeviceCommunicationService.ACTION_CONNECT);
serviceIntent.putExtra(DeviceCommunicationService.EXTRA_PERFORM_PAIR, true);
serviceIntent.putExtra(DeviceCommunicationService.EXTRA_DEVICE_ADDRESS, macAddress);
startService(serviceIntent);
GBApplication.deviceService().connect(macAddress, true);
}
private void pairingFinished(boolean pairedSuccessfully) {

View File

@ -17,12 +17,11 @@ import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
public class PBWInstallHandler implements InstallHandler {
private final Context mContext;
private final PBWReader mPBWReader;
private PBWReader mPBWReader;
private final Uri mUri;
public PBWInstallHandler(Uri uri, Context context) {
mContext = context;
mPBWReader = new PBWReader(uri, context, ""); // FIXME: we should know the platform here
mUri = uri;
}
@ -34,6 +33,13 @@ public class PBWInstallHandler implements InstallHandler {
return;
}
mPBWReader = new PBWReader(mUri, mContext, device.getHardwareVersion().equals("dvt") ? "basalt" : "aplite");
if (!mPBWReader.isValid()) {
installActivity.setInfoText("pbw/pbz is broken or incompatible with your Hardware or Firmware.");
installActivity.setInstallEnabled(false);
return;
}
if (mPBWReader.isFirmware()) {
String hwRevision = mPBWReader.getHWRevision();
if (hwRevision != null && hwRevision.equals(device.getHardwareVersion())) {
@ -77,7 +83,8 @@ public class PBWInstallHandler implements InstallHandler {
}
public boolean isValid() {
return mPBWReader.isValid();
// always pretend it is valid, as we cant know yet about hw/fw version
return true;
}
}

View File

@ -147,7 +147,6 @@ public class PBWReader {
if (appName != null && appCreator != null && appVersion != null) {
// FIXME: dont assume WATCHFACE
app = new GBDeviceApp(uuid, appName, appCreator, appVersion, GBDeviceApp.Type.WATCHFACE);
isValid = true;
}
} catch (JSONException e) {

View File

@ -8,6 +8,7 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
@ -27,12 +28,9 @@ public class BluetoothStateChangeReceiver extends BroadcastReceiver {
return;
}
Intent connectIntent = new Intent(context, DeviceCommunicationService.class);
connectIntent.setAction(DeviceCommunicationService.ACTION_CONNECT);
context.startService(connectIntent);
GBApplication.deviceService().connect();
} else if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) {
Intent stopIntent = new Intent(context, DeviceCommunicationService.class);
context.stopService(stopIntent);
GBApplication.deviceService().quit();
Intent quitIntent = new Intent(ControlCenter.ACTION_QUIT);

View File

@ -12,7 +12,7 @@ import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
public class K9Receiver extends BroadcastReceiver {
@ -65,12 +65,6 @@ public class K9Receiver extends BroadcastReceiver {
} while (c.moveToNext());
c.close();
Intent startIntent = new Intent(context, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_NOTIFICATION_EMAIL);
startIntent.putExtra("notification_sender", sender);
startIntent.putExtra("notification_subject", subject);
startIntent.putExtra("notification_body", preview);
context.startService(startIntent);
GBApplication.deviceService().onEmail(sender, subject, preview);
}
}

View File

@ -7,7 +7,7 @@ import android.content.Intent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
public class MusicPlaybackReceiver extends BroadcastReceiver {
private static final Logger LOG = LoggerFactory.getLogger(MusicPlaybackReceiver.class);
@ -20,11 +20,6 @@ public class MusicPlaybackReceiver extends BroadcastReceiver {
LOG.info("Current track: " + artist + ", " + album + ", " + track);
Intent startIntent = new Intent(context, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_SETMUSICINFO);
startIntent.putExtra("music_artist", artist);
startIntent.putExtra("music_album", album);
startIntent.putExtra("music_track", track);
context.startService(startIntent);
GBApplication.deviceService().onSetMusicInfo(artist, album, track);
}
}

View File

@ -17,6 +17,7 @@ import android.support.v4.content.LocalBroadcastManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
public class NotificationListener extends NotificationListenerService {
@ -111,13 +112,8 @@ public class NotificationListener extends NotificationListenerService {
}
if (content != null) {
Intent startIntent = new Intent(NotificationListener.this, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_NOTIFICATION_GENERIC);
startIntent.putExtra("notification_title", title);
startIntent.putExtra("notification_body", content);
startService(startIntent);
GBApplication.deviceService().onGenericNotification(title, content);
}
}
private boolean isServiceRunning() {

View File

@ -12,7 +12,7 @@ import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
public class PebbleReceiver extends BroadcastReceiver {
@ -51,11 +51,7 @@ public class PebbleReceiver extends BroadcastReceiver {
}
if (title != null && body != null) {
Intent startIntent = new Intent(context, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_NOTIFICATION_SMS);
startIntent.putExtra("notification_sender", title);
startIntent.putExtra("notification_body", body);
context.startService(startIntent);
GBApplication.deviceService().onSMS(title, body);
}
}
}

View File

@ -5,7 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
@ -62,11 +62,7 @@ public class PhoneCallReceiver extends BroadcastReceiver {
break;
}
if (callCommand != null) {
Intent startIntent = new Intent(context, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_CALLSTATE);
startIntent.putExtra("call_phonenumber", mSavedNumber);
startIntent.putExtra("call_command", callCommand.ordinal());
context.startService(startIntent);
GBApplication.deviceService().onSetCallState(mSavedNumber, null, callCommand);
}
mLastState = state;
}

View File

@ -9,7 +9,7 @@ import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.telephony.SmsMessage;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
public class SMSReceiver extends BroadcastReceiver {
@ -36,11 +36,7 @@ public class SMSReceiver extends BroadcastReceiver {
String body = message.getDisplayMessageBody();
String sender = message.getOriginatingAddress();
if (sender != null && body != null) {
Intent startIntent = new Intent(context, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_NOTIFICATION_SMS);
startIntent.putExtra("notification_sender", sender);
startIntent.putExtra("notification_body", body);
context.startService(startIntent);
GBApplication.deviceService().onSMS(sender, body);
}
}
}

View File

@ -9,7 +9,7 @@ import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
public class TimeChangeReceiver extends BroadcastReceiver {
@ -23,9 +23,7 @@ public class TimeChangeReceiver extends BroadcastReceiver {
if (sharedPrefs.getBoolean("datetime_synconconnect", true) && (action.equals(Intent.ACTION_TIME_CHANGED) || action.equals(Intent.ACTION_TIMEZONE_CHANGED))) {
LOG.info("Time or Timezone changed, syncing with device");
Intent startIntent = new Intent(context, DeviceCommunicationService.class);
startIntent.setAction(DeviceCommunicationService.ACTION_SETTIME);
context.startService(startIntent);
GBApplication.deviceService().onSetTime();
}
}
}

View File

@ -0,0 +1,186 @@
package nodomain.freeyourgadget.gadgetbridge.impl;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
public class GBDeviceService implements DeviceService {
protected final Context mContext;
protected final Class<? extends Service> mServiceClass;
public GBDeviceService(Context context, Class<? extends Service> serviceClass) {
mContext = context;
mServiceClass = serviceClass;
}
private Intent createIntent() {
Intent startIntent = new Intent(mContext, mServiceClass);
return startIntent;
}
protected void invokeService(Intent intent) {
mContext.startService(intent);
}
protected void stopService(Intent intent) {
mContext.stopService(intent);
}
@Override
public void start() {
Intent intent = createIntent().setAction(ACTION_START);
invokeService(intent);
}
@Override
public void connect() {
connect(null, false);
}
@Override
public void connect(@Nullable String deviceAddress) {
connect(deviceAddress, false);
}
@Override
public void connect(@Nullable String deviceAddress, boolean performPair) {
Intent intent = createIntent().setAction(ACTION_CONNECT)
.putExtra(EXTRA_DEVICE_ADDRESS, deviceAddress)
.putExtra(EXTRA_PERFORM_PAIR, performPair);
invokeService(intent);
}
@Override
public void disconnect() {
Intent intent = createIntent().setAction(ACTION_DISCONNECT);
invokeService(intent);
}
@Override
public void quit() {
Intent intent = createIntent();
stopService(intent);
}
@Override
public void requestDeviceInfo() {
Intent intent = createIntent().setAction(ACTION_REQUEST_DEVICEINFO);
invokeService(intent);
}
@Override
public void onSMS(String from, String body) {
Intent intent = createIntent().setAction(ACTION_NOTIFICATION_SMS)
.putExtra(EXTRA_NOTIFICATION_SENDER, from)
.putExtra(EXTRA_NOTIFICATION_BODY, body);
invokeService(intent);
}
@Override
public void onEmail(String from, String subject, String body) {
Intent intent = createIntent().setAction(ACTION_NOTIFICATION_EMAIL)
.putExtra(EXTRA_NOTIFICATION_SENDER, from)
.putExtra(EXTRA_NOTIFICATION_SUBJECT, subject)
.putExtra(EXTRA_NOTIFICATION_BODY, body);
invokeService(intent);
}
@Override
public void onGenericNotification(String title, String details) {
Intent intent = createIntent().setAction(ACTION_NOTIFICATION_GENERIC)
.putExtra(EXTRA_NOTIFICATION_TITLE, title)
.putExtra(EXTRA_NOTIFICATION_BODY, details);
invokeService(intent);
}
@Override
public void onSetTime() {
Intent intent = createIntent().setAction(ACTION_SETTIME);
invokeService(intent);
}
@Override
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
Intent intent = createIntent().setAction(ACTION_SET_ALARMS)
.putParcelableArrayListExtra(EXTRA_ALARMS, alarms);
invokeService(intent);
}
@Override
public void onSetCallState(String number, String name, ServiceCommand command) {
// name is actually ignored and provided by the service itself...
Intent intent = createIntent().setAction(ACTION_CALLSTATE)
.putExtra(EXTRA_CALL_PHONENUMBER, number)
.putExtra(EXTRA_CALL_COMMAND, command);
invokeService(intent);
}
@Override
public void onSetMusicInfo(String artist, String album, String track) {
Intent intent = createIntent().setAction(ACTION_SETMUSICINFO)
.putExtra(EXTRA_MUSIC_ARTIST, artist)
.putExtra(EXTRA_MUSIC_TRACK, track);
invokeService(intent);
}
@Override
public void onInstallApp(Uri uri) {
Intent intent = createIntent().setAction(ACTION_INSTALL)
.putExtra(EXTRA_URI, uri);
invokeService(intent);
}
@Override
public void onAppInfoReq() {
Intent intent = createIntent().setAction(ACTION_REQUEST_APPINFO);
invokeService(intent);
}
@Override
public void onAppStart(UUID uuid) {
Intent intent = createIntent().setAction(ACTION_STARTAPP)
.putExtra(EXTRA_APP_UUID, uuid);
invokeService(intent);
}
@Override
public void onAppDelete(UUID uuid) {
Intent intent = createIntent().setAction(ACTION_DELETEAPP)
.putExtra(EXTRA_APP_UUID, uuid);
invokeService(intent);
}
@Override
public void onFetchActivityData() {
Intent intent = createIntent().setAction(ACTION_FETCH_ACTIVITY_DATA);
invokeService(intent);
}
@Override
public void onReboot() {
Intent intent = createIntent().setAction(ACTION_REBOOT);
invokeService(intent);
}
@Override
public void onFindDevice(boolean start) {
Intent intent = createIntent().setAction(ACTION_FIND_DEVICE)
.putExtra(EXTRA_APP_UUID, start);
invokeService(intent);
}
@Override
public void onScreenshotReq() {
Intent intent = createIntent().setAction(ACTION_REQUEST_SCREENSHOT);
invokeService(intent);
}
}

View File

@ -0,0 +1,68 @@
package nodomain.freeyourgadget.gadgetbridge.model;
import android.support.annotation.Nullable;
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
/**
*
*/
public interface DeviceService extends EventHandler {
static final String PREFIX = "nodomain.freeyourgadget.gadgetbridge.devices";
static final String ACTION_START = PREFIX + ".action.start";
static final String ACTION_CONNECT = PREFIX + ".action.connect";
static final String ACTION_NOTIFICATION_GENERIC = PREFIX + ".action.notification_generic";
static final String ACTION_NOTIFICATION_SMS = PREFIX + ".action.notification_sms";
static final String ACTION_NOTIFICATION_EMAIL = PREFIX + ".action.notification_email";
static final String ACTION_CALLSTATE = PREFIX + ".action.callstate";
static final String ACTION_SETTIME = PREFIX + ".action.settime";
static final String ACTION_SETMUSICINFO = PREFIX + ".action.setmusicinfo";
static final String ACTION_REQUEST_DEVICEINFO = PREFIX + ".action.request_deviceinfo";
static final String ACTION_REQUEST_APPINFO = PREFIX + ".action.request_appinfo";
static final String ACTION_REQUEST_SCREENSHOT = PREFIX + ".action.request_screenshot";
static final String ACTION_STARTAPP = PREFIX + ".action.startapp";
static final String ACTION_DELETEAPP = PREFIX + ".action.deleteapp";
static final String ACTION_INSTALL = PREFIX + ".action.install";
static final String ACTION_REBOOT = PREFIX + ".action.reboot";
static final String ACTION_FETCH_ACTIVITY_DATA = PREFIX + ".action.fetch_activity_data";
static final String ACTION_DISCONNECT = PREFIX + ".action.disconnect";
static final String ACTION_FIND_DEVICE = PREFIX + ".action.find_device";
static final String ACTION_SET_ALARMS = PREFIX + ".action.set_alarms";
static final String EXTRA_DEVICE_ADDRESS = "device_address";
static final String EXTRA_NOTIFICATION_TITLE = "notification_title";
static final String EXTRA_NOTIFICATION_BODY = "notification_body";
static final String EXTRA_NOTIFICATION_SENDER = "notification_sender";
static final String EXTRA_NOTIFICATION_SUBJECT = "notification_subject";
static final String EXTRA_FIND_START = "find_start";
static final String EXTRA_CALL_COMMAND = "call_command";
static final String EXTRA_CALL_PHONENUMBER = "call_phonenumber";
static final String EXTRA_MUSIC_ARTIST = "music_artist";
static final String EXTRA_MUSIC_ALBUM = "music_album";
static final String EXTRA_MUSIC_TRACK = "music_track";
static final String EXTRA_APP_UUID = "app_uuid";
static final String EXTRA_URI = "uri";
static final String EXTRA_ALARMS = "alarms";
static final String EXTRA_PERFORM_PAIR = "perform_pair";
void start();
void connect();
void connect(@Nullable String deviceAddress);
void connect(@Nullable String deviceAddress, boolean performPair);
void disconnect();
void quit();
/**
* Requests information from the {@link DeviceCommunicationService} about the connection state,
* firmware info, etc.
* <p/>
* Note that this will not need a connection to the device -- only the cached information
* from the service will be reported.
*/
void requestDeviceInfo();
}

View File

@ -27,46 +27,10 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.*;
public class DeviceCommunicationService extends Service {
public static final String ACTION_START
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.start";
public static final String ACTION_CONNECT
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.connect";
public static final String ACTION_NOTIFICATION_GENERIC
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.notification_generic";
public static final String ACTION_NOTIFICATION_SMS
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.notification_sms";
public static final String ACTION_NOTIFICATION_EMAIL
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.notification_email";
public static final String ACTION_CALLSTATE
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.callstate";
public static final String ACTION_SETTIME
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.settime";
public static final String ACTION_SETMUSICINFO
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.setmusicinfo";
public static final String ACTION_REQUEST_DEVICEINFO
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.request_deviceinfo";
public static final String ACTION_REQUEST_APPINFO
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.request_appinfo";
public static final String ACTION_REQUEST_SCREENSHOT
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.request_screenshot";
public static final String ACTION_STARTAPP
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.startapp";
public static final String ACTION_DELETEAPP
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.deleteapp";
public static final String ACTION_INSTALL
= "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.install";
public static final String ACTION_REBOOT = "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.reboot";
public static final String ACTION_FETCH_ACTIVITY_DATA = "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.fetch_activity_data";
public static final String ACTION_DISCONNECT = "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.disconnect";
public static final String ACTION_FIND_DEVICE = "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.find_device";
public static final String ACTION_SET_ALARMS = "nodomain.freeyourgadget.gadgetbridge.devicecommunicationservice.action.set_alarms";
public static final String EXTRA_PERFORM_PAIR = "perform_pair";
private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
public static final String EXTRA_DEVICE_ADDRESS = "device_address";
private boolean mStarted = false;
@ -179,22 +143,22 @@ public class DeviceCommunicationService extends Service {
mGBDevice.sendDeviceUpdateIntent(this);
break;
case ACTION_NOTIFICATION_GENERIC: {
String title = intent.getStringExtra("notification_title");
String body = intent.getStringExtra("notification_body");
String title = intent.getStringExtra(EXTRA_NOTIFICATION_TITLE);
String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
mDeviceSupport.onGenericNotification(title, body);
break;
}
case ACTION_NOTIFICATION_SMS: {
String sender = intent.getStringExtra("notification_sender");
String body = intent.getStringExtra("notification_body");
String sender = intent.getStringExtra(EXTRA_NOTIFICATION_SENDER);
String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
String senderName = getContactDisplayNameByNumber(sender);
mDeviceSupport.onSMS(senderName, body);
break;
}
case ACTION_NOTIFICATION_EMAIL: {
String sender = intent.getStringExtra("notification_sender");
String subject = intent.getStringExtra("notification_subject");
String body = intent.getStringExtra("notification_body");
String sender = intent.getStringExtra(EXTRA_NOTIFICATION_SENDER);
String subject = intent.getStringExtra(EXTRA_NOTIFICATION_SUBJECT);
String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
mDeviceSupport.onEmail(sender, subject, body);
break;
}
@ -212,14 +176,14 @@ public class DeviceCommunicationService extends Service {
break;
}
case ACTION_FIND_DEVICE: {
boolean start = intent.getBooleanExtra("find_start", false);
boolean start = intent.getBooleanExtra(EXTRA_FIND_START, false);
mDeviceSupport.onFindDevice(start);
break;
}
case ACTION_CALLSTATE:
ServiceCommand command = ServiceCommand.values()[intent.getIntExtra("call_command", 0)]; // UGLY
ServiceCommand command = (ServiceCommand) intent.getSerializableExtra(EXTRA_CALL_COMMAND);
String phoneNumber = intent.getStringExtra("call_phonenumber");
String phoneNumber = intent.getStringExtra(EXTRA_CALL_PHONENUMBER);
String callerName = null;
if (phoneNumber != null) {
callerName = getContactDisplayNameByNumber(phoneNumber);
@ -227,12 +191,12 @@ public class DeviceCommunicationService extends Service {
mDeviceSupport.onSetCallState(phoneNumber, callerName, command);
break;
case ACTION_SETTIME:
mDeviceSupport.onSetTime(-1);
mDeviceSupport.onSetTime();
break;
case ACTION_SETMUSICINFO:
String artist = intent.getStringExtra("music_artist");
String album = intent.getStringExtra("music_album");
String track = intent.getStringExtra("music_track");
String artist = intent.getStringExtra(EXTRA_MUSIC_ARTIST);
String album = intent.getStringExtra(EXTRA_MUSIC_ALBUM);
String track = intent.getStringExtra(EXTRA_MUSIC_TRACK);
mDeviceSupport.onSetMusicInfo(artist, album, track);
break;
case ACTION_REQUEST_APPINFO:
@ -241,23 +205,25 @@ public class DeviceCommunicationService extends Service {
case ACTION_REQUEST_SCREENSHOT:
mDeviceSupport.onScreenshotReq();
break;
case ACTION_STARTAPP:
UUID uuid = UUID.fromString(intent.getStringExtra("app_uuid"));
case ACTION_STARTAPP: {
UUID uuid = (UUID) intent.getSerializableExtra(EXTRA_APP_UUID);
mDeviceSupport.onAppStart(uuid);
break;
case ACTION_DELETEAPP:
uuid = UUID.fromString(intent.getStringExtra("app_uuid"));
}
case ACTION_DELETEAPP: {
UUID uuid = (UUID) intent.getSerializableExtra(EXTRA_APP_UUID);
mDeviceSupport.onAppDelete(uuid);
break;
}
case ACTION_INSTALL:
Uri uri = intent.getParcelableExtra("uri");
Uri uri = intent.getParcelableExtra(EXTRA_URI);
if (uri != null) {
LOG.info("will try to install app/fw");
mDeviceSupport.onInstallApp(uri);
}
break;
case ACTION_SET_ALARMS:
ArrayList<Alarm> alarms = intent.getParcelableArrayListExtra("alarms");
ArrayList<Alarm> alarms = intent.getParcelableArrayListExtra(EXTRA_ALARMS);
mDeviceSupport.onSetAlarms(alarms);
break;
}

View File

@ -11,9 +11,9 @@ import java.util.ArrayList;
import java.util.EnumSet;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
/**
* Wraps another device support instance and supports busy-checking and throttling of events.
@ -135,11 +135,11 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
@Override
public void onSetTime(long ts) {
public void onSetTime() {
if (checkBusy("set time") || checkThrottle("set time")) {
return;
}
delegate.onSetTime(ts);
delegate.onSetTime();
}
// No throttling for the other events
@ -160,14 +160,6 @@ public class ServiceDeviceSupport implements DeviceSupport {
delegate.onSetMusicInfo(artist, album, track);
}
@Override
public void onBatteryInfoReq() {
if (checkBusy("battery info request")) {
return;
}
delegate.onBatteryInfoReq();
}
@Override
public void onInstallApp(Uri uri) {
if (checkBusy("install app")) {
@ -200,14 +192,6 @@ public class ServiceDeviceSupport implements DeviceSupport {
delegate.onAppDelete(uuid);
}
@Override
public void onPhoneVersion(byte os) {
if (checkBusy("phone version")) {
return;
}
delegate.onPhoneVersion(os);
}
@Override
public void onFetchActivityData() {
if (checkBusy("fetch activity data")) {
@ -241,7 +225,7 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
@Override
public void onSetAlarms(ArrayList<Alarm> alarms) {
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
if (checkBusy("set alarms")) {
return;
}

View File

@ -382,7 +382,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetAlarms(ArrayList<Alarm> alarms) {
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
try {
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT);
TransactionBuilder builder = performInitialized("Set alarm");
@ -413,7 +413,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSetTime(long ts) {
public void onSetTime() {
try {
TransactionBuilder builder = performInitialized("Set date and time");
setCurrentTime(builder);
@ -479,17 +479,6 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
// not supported
}
@Override
public void onBatteryInfoReq() {
try {
TransactionBuilder builder = performInitialized("Get MI Band battery info");
requestBatteryInfo(builder);
builder.queue(getQueue());
} catch (IOException ex) {
LOG.error("Unable to read battery info from MI", ex);
}
}
@Override
public void onReboot() {
try {
@ -587,11 +576,6 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
// not supported
}
@Override
public void onPhoneVersion(byte os) {
// not supported
}
@Override
public void onScreenshotReq() {
// not supported

View File

@ -320,7 +320,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
if (sharedPrefs.getBoolean("datetime_synconconnect", true)) {
LOG.info("syncing time");
write(mPebbleProtocol.encodeSetTime(-1));
write(mPebbleProtocol.encodeSetTime());
}
gbDevice.setState(GBDevice.State.INITIALIZED);
return false;
@ -480,10 +480,12 @@ public class PebbleIoThread extends GBDeviceIoThread {
mPBWReader = null;
mIsInstalling = false;
try {
mZis.close();
} catch (IOException e) {
// ignore
if (mZis != null) {
try {
mZis.close();
} catch (IOException e) {
// ignore
}
}
mZis = null;
mAppInstallToken = -1;
@ -500,6 +502,13 @@ public class PebbleIoThread extends GBDeviceIoThread {
e.printStackTrace();
}
}
if (mTCPSocket != null) {
try {
mTCPSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private enum PebbleAppInstallState {

View File

@ -38,7 +38,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
static final short ENDPOINT_PHONECONTROL = 33;
static final short ENDPOINT_APPLICATIONMESSAGE = 48;
static final short ENDPOINT_LAUNCHER = 49;
static final short ENDPOINT_APPRUNSTATE = 52;
static final short ENDPOINT_APPRUNSTATE = 52; // 3.x only
static final short ENDPOINT_LOGS = 2000;
static final short ENDPOINT_PING = 2001;
static final short ENDPOINT_LOGDUMP = 2002;
@ -178,10 +178,10 @@ public class PebbleProtocol extends GBDeviceProtocol {
static final short LENGTH_APPFETCH = 2;
static final short LENGTH_APPRUNSTATE = 17;
static final short LENGTH_BLOBDB = 21;
static final short LENGTH_PING = 5;
static final short LENGTH_PHONEVERSION = 17;
static final short LENGTH_REMOVEAPP_2X = 17;
static final short LENGTH_REMOVEAPP_3X = 21;
static final short LENGTH_REFRESHAPP = 5;
static final short LENGTH_SETTIME = 5;
static final short LENGTH_SYSTEMMESSAGE = 2;
@ -299,10 +299,8 @@ public class PebbleProtocol extends GBDeviceProtocol {
}
@Override
public byte[] encodeSetTime(long ts) {
if (ts == -1) {
ts = System.currentTimeMillis();
}
public byte[] encodeSetTime() {
long ts = System.currentTimeMillis();
long ts_offset = (SimpleTimeZone.getDefault().getOffset(ts));
ByteBuffer buf;
if (isFw3x) {
@ -398,6 +396,37 @@ public class PebbleProtocol extends GBDeviceProtocol {
return buf.array();
}
private byte[] encodeBlobdb(UUID uuid, byte command, byte db, byte[] blob) {
int length = LENGTH_BLOBDB;
if (blob != null) {
length += blob.length + 2;
}
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + length);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort((short) length);
buf.putShort(ENDPOINT_BLOBDB);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put(command);
buf.putShort((short) mRandom.nextInt()); // token
buf.put(db);
buf.put(LENGTH_UUID);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putLong(uuid.getMostSignificantBits());
buf.putLong(uuid.getLeastSignificantBits());
buf.order(ByteOrder.LITTLE_ENDIAN);
if (blob != null) {
buf.putShort((short) blob.length);
buf.put(blob);
}
return buf.array();
}
private byte[] encodeBlobdbNotification(int timestamp, String title, String subtitle, String body, byte type) {
String[] parts = {title, subtitle, body};
@ -410,7 +439,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
icon_id = 45;
}
// Calculate length first
final short BLOBDB_LENGTH = 23;
final short NOTIFICATION_PIN_LENGTH = 46;
final short ACTIONS_LENGTH = 17;
@ -434,31 +462,18 @@ public class PebbleProtocol extends GBDeviceProtocol {
attributes_length += ACTIONS_LENGTH;
}
short length = (short) (BLOBDB_LENGTH + NOTIFICATION_PIN_LENGTH + attributes_length);
UUID uuid = UUID.randomUUID();
short pin_length = (short) (NOTIFICATION_PIN_LENGTH + attributes_length);
// Encode Prefix
ByteBuffer buf = ByteBuffer.allocate(length + LENGTH_PREFIX);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort(length);
buf.putShort(ENDPOINT_BLOBDB);
buf.order(ByteOrder.LITTLE_ENDIAN);
// blobdb - 23 bytes
buf.put(BLOBDB_INSERT);
buf.putShort((short) mRandom.nextInt()); // token
buf.put(BLOBDB_NOTIFICATION);
buf.put(LENGTH_UUID); // uuid length
byte[] uuid_buf = new byte[LENGTH_UUID];
mRandom.nextBytes(uuid_buf);
buf.put(uuid_buf); // random UUID
buf.putShort(pin_length); // length of the encapsulated data
ByteBuffer buf = ByteBuffer.allocate(pin_length);
// pin - 46 bytes
buf.put(uuid_buf); // random UUID
buf.put(uuid_buf); // parent UUID
buf.order(ByteOrder.BIG_ENDIAN);
buf.putLong(uuid.getMostSignificantBits());
buf.putLong(uuid.getLeastSignificantBits());
buf.putLong(uuid.getMostSignificantBits());
buf.putLong(uuid.getLeastSignificantBits());
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putInt(timestamp); // 32-bit timestamp
buf.putShort((short) 0); // duration
buf.put((byte) 0x01); // type (0x01 = notification)
@ -500,36 +515,16 @@ public class PebbleProtocol extends GBDeviceProtocol {
buf.put(actionstring.getBytes());
}
return buf.array();
return encodeBlobdb(UUID.randomUUID(), BLOBDB_INSERT, BLOBDB_NOTIFICATION, buf.array());
}
public byte[] encodeInstallMetadata(UUID uuid, String appName, short appVersion, short sdkVersion, int flags, int iconId) {
// Calculate length first
final short BLOBDB_LENGTH = 23;
final short METADATA_LENGTH = 126;
final short length = (short) (BLOBDB_LENGTH + METADATA_LENGTH);
byte[] name_buf = new byte[96];
System.arraycopy(appName.getBytes(), 0, name_buf, 0, appName.length());
ByteBuffer buf = ByteBuffer.allocate(length + LENGTH_PREFIX);
ByteBuffer buf = ByteBuffer.allocate(METADATA_LENGTH);
// Encode Prefix
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort(length);
buf.putShort(ENDPOINT_BLOBDB);
buf.order(ByteOrder.LITTLE_ENDIAN);
// blobdb - 23 bytes
buf.put(BLOBDB_INSERT); // insert
buf.putShort((short) mRandom.nextInt()); // token
buf.put(BLOBDB_APP);
buf.put(LENGTH_UUID);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putLong(uuid.getMostSignificantBits()); // watchapp uuid
buf.putLong(uuid.getLeastSignificantBits());
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putShort(METADATA_LENGTH); // length of the encapsulated data
buf.order(ByteOrder.BIG_ENDIAN);
buf.putLong(uuid.getMostSignificantBits()); // watchapp uuid
buf.putLong(uuid.getLeastSignificantBits());
@ -542,7 +537,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
buf.put((byte) 0); // app_face_template_id
buf.put(name_buf); // 96 bytes
return buf.array();
return encodeBlobdb(uuid, BLOBDB_INSERT, BLOBDB_APP, buf.array());
}
public byte[] encodeAppFetchAck() {
@ -630,28 +625,18 @@ public class PebbleProtocol extends GBDeviceProtocol {
@Override
public byte[] encodeAppDelete(UUID uuid) {
ByteBuffer buf;
if (isFw3x) {
buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_REMOVEAPP_3X);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort(LENGTH_REMOVEAPP_3X);
buf.putShort(ENDPOINT_BLOBDB);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put(BLOBDB_DELETE);
buf.putShort((short) mRandom.nextInt()); // token
buf.put(BLOBDB_APP);
buf.put(LENGTH_UUID);
buf.order(ByteOrder.BIG_ENDIAN);
return encodeBlobdb(uuid, BLOBDB_DELETE, BLOBDB_APP, null);
} else {
buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_REMOVEAPP_2X);
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_REMOVEAPP_2X);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort(LENGTH_REMOVEAPP_2X);
buf.putShort(ENDPOINT_APPMANAGER);
buf.put(APPMANAGER_REMOVEAPP);
buf.putLong(uuid.getMostSignificantBits());
buf.putLong(uuid.getLeastSignificantBits());
return buf.array();
}
buf.putLong(uuid.getMostSignificantBits());
buf.putLong(uuid.getLeastSignificantBits());
return buf.array();
}
private byte[] encodePhoneVersion2x(byte os) {
@ -701,7 +686,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
return buf.array();
}
@Override
public byte[] encodePhoneVersion(byte os) {
return encodePhoneVersion3x(os);
}

View File

@ -43,7 +43,7 @@ public class PebbleSupport extends AbstractSerialDeviceSupport {
}
@Override
public void onSetAlarms(ArrayList<Alarm> alarms) {
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
//nothing to do ATM
}
}

View File

@ -129,8 +129,8 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
}
@Override
public void onSetTime(long ts) {
byte[] bytes = gbDeviceProtocol.encodeSetTime(ts);
public void onSetTime() {
byte[] bytes = gbDeviceProtocol.encodeSetTime();
sendToDevice(bytes);
}
@ -146,12 +146,6 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
sendToDevice(bytes);
}
@Override
public void onBatteryInfoReq() {
byte[] bytes = gbDeviceProtocol.encodeBatteryInfoReq();
sendToDevice(bytes);
}
@Override
public void onAppInfoReq() {
byte[] bytes = gbDeviceProtocol.encodeAppInfoReq();
@ -170,12 +164,6 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
sendToDevice(bytes);
}
@Override
public void onPhoneVersion(byte os) {
byte[] bytes = gbDeviceProtocol.encodePhoneVersion(os);
sendToDevice(bytes);
}
@Override
public void onFetchActivityData() {
byte[] bytes = gbDeviceProtocol.encodeSynchronizeActivityData();

View File

@ -19,7 +19,7 @@ public abstract class GBDeviceProtocol {
return null;
}
public byte[] encodeSetTime(long ts) {
public byte[] encodeSetTime() {
return null;
}
@ -35,10 +35,6 @@ public abstract class GBDeviceProtocol {
return null;
}
public byte[] encodeBatteryInfoReq() {
return null;
}
public byte[] encodeAppInfoReq() {
return null;
}
@ -55,10 +51,6 @@ public abstract class GBDeviceProtocol {
return null;
}
public byte[] encodePhoneVersion(byte os) {
return null;
}
public byte[] encodeSynchronizeActivityData() {
return null;
}

View File

@ -14,8 +14,6 @@ import android.os.Looper;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
import com.github.pfichtner.durationformatter.DurationFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -24,11 +22,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;