Merge remote-tracking branch 'origin/master' into db-refactoring
This commit is contained in:
commit
a01507a924
|
@ -1,4 +1,12 @@
|
|||
###Changelog
|
||||
####Version 0.10.1
|
||||
* Pebble: set extended music info by dissecting notifications on Android 5.0+
|
||||
* Pebble: various other improvemnts to music playback
|
||||
* Pebble: allow ignoring activity trackers indiviually (to keep the data on the pebble)
|
||||
* Mi Band: support for shifting the device time by N hours (for people who sleep at daytime)
|
||||
* Mi Band: initial and untested support for Mi Band 2
|
||||
* Allow setting the application language
|
||||
|
||||
####Version 0.10.0
|
||||
* Pebble: option to send sunrise and sunset events to timeline
|
||||
* Pebble: fix problems with unknown app keys while configuring watchfaces
|
||||
|
|
|
@ -18,8 +18,8 @@ android {
|
|||
targetSdkVersion 23
|
||||
|
||||
// note: always bump BOTH versionCode and versionName!
|
||||
versionName "0.10.0"
|
||||
versionCode 53
|
||||
versionName "0.10.1"
|
||||
versionCode 54
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
|
|
@ -193,6 +193,9 @@ public class AppManagerActivity extends GBActivity {
|
|||
if (!selectedApp.isConfigurable()) {
|
||||
menu.removeItem(R.id.appmanager_app_configure);
|
||||
}
|
||||
if (mGBDevice != null && !mGBDevice.getFirmwareVersion().startsWith("v3")) {
|
||||
menu.removeItem(R.id.appmanager_app_move_to_top);
|
||||
}
|
||||
menu.setHeaderTitle(selectedApp.getName());
|
||||
}
|
||||
|
||||
|
@ -256,6 +259,9 @@ public class AppManagerActivity extends GBActivity {
|
|||
startIntent.putExtra(GBDevice.EXTRA_DEVICE, mGBDevice);
|
||||
startActivity(startIntent);
|
||||
return true;
|
||||
case R.id.appmanager_app_move_to_top:
|
||||
GBApplication.deviceService().onAppReorder(new UUID[]{selectedApp.getUUID()});
|
||||
return true;
|
||||
default:
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
@ -222,6 +223,15 @@ public class DebugActivity extends GBActivity {
|
|||
musicSpec.trackNr = 2;
|
||||
|
||||
GBApplication.deviceService().onSetMusicInfo(musicSpec);
|
||||
|
||||
MusicStateSpec stateSpec = new MusicStateSpec();
|
||||
stateSpec.position = 0;
|
||||
stateSpec.state = 0x01; // playing
|
||||
stateSpec.playRate = 100;
|
||||
stateSpec.repeat = 1;
|
||||
stateSpec.shuffle = 1;
|
||||
|
||||
GBApplication.deviceService().onSetMusicState(stateSpec);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
|
||||
/**
|
||||
|
@ -25,6 +26,8 @@ public interface EventHandler {
|
|||
|
||||
void onSetCallState(CallSpec callSpec);
|
||||
|
||||
void onSetMusicState(MusicStateSpec stateSpec);
|
||||
|
||||
void onSetMusicInfo(MusicSpec musicSpec);
|
||||
|
||||
void onEnableRealtimeSteps(boolean enable);
|
||||
|
@ -39,6 +42,8 @@ public interface EventHandler {
|
|||
|
||||
void onAppConfiguration(UUID appUuid, String config);
|
||||
|
||||
void onAppReorder(UUID uuids[]);
|
||||
|
||||
void onFetchActivityData();
|
||||
|
||||
void onReboot();
|
||||
|
|
|
@ -3,30 +3,54 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
|||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
|
||||
public class MusicPlaybackReceiver extends BroadcastReceiver {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MusicPlaybackReceiver.class);
|
||||
private static MusicSpec lastMusicSpec = new MusicSpec();
|
||||
private static MusicStateSpec lastStatecSpec = new MusicStateSpec();
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String artist = intent.getStringExtra("artist");
|
||||
String album = intent.getStringExtra("album");
|
||||
String track = intent.getStringExtra("track");
|
||||
|
||||
LOG.info("Current track: " + artist + ", " + album + ", " + track);
|
||||
|
||||
/*
|
||||
Bundle bundle = intent.getExtras();
|
||||
for (String key : bundle.keySet()) {
|
||||
Object value = bundle.get(key);
|
||||
LOG.info(String.format("%s %s (%s)", key,
|
||||
value != null ? value.toString() : "null", value != null ? value.getClass().getName() : "no class"));
|
||||
}
|
||||
*/
|
||||
MusicSpec musicSpec = new MusicSpec();
|
||||
musicSpec.artist = artist;
|
||||
musicSpec.album = album;
|
||||
musicSpec.track = track;
|
||||
musicSpec.artist = intent.getStringExtra("artist");
|
||||
musicSpec.album = intent.getStringExtra("album");
|
||||
musicSpec.track = intent.getStringExtra("track");
|
||||
musicSpec.duration = intent.getIntExtra("duration", 0) / 1000;
|
||||
|
||||
GBApplication.deviceService().onSetMusicInfo(musicSpec);
|
||||
if (!lastMusicSpec.equals(musicSpec)) {
|
||||
lastMusicSpec = musicSpec;
|
||||
LOG.info("Update Music Info: " + musicSpec.artist + " / " + musicSpec.album + " / " + musicSpec.track);
|
||||
GBApplication.deviceService().onSetMusicInfo(musicSpec);
|
||||
} else {
|
||||
LOG.info("got metadata changed intent, but nothing changed, ignoring.");
|
||||
}
|
||||
|
||||
if (intent.hasExtra("position") && intent.hasExtra("playing")) {
|
||||
MusicStateSpec stateSpec = new MusicStateSpec();
|
||||
stateSpec.position = intent.getIntExtra("position", 0) / 1000;
|
||||
stateSpec.state = (byte) (intent.getBooleanExtra("playing", true) ? MusicStateSpec.STATE_PLAYING : MusicStateSpec.STATE_PAUSED);
|
||||
if (!lastStatecSpec.equals(stateSpec)) {
|
||||
LOG.info("Update Music State: state=" + stateSpec.state + ", position= " + stateSpec.position);
|
||||
GBApplication.deviceService().onSetMusicState(stateSpec);
|
||||
} else {
|
||||
LOG.info("got state changed intent, but not enough has changed, ignoring.");
|
||||
}
|
||||
lastStatecSpec = stateSpec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,11 @@ import android.content.Intent;
|
|||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.MediaMetadata;
|
||||
import android.media.session.MediaController;
|
||||
import android.media.session.MediaSession;
|
||||
import android.media.session.PlaybackState;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
|
@ -25,6 +30,8 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
|
||||
|
@ -161,13 +168,6 @@ public class NotificationListener extends NotificationListenerService {
|
|||
return;
|
||||
}
|
||||
|
||||
Prefs prefs = GBApplication.getPrefs();
|
||||
if (!prefs.getBoolean("notifications_generic_whenscreenon", false)) {
|
||||
PowerManager powermanager = (PowerManager) getSystemService(POWER_SERVICE);
|
||||
if (powermanager.isScreenOn()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (GBApplication.getGrantedInterruptionFilter()) {
|
||||
case NotificationManager.INTERRUPTION_FILTER_ALL:
|
||||
break;
|
||||
|
@ -182,6 +182,17 @@ public class NotificationListener extends NotificationListenerService {
|
|||
String source = sbn.getPackageName();
|
||||
Notification notification = sbn.getNotification();
|
||||
|
||||
if (handleMediaSessionNotification(notification))
|
||||
return;
|
||||
|
||||
Prefs prefs = GBApplication.getPrefs();
|
||||
if (!prefs.getBoolean("notifications_generic_whenscreenon", false)) {
|
||||
PowerManager powermanager = (PowerManager) getSystemService(POWER_SERVICE);
|
||||
if (powermanager.isScreenOn()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((notification.flags & Notification.FLAG_ONGOING_EVENT) == Notification.FLAG_ONGOING_EVENT) {
|
||||
return;
|
||||
}
|
||||
|
@ -311,6 +322,79 @@ public class NotificationListener extends NotificationListenerService {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to handle media session notifications that tell info about the current play state.
|
||||
*
|
||||
* @param notification The notification to handle.
|
||||
* @return true if notification was handled, false otherwise
|
||||
*/
|
||||
public boolean handleMediaSessionNotification(Notification notification) {
|
||||
|
||||
// this code requires Android 5.0 or newer
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MusicSpec musicSpec = new MusicSpec();
|
||||
MusicStateSpec stateSpec = new MusicStateSpec();
|
||||
|
||||
Bundle extras = notification.extras;
|
||||
if (extras == null)
|
||||
return false;
|
||||
|
||||
if (extras.get(Notification.EXTRA_MEDIA_SESSION) == null)
|
||||
return false;
|
||||
|
||||
MediaController c;
|
||||
try {
|
||||
c = new MediaController(getApplicationContext(), (MediaSession.Token) extras.get(Notification.EXTRA_MEDIA_SESSION));
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PlaybackState s = c.getPlaybackState();
|
||||
stateSpec.position = (int) (s.getPosition() / 1000);
|
||||
stateSpec.playRate = Math.round(100 * s.getPlaybackSpeed());
|
||||
stateSpec.repeat = 1;
|
||||
stateSpec.shuffle = 1;
|
||||
switch (s.getState()) {
|
||||
case PlaybackState.STATE_PLAYING:
|
||||
stateSpec.state = MusicStateSpec.STATE_PLAYING;
|
||||
break;
|
||||
case PlaybackState.STATE_STOPPED:
|
||||
stateSpec.state = MusicStateSpec.STATE_STOPPED;
|
||||
break;
|
||||
case PlaybackState.STATE_PAUSED:
|
||||
stateSpec.state = MusicStateSpec.STATE_PAUSED;
|
||||
break;
|
||||
default:
|
||||
stateSpec.state = MusicStateSpec.STATE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
MediaMetadata d = c.getMetadata();
|
||||
if (d == null)
|
||||
return false;
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_ARTIST))
|
||||
musicSpec.artist = d.getString(MediaMetadata.METADATA_KEY_ARTIST);
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_ALBUM))
|
||||
musicSpec.album = d.getString(MediaMetadata.METADATA_KEY_ALBUM);
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_TITLE))
|
||||
musicSpec.track = d.getString(MediaMetadata.METADATA_KEY_TITLE);
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_DURATION))
|
||||
musicSpec.duration = (int)d.getLong(MediaMetadata.METADATA_KEY_DURATION) / 1000;
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_NUM_TRACKS))
|
||||
musicSpec.trackCount = (int)d.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS);
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_TRACK_NUMBER))
|
||||
musicSpec.trackNr = (int)d.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER);
|
||||
|
||||
// finally, tell the device about it
|
||||
GBApplication.deviceService().onSetMusicInfo(musicSpec);
|
||||
GBApplication.deviceService().onSetMusicState(stateSpec);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationRemoved(StatusBarNotification sbn) {
|
||||
|
||||
|
|
|
@ -14,9 +14,12 @@ import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
|
||||
|
||||
//import java.util.UUID;
|
||||
|
||||
public class GBDeviceService implements DeviceService {
|
||||
protected final Context mContext;
|
||||
protected final Class<? extends Service> mServiceClass;
|
||||
|
@ -125,6 +128,17 @@ public class GBDeviceService implements DeviceService {
|
|||
invokeService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicState(MusicStateSpec stateSpec) {
|
||||
Intent intent = createIntent().setAction(ACTION_SETMUSICSTATE)
|
||||
.putExtra(EXTRA_MUSIC_REPEAT, stateSpec.repeat)
|
||||
.putExtra(EXTRA_MUSIC_RATE, stateSpec.playRate)
|
||||
.putExtra(EXTRA_MUSIC_STATE, stateSpec.state)
|
||||
.putExtra(EXTRA_MUSIC_SHUFFLE, stateSpec.shuffle)
|
||||
.putExtra(EXTRA_MUSIC_POSITION, stateSpec.position);
|
||||
invokeService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(MusicSpec musicSpec) {
|
||||
Intent intent = createIntent().setAction(ACTION_SETMUSICINFO)
|
||||
|
@ -173,6 +187,13 @@ public class GBDeviceService implements DeviceService {
|
|||
invokeService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppReorder(UUID[] uuids) {
|
||||
Intent intent = createIntent().setAction(ACTION_APP_REORDER)
|
||||
.putExtra(EXTRA_APP_UUID, uuids);
|
||||
invokeService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFetchActivityData() {
|
||||
Intent intent = createIntent().setAction(ACTION_FETCH_ACTIVITY_DATA);
|
||||
|
|
|
@ -18,12 +18,14 @@ public interface DeviceService extends EventHandler {
|
|||
String ACTION_CALLSTATE = PREFIX + ".action.callstate";
|
||||
String ACTION_SETTIME = PREFIX + ".action.settime";
|
||||
String ACTION_SETMUSICINFO = PREFIX + ".action.setmusicinfo";
|
||||
String ACTION_SETMUSICSTATE = PREFIX + ".action.setmusicstate";
|
||||
String ACTION_REQUEST_DEVICEINFO = PREFIX + ".action.request_deviceinfo";
|
||||
String ACTION_REQUEST_APPINFO = PREFIX + ".action.request_appinfo";
|
||||
String ACTION_REQUEST_SCREENSHOT = PREFIX + ".action.request_screenshot";
|
||||
String ACTION_STARTAPP = PREFIX + ".action.startapp";
|
||||
String ACTION_DELETEAPP = PREFIX + ".action.deleteapp";
|
||||
String ACTION_APP_CONFIGURE = PREFIX + ".action.app_configure";
|
||||
String ACTION_APP_REORDER = PREFIX + ".action.app_reorder";
|
||||
String ACTION_INSTALL = PREFIX + ".action.install";
|
||||
String ACTION_REBOOT = PREFIX + ".action.reboot";
|
||||
String ACTION_HEARTRATE_TEST = PREFIX + ".action.heartrate_test";
|
||||
|
@ -57,6 +59,11 @@ public interface DeviceService extends EventHandler {
|
|||
String EXTRA_MUSIC_DURATION = "music_duration";
|
||||
String EXTRA_MUSIC_TRACKNR = "music_tracknr";
|
||||
String EXTRA_MUSIC_TRACKCOUNT = "music_trackcount";
|
||||
String EXTRA_MUSIC_STATE = "music_state";
|
||||
String EXTRA_MUSIC_SHUFFLE = "music_shuffle";
|
||||
String EXTRA_MUSIC_REPEAT = "music_repeat";
|
||||
String EXTRA_MUSIC_POSITION = "music_position";
|
||||
String EXTRA_MUSIC_RATE = "music_rate";
|
||||
String EXTRA_APP_UUID = "app_uuid";
|
||||
String EXTRA_APP_START = "app_start";
|
||||
String EXTRA_APP_CONFIG = "app_config";
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MusicSpec {
|
||||
public static final int MUSIC_UNDEFINED = 0;
|
||||
public static final int MUSIC_PLAY = 1;
|
||||
|
@ -14,4 +16,23 @@ public class MusicSpec {
|
|||
public int duration;
|
||||
public int trackCount;
|
||||
public int trackNr;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof MusicSpec)) {
|
||||
return false;
|
||||
}
|
||||
MusicSpec musicSpec = (MusicSpec) obj;
|
||||
|
||||
return Objects.equals(this.artist, musicSpec.artist) &&
|
||||
Objects.equals(this.album, musicSpec.album) &&
|
||||
Objects.equals(this.track, musicSpec.track) &&
|
||||
this.duration == musicSpec.duration &&
|
||||
this.trackCount == musicSpec.trackCount &&
|
||||
this.trackNr == musicSpec.trackNr;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||
|
||||
/**
|
||||
* Created by steffen on 07.06.16.
|
||||
*/
|
||||
public class MusicStateSpec {
|
||||
public static final int STATE_PLAYING = 0;
|
||||
public static final int STATE_PAUSED = 1;
|
||||
public static final int STATE_STOPPED = 2;
|
||||
public static final int STATE_UNKNOWN = 3;
|
||||
|
||||
public byte state;
|
||||
public int position;
|
||||
public int playRate;
|
||||
public byte shuffle;
|
||||
public byte repeat;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof MusicStateSpec)) {
|
||||
return false;
|
||||
}
|
||||
MusicStateSpec stateSpec = (MusicStateSpec) obj;
|
||||
|
||||
return this.state == stateSpec.state &&
|
||||
Math.abs(this.position - stateSpec.position)<=2 &&
|
||||
this.playRate == stateSpec.playRate &&
|
||||
this.shuffle == stateSpec.shuffle &&
|
||||
this.repeat == stateSpec.repeat;
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
|
@ -47,6 +48,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
|||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ADD_CALENDAREVENT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_CONFIGURE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_REORDER;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_CALLSTATE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_CONNECT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DELETEAPP;
|
||||
|
@ -65,6 +67,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_RE
|
|||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_DEVICEINFO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_SCREENSHOT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETMUSICINFO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETMUSICSTATE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETTIME;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_ALARMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_START;
|
||||
|
@ -87,6 +90,11 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_FIN
|
|||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ALBUM;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ARTIST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_DURATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_POSITION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_RATE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_REPEAT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_SHUFFLE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_STATE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACK;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACKCOUNT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACKNR;
|
||||
|
@ -351,6 +359,15 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
|||
musicSpec.trackNr = intent.getIntExtra(EXTRA_MUSIC_TRACKNR, 0);
|
||||
mDeviceSupport.onSetMusicInfo(musicSpec);
|
||||
break;
|
||||
case ACTION_SETMUSICSTATE:
|
||||
MusicStateSpec stateSpec = new MusicStateSpec();
|
||||
stateSpec.shuffle = intent.getByteExtra(EXTRA_MUSIC_SHUFFLE, (byte)0);
|
||||
stateSpec.repeat = intent.getByteExtra(EXTRA_MUSIC_REPEAT, (byte)0);
|
||||
stateSpec.position = intent.getIntExtra(EXTRA_MUSIC_POSITION, 0);
|
||||
stateSpec.playRate = intent.getIntExtra(EXTRA_MUSIC_RATE, 0);
|
||||
stateSpec.state = intent.getByteExtra(EXTRA_MUSIC_STATE, (byte)0);
|
||||
mDeviceSupport.onSetMusicState(stateSpec);
|
||||
break;
|
||||
case ACTION_REQUEST_APPINFO:
|
||||
mDeviceSupport.onAppInfoReq();
|
||||
break;
|
||||
|
@ -372,6 +389,12 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
|||
UUID uuid = (UUID) intent.getSerializableExtra(EXTRA_APP_UUID);
|
||||
String config = intent.getStringExtra(EXTRA_APP_CONFIG);
|
||||
mDeviceSupport.onAppConfiguration(uuid, config);
|
||||
break;
|
||||
}
|
||||
case ACTION_APP_REORDER: {
|
||||
UUID[] uuids = (UUID[]) intent.getSerializableExtra(EXTRA_APP_UUID);
|
||||
mDeviceSupport.onAppReorder(uuids);
|
||||
break;
|
||||
}
|
||||
case ACTION_INSTALL:
|
||||
Uri uri = intent.getParcelableExtra(EXTRA_URI);
|
||||
|
|
|
@ -16,6 +16,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
|
||||
/**
|
||||
|
@ -150,6 +151,14 @@ public class ServiceDeviceSupport implements DeviceSupport {
|
|||
delegate.onSetCallState(callSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicState(MusicStateSpec stateSpec) {
|
||||
if (checkBusy("set music state")) {
|
||||
return;
|
||||
}
|
||||
delegate.onSetMusicState(stateSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(MusicSpec musicSpec) {
|
||||
if (checkBusy("set music info")) {
|
||||
|
@ -198,6 +207,14 @@ public class ServiceDeviceSupport implements DeviceSupport {
|
|||
delegate.onAppConfiguration(uuid, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppReorder(UUID[] uuids) {
|
||||
if (checkBusy("app reorder")) {
|
||||
return;
|
||||
}
|
||||
delegate.onAppReorder(uuids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFetchActivityData() {
|
||||
if (checkBusy("fetch activity data")) {
|
||||
|
|
|
@ -38,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
|
||||
|
@ -599,6 +600,11 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||
return telephoneRinging;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicState(MusicStateSpec stateSpec) {
|
||||
// not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(MusicSpec musicSpec) {
|
||||
// not supported
|
||||
|
@ -761,6 +767,11 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||
// not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppReorder(UUID[] uuids) {
|
||||
// not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScreenshotReq() {
|
||||
// not supported
|
||||
|
|
|
@ -18,7 +18,6 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
|||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.MisfitSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.PebbleActivitySample;
|
||||
|
@ -47,8 +46,7 @@ public class AppMessageHandlerMisfit extends AppMessageHandler {
|
|||
@Override
|
||||
public boolean isEnabled() {
|
||||
Prefs prefs = GBApplication.getPrefs();
|
||||
int activityTracker = prefs.getInt("pebble_activitytracker", SampleProvider.PROVIDER_PEBBLE_HEALTH);
|
||||
return (activityTracker == SampleProvider.PROVIDER_PEBBLE_MISFIT);
|
||||
return prefs.getBoolean("pebble_sync_misfit", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -62,8 +62,7 @@ public class AppMessageHandlerMorpheuz extends AppMessageHandler {
|
|||
@Override
|
||||
public boolean isEnabled() {
|
||||
Prefs prefs = GBApplication.getPrefs();
|
||||
int activityTracker = prefs.getInt("pebble_activitytracker", SampleProvider.PROVIDER_PEBBLE_HEALTH);
|
||||
return (activityTracker == SampleProvider.PROVIDER_PEBBLE_MORPHEUZ);
|
||||
return prefs.getBoolean("pebble_sync_morpheuz", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,7 +3,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble;
|
|||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
abstract class DatalogSessionPebbleHealth extends DatalogSession {
|
||||
|
@ -14,7 +13,6 @@ abstract class DatalogSessionPebbleHealth extends DatalogSession {
|
|||
|
||||
protected boolean isPebbleHealthEnabled() {
|
||||
Prefs prefs = GBApplication.getPrefs();
|
||||
int activityTracker = prefs.getInt("pebble_activitytracker", SampleProvider.PROVIDER_PEBBLE_HEALTH);
|
||||
return (activityTracker == SampleProvider.PROVIDER_PEBBLE_HEALTH);
|
||||
return prefs.getBoolean("pebble_sync_health", true);
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
||||
|
@ -70,6 +71,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
static final short ENDPOINT_RUNKEEPER = 7000;
|
||||
static final short ENDPOINT_SCREENSHOT = 8000;
|
||||
static final short ENDPOINT_NOTIFICATIONACTION = 11440; // 3.x only, TODO: find a better name
|
||||
static final short ENDPOINT_APPREORDER = (short) 0xabcd; // 3.x only
|
||||
static final short ENDPOINT_BLOBDB = (short) 45531; // 3.x only
|
||||
static final short ENDPOINT_PUTBYTES = (short) 48879;
|
||||
|
||||
|
@ -1103,6 +1105,20 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
}
|
||||
|
||||
public byte[] encodeSetMusicState(byte state, int position, int playRate, byte shuffle, byte repeat) {
|
||||
byte playState;
|
||||
|
||||
switch (state) {
|
||||
case MusicStateSpec.STATE_PLAYING:
|
||||
playState = MUSICCONTROL_STATE_PLAYING;
|
||||
break;
|
||||
case MusicStateSpec.STATE_PAUSED:
|
||||
playState = MUSICCONTROL_STATE_PAUSED;
|
||||
break;
|
||||
default:
|
||||
playState = MUSICCONTROL_STATE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
int length = LENGTH_PREFIX + 12;
|
||||
// Encode Prefix
|
||||
ByteBuffer buf = ByteBuffer.allocate(length);
|
||||
|
@ -1112,8 +1128,8 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
|
||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
buf.put(MUSICCONTROL_SETPLAYSTATE);
|
||||
buf.put(state);
|
||||
buf.putInt(position);
|
||||
buf.put(playState);
|
||||
buf.putInt(position * 1000);
|
||||
buf.putInt(playRate);
|
||||
buf.put(shuffle);
|
||||
buf.put(repeat);
|
||||
|
@ -1127,7 +1143,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
if (duration == 0) {
|
||||
return encodeMessage(ENDPOINT_MUSICCONTROL, MUSICCONTROL_SETMUSICINFO, 0, parts);
|
||||
} else {
|
||||
byte[] stateMessage = encodeSetMusicState(MUSICCONTROL_STATE_PLAYING, 0, 100, (byte) 1, (byte) 1);
|
||||
// Calculate length first
|
||||
int length = LENGTH_PREFIX + 9;
|
||||
if (parts != null) {
|
||||
|
@ -1141,7 +1156,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
}
|
||||
|
||||
// Encode Prefix
|
||||
ByteBuffer buf = ByteBuffer.allocate(length + stateMessage.length);
|
||||
ByteBuffer buf = ByteBuffer.allocate(length);
|
||||
buf.order(ByteOrder.BIG_ENDIAN);
|
||||
buf.putShort((short) (length - LENGTH_PREFIX));
|
||||
buf.putShort(ENDPOINT_MUSICCONTROL);
|
||||
|
@ -1165,8 +1180,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
buf.putShort((short) (trackCount & 0xffff));
|
||||
buf.putShort((short) (trackNr & 0xffff));
|
||||
|
||||
buf.put(stateMessage);
|
||||
|
||||
return buf.array();
|
||||
}
|
||||
}
|
||||
|
@ -1281,6 +1294,23 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
return encodeSimpleMessage(ENDPOINT_SCREENSHOT, SCREENSHOT_TAKE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeAppReorder(UUID[] uuids) {
|
||||
int length = 2 + uuids.length * LENGTH_UUID;
|
||||
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + length);
|
||||
buf.order(ByteOrder.BIG_ENDIAN);
|
||||
buf.putShort((short) length);
|
||||
buf.putShort(ENDPOINT_APPREORDER);
|
||||
buf.put((byte) 0x01);
|
||||
buf.put((byte) uuids.length);
|
||||
for (UUID uuid : uuids) {
|
||||
buf.putLong(uuid.getMostSignificantBits());
|
||||
buf.putLong(uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
/* pebble specific install methods */
|
||||
public byte[] encodeUploadStart(byte type, int app_id, int size, String filename) {
|
||||
short length;
|
||||
|
@ -1936,6 +1966,16 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
return sendBytes;
|
||||
}
|
||||
|
||||
private GBDeviceEvent decodeAppReorder(ByteBuffer buf) {
|
||||
byte status = buf.get();
|
||||
if (status == 1) {
|
||||
LOG.info("app reordering successful");
|
||||
} else {
|
||||
LOG.info("app reordering returned status " + status);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
|
||||
ByteBuffer buf = ByteBuffer.wrap(responseData);
|
||||
|
@ -2186,6 +2226,8 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
case ENDPOINT_BLOBDB:
|
||||
devEvts = new GBDeviceEvent[]{decodeBlobDb(buf)};
|
||||
break;
|
||||
case ENDPOINT_APPREORDER:
|
||||
devEvts = new GBDeviceEvent[]{decodeAppReorder(buf)};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
|
||||
|
@ -108,6 +109,13 @@ public class PebbleSupport extends AbstractSerialDeviceSupport {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicState(MusicStateSpec musicStateSpec) {
|
||||
if (reconnect()) {
|
||||
super.onSetMusicState(musicStateSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(MusicSpec musicSpec) {
|
||||
if (reconnect()) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
|
||||
|
||||
|
@ -123,6 +124,12 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
|
|||
sendToDevice(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicState(MusicStateSpec stateSpec) {
|
||||
byte[] bytes = gbDeviceProtocol.encodeSetMusicState(stateSpec.state, stateSpec.position, stateSpec.playRate, stateSpec.shuffle, stateSpec.repeat);
|
||||
sendToDevice(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(MusicSpec musicSpec) {
|
||||
byte[] bytes = gbDeviceProtocol.encodeSetMusicInfo(musicSpec.artist, musicSpec.album, musicSpec.track, musicSpec.duration, musicSpec.trackCount, musicSpec.trackNr);
|
||||
|
@ -147,6 +154,12 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
|
|||
sendToDevice(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppReorder(UUID[] uuids) {
|
||||
byte[] bytes = gbDeviceProtocol.encodeAppReorder(uuids);
|
||||
sendToDevice(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFetchActivityData() {
|
||||
byte[] bytes = gbDeviceProtocol.encodeSynchronizeActivityData();
|
||||
|
|
|
@ -31,6 +31,10 @@ public abstract class GBDeviceProtocol {
|
|||
return null;
|
||||
}
|
||||
|
||||
public byte[] encodeSetMusicState(byte state, int position, int playRate, byte shuffle, byte repeat) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] encodeFirmwareVersionReq() {
|
||||
return null;
|
||||
}
|
||||
|
@ -51,6 +55,10 @@ public abstract class GBDeviceProtocol {
|
|||
return null;
|
||||
}
|
||||
|
||||
public byte[] encodeAppReorder(UUID[] uuids) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] encodeSynchronizeActivityData() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -18,4 +18,8 @@
|
|||
<item
|
||||
android:id="@+id/appmanager_app_configure"
|
||||
android:title="@string/app_configure"/>
|
||||
<item
|
||||
android:id="@+id/appmanager_app_move_to_top"
|
||||
android:title="@string/app_move_to_top"/>
|
||||
|
||||
</menu>
|
|
@ -238,5 +238,4 @@
|
|||
<string name="updatefirmwareoperation_firmware_not_sent">Firmware non inviato</string>
|
||||
<string name="charts_legend_heartrate">Battito cardiaco</string>
|
||||
<string name="live_activity_heart_rate">Battito cardiaco</string>
|
||||
<string name="miband_prefs_device_time_offset_hours">Offset orologio del dispositivo in ore (per l\'identificazione del sonno dei lavoratori a turni)</string>
|
||||
</resources>
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<string name="pref_title_theme">テーマ</string>
|
||||
<string name="pref_theme_light">ライト</string>
|
||||
<string name="pref_theme_dark">ダーク</string>
|
||||
<string name="pref_title_language">言語</string>
|
||||
<string name="pref_header_notifications">通知</string>
|
||||
<string name="pref_title_notifications_repetitions">繰り返し</string>
|
||||
<string name="pref_title_notifications_call">電話通知</string>
|
||||
|
@ -57,7 +58,11 @@
|
|||
<string name="pref_header_development">開発者用設定</string>
|
||||
<string name="pref_title_development_miaddr">Mi Bandのアドレス</string>
|
||||
<string name="pref_title_pebble_settings">Pebbleの設定</string>
|
||||
<string name="pref_header_activitytrackers">アクティビティ トラッカー</string>
|
||||
<string name="pref_title_pebble_activitytracker">お好みのアクティビティ トラッカー</string>
|
||||
<string name="pref_title_pebble_sync_health">Pebble Health 同期</string>
|
||||
<string name="pref_title_pebble_sync_misfit">Misfit 同期</string>
|
||||
<string name="pref_title_pebble_sync_morpheuz">Morpheuz 同期</string>
|
||||
<string name="pref_title_enable_pebblekit">第三者のアンドロイドアップにアクセス権利を与える</string>
|
||||
<string name="pref_summary_enable_pebblekit">PebbleKitを使用してAndroidアプリ用の実験的なサポートを有効にします</string>
|
||||
<string name="pref_title_sunrise_sunset">日の出と日の入り</string>
|
||||
|
@ -214,6 +219,7 @@
|
|||
<string name="fwinstaller_firmware_not_compatible_to_device">このファームウェアは、デバイスと互換性がありません</string>
|
||||
<string name="miband_prefs_reserve_alarm_calendar">今後のイベントのために予約するアラーム</string>
|
||||
<string name="miband_prefs_hr_sleep_detection">睡眠の検出を改善するために心拍センサーを使用する</string>
|
||||
<string name="miband_prefs_device_time_offset_hours">デバイスの時刻オフセット時間 (交代勤務の睡眠検知用)</string>
|
||||
<string name="waiting_for_reconnect">再接続の待機中</string>
|
||||
<string name="appmananger_app_reinstall">再インストール</string>
|
||||
<string name="activity_prefs_about_you">あなたについて</string>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<string name="pref_title_theme">Тема</string>
|
||||
<string name="pref_theme_light">Світла</string>
|
||||
<string name="pref_theme_dark">Темна</string>
|
||||
<string name="pref_title_language">Мова</string>
|
||||
<string name="pref_header_notifications">Сповіщення</string>
|
||||
<string name="pref_title_notifications_repetitions">Повтори</string>
|
||||
<string name="pref_title_notifications_call">Виклики</string>
|
||||
|
@ -203,4 +204,6 @@
|
|||
<string name="appmanager_health_deactivate">Вимкнути</string>
|
||||
<string name="app_configure">Конфігурація</string>
|
||||
<string name="add_widget">Додати віджет</string>
|
||||
<string name="device_hw">Пристрій: %1$s</string>
|
||||
<string name="device_fw">ПЗ: %1$s</string>
|
||||
</resources>
|
||||
|
|
|
@ -74,7 +74,13 @@
|
|||
<string name="pref_title_development_miaddr">Mi Band address</string>
|
||||
|
||||
<string name="pref_title_pebble_settings">Pebble Settings</string>
|
||||
|
||||
<string name="pref_header_activitytrackers">Activity Trackers</string>
|
||||
<string name="pref_title_pebble_activitytracker">Preferred Activitytracker</string>
|
||||
<string name="pref_title_pebble_sync_health">Sync Pebble Health</string>
|
||||
<string name="pref_title_pebble_sync_misfit">Sync Misfit</string>
|
||||
<string name="pref_title_pebble_sync_morpheuz">Sync Morpheuz</string>
|
||||
|
||||
<string name="pref_title_enable_pebblekit">Allow 3rd Party Android App Access</string>
|
||||
<string name="pref_summary_enable_pebblekit">Enable experimental support for Android Apps using PebbleKit</string>
|
||||
|
||||
|
@ -251,9 +257,11 @@
|
|||
<string name="activity_prefs_weight_kg">Weight in kg</string>
|
||||
<string name="appmanager_health_activate">Activate</string>
|
||||
<string name="appmanager_health_deactivate">Deactivate</string>
|
||||
<string name="app_configure">Configure</string>
|
||||
<string name="app_move_to_top">Move to top</string>
|
||||
|
||||
<string name="authenticating">authenticating</string>
|
||||
<string name="authentication_required">authentication required</string>
|
||||
<string name="app_configure">Configure</string>
|
||||
|
||||
<string name="appwidget_text">Zzz</string>
|
||||
<string name="add_widget">Add widget</string>
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<changelog>
|
||||
<release version="0.10.1" versioncode="54">
|
||||
<change>Pebble: set extended music info by dissecting notifications on Android 5.0+</change>
|
||||
<change>Pebble: various other improvemnts to music playback</change>
|
||||
<change>Pebble: allow ignoring activity trackers indiviually (to keep the data on the pebble)</change>
|
||||
<change>Mi Band: support for shifting the device time by N hours (for people who sleep at daytime)</change>
|
||||
<change>Mi Band: initial and untested support for Mi Band 2</change>
|
||||
<change>Allow setting the application language</change>
|
||||
</release>
|
||||
<release version="0.10.0" versioncode="53">
|
||||
<change>Pebble: option to send sunrise and sunset events to timeline</change>
|
||||
<change>Pebble: fix problems with unknown app keys while configuring watchfaces</change>
|
||||
|
|
|
@ -215,17 +215,31 @@
|
|||
android:key="pebble_reconnect_attempts"
|
||||
android:maxLength="4"
|
||||
android:title="@string/pref_title_pebble_reconnect_attempts" />
|
||||
<CheckBoxPreference
|
||||
android:title="@string/pref_title_sunrise_sunset"
|
||||
android:summary="@string/pref_summary_sunrise_sunset"
|
||||
android:key="send_sunrise_sunset" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/pref_header_activitytrackers">
|
||||
<ListPreference
|
||||
android:defaultValue="4"
|
||||
android:entries="@array/pebble_activitytracker"
|
||||
android:entryValues="@array/pebble_activitytracker_values"
|
||||
android:key="pebble_activitytracker"
|
||||
android:title="@string/pref_title_pebble_activitytracker"
|
||||
android:summary="%s" />
|
||||
android:summary="%s"
|
||||
android:title="@string/pref_title_pebble_activitytracker" />
|
||||
<CheckBoxPreference
|
||||
android:title="@string/pref_title_sunrise_sunset"
|
||||
android:summary="@string/pref_summary_sunrise_sunset"
|
||||
android:key="send_sunrise_sunset" />
|
||||
android:defaultValue="true"
|
||||
android:key="pebble_sync_health"
|
||||
android:title="@string/pref_title_pebble_sync_health" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="pebble_sync_misfit"
|
||||
android:title="@string/pref_title_pebble_sync_misfit" />>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="pebble_sync_morpheuz"
|
||||
android:title="@string/pref_title_pebble_sync_morpheuz" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/pref_header_location">
|
||||
|
|
|
@ -12,6 +12,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
|
||||
public class TestDeviceSupport extends AbstractDeviceSupport {
|
||||
|
@ -66,6 +67,11 @@ public class TestDeviceSupport extends AbstractDeviceSupport {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicState(MusicStateSpec stateSpec) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(MusicSpec musicSpec) {
|
||||
|
||||
|
@ -96,6 +102,11 @@ public class TestDeviceSupport extends AbstractDeviceSupport {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppReorder(UUID[] uuids) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFetchActivityData() {
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.1.0'
|
||||
classpath 'com.android.tools.build:gradle:2.1.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
|
Loading…
Reference in New Issue