mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-26 16:41:43 +01:00
Merge branch 'master' into live-activity-data
This commit is contained in:
commit
5f993c0049
@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -215,6 +216,12 @@ public class DebugActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void testNotification() {
|
private void testNotification() {
|
||||||
|
Intent notificationIntent = new Intent(getApplicationContext(), DebugActivity.class);
|
||||||
|
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0,
|
||||||
|
notificationIntent, 0);
|
||||||
|
|
||||||
NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this);
|
NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this);
|
||||||
ncomp.setContentTitle(getString(R.string.test_notification));
|
ncomp.setContentTitle(getString(R.string.test_notification));
|
||||||
@ -222,6 +229,7 @@ public class DebugActivity extends Activity {
|
|||||||
ncomp.setTicker(getString(R.string.this_is_a_test_notification_from_gadgetbridge));
|
ncomp.setTicker(getString(R.string.this_is_a_test_notification_from_gadgetbridge));
|
||||||
ncomp.setSmallIcon(R.drawable.ic_notification);
|
ncomp.setSmallIcon(R.drawable.ic_notification);
|
||||||
ncomp.setAutoCancel(true);
|
ncomp.setAutoCancel(true);
|
||||||
|
ncomp.setContentIntent(pendingIntent);
|
||||||
nManager.notify((int) System.currentTimeMillis(), ncomp.build());
|
nManager.notify((int) System.currentTimeMillis(), ncomp.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.adapter;
|
package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -61,9 +63,15 @@ public class GBDeviceAdapter extends ArrayAdapter<GBDevice> {
|
|||||||
if (batteryLevel != GBDevice.BATTERY_UNKNOWN) {
|
if (batteryLevel != GBDevice.BATTERY_UNKNOWN) {
|
||||||
batteryStatusLabel.setText("BAT: " + device.getBatteryLevel() + "%");
|
batteryStatusLabel.setText("BAT: " + device.getBatteryLevel() + "%");
|
||||||
BatteryState batteryState = device.getBatteryState();
|
BatteryState batteryState = device.getBatteryState();
|
||||||
if (BatteryState.BATTERY_CHARGING.equals(batteryState) ||
|
if (BatteryState.BATTERY_LOW.equals(batteryState)) {
|
||||||
BatteryState.BATTERY_CHARGING_FULL.equals(batteryState)) {
|
batteryStatusLabel.setTextColor(Color.RED);
|
||||||
batteryStatusLabel.append(" CHG");
|
} else {
|
||||||
|
batteryStatusLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.secondarytext));
|
||||||
|
|
||||||
|
if (BatteryState.BATTERY_CHARGING.equals(batteryState) ||
|
||||||
|
BatteryState.BATTERY_CHARGING_FULL.equals(batteryState)) {
|
||||||
|
batteryStatusLabel.append(" CHG");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
batteryStatusLabel.setText("");
|
batteryStatusLabel.setText("");
|
||||||
|
@ -129,6 +129,7 @@ public class NotificationListener extends NotificationListenerService {
|
|||||||
source.equals("com.android.systemui") ||
|
source.equals("com.android.systemui") ||
|
||||||
source.equals("com.android.dialer") ||
|
source.equals("com.android.dialer") ||
|
||||||
source.equals("com.android.mms") ||
|
source.equals("com.android.mms") ||
|
||||||
|
source.equals("com.moez.QKSMS") ||
|
||||||
source.equals("com.cyanogenmod.eleven") ||
|
source.equals("com.cyanogenmod.eleven") ||
|
||||||
source.equals("com.fsck.k9")) {
|
source.equals("com.fsck.k9")) {
|
||||||
return;
|
return;
|
||||||
|
@ -9,7 +9,11 @@ import android.preference.PreferenceManager;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
|
||||||
|
|
||||||
public class TimeChangeReceiver extends BroadcastReceiver {
|
public class TimeChangeReceiver extends BroadcastReceiver {
|
||||||
@ -22,7 +26,8 @@ public class TimeChangeReceiver extends BroadcastReceiver {
|
|||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
|
|
||||||
if (sharedPrefs.getBoolean("datetime_synconconnect", true) && (action.equals(Intent.ACTION_TIME_CHANGED) || action.equals(Intent.ACTION_TIMEZONE_CHANGED))) {
|
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");
|
Date newTime = GregorianCalendar.getInstance().getTime();
|
||||||
|
LOG.info("Time or Timezone changed, syncing with device: " + DateTimeUtils.formatDate(newTime) + " (" + newTime.toGMTString() + "), " + intent.getAction());
|
||||||
GBApplication.deviceService().onSetTime();
|
GBApplication.deviceService().onSetTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,10 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle;
|
|||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bluedroid implementation only allows performing one GATT request at a time.
|
* The Bluedroid implementation only allows performing one GATT request at a time.
|
||||||
* As they are asynchronous anyway, we encapsulate every GATT request (read and write)
|
* As they are asynchronous anyway, we encapsulate every GATT request (read and write)
|
||||||
@ -50,7 +51,7 @@ public abstract class BtLEAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String getCreationTime() {
|
protected String getCreationTime() {
|
||||||
return DateFormat.getTimeInstance().format(new Date(creationTimestamp));
|
return DateTimeUtils.formatDateTime(new Date(creationTimestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -432,22 +432,31 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] encodeExtensibleNotification(int id, int timestamp, String title, String subtitle, String body, byte type, boolean hasHandle) {
|
private static byte[] encodeExtensibleNotification(int id, int timestamp, String title, String subtitle, String body, byte type, boolean hasHandle) {
|
||||||
|
final short ACTION_LENGTH_MIN = 10;
|
||||||
|
|
||||||
String[] parts = {title, subtitle, body};
|
String[] parts = {title, subtitle, body};
|
||||||
|
|
||||||
// Calculate length first
|
// Calculate length first
|
||||||
String actionstring;
|
byte actions_count;
|
||||||
byte action_id;
|
short actions_length;
|
||||||
|
String dismiss_string;
|
||||||
|
String open_string = "Open on phone";
|
||||||
|
byte dismiss_action_id;
|
||||||
if (hasHandle) {
|
if (hasHandle) {
|
||||||
actionstring = "dismiss";
|
actions_count = 2;
|
||||||
action_id = 0x02;
|
dismiss_string = "Dismiss";
|
||||||
|
dismiss_action_id = 0x02;
|
||||||
|
actions_length = (short) (ACTION_LENGTH_MIN * actions_count + dismiss_string.length() + open_string.length());
|
||||||
} else {
|
} else {
|
||||||
actionstring = "dismiss all";
|
actions_count = 1;
|
||||||
action_id = 0x03;
|
dismiss_string = "Dismiss all";
|
||||||
|
dismiss_action_id = 0x03;
|
||||||
|
actions_length = (short) (ACTION_LENGTH_MIN * actions_count + dismiss_string.length() + open_string.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
byte attributes_count = 0;
|
byte attributes_count = 0;
|
||||||
|
|
||||||
int length = 21 + 10 + actionstring.length(); //+ 19
|
int length = 21 + 10 + actions_length;
|
||||||
if (parts != null) {
|
if (parts != null) {
|
||||||
for (String s : parts) {
|
for (String s : parts) {
|
||||||
if (s == null || s.equals("")) {
|
if (s == null || s.equals("")) {
|
||||||
@ -474,8 +483,8 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
buf.putInt(0x00000000); // ANCS id
|
buf.putInt(0x00000000); // ANCS id
|
||||||
buf.putInt(timestamp);
|
buf.putInt(timestamp);
|
||||||
buf.put((byte) 0x01); // layout - ?
|
buf.put((byte) 0x01); // layout - ?
|
||||||
buf.put(attributes_count); // length attributes
|
buf.put(attributes_count);
|
||||||
buf.put((byte) 1); // len actions
|
buf.put(actions_count);
|
||||||
|
|
||||||
byte attribute_id = 0;
|
byte attribute_id = 0;
|
||||||
// Encode Pascal-Style Strings
|
// Encode Pascal-Style Strings
|
||||||
@ -494,23 +503,24 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACTION
|
|
||||||
buf.put(action_id);
|
|
||||||
buf.put((byte) 0x04); // dismiss action
|
|
||||||
buf.put((byte) 0x01); // number attributes
|
|
||||||
buf.put((byte) 0x01); // attribute id (title)
|
|
||||||
buf.putShort((short) actionstring.length());
|
|
||||||
buf.put(actionstring.getBytes());
|
|
||||||
|
|
||||||
/*
|
// dismiss action
|
||||||
buf.put((byte) 0x01); // id
|
buf.put(dismiss_action_id);
|
||||||
buf.put((byte) 0x02); // generic action
|
buf.put((byte) 0x04); // dismiss
|
||||||
buf.put((byte) 0x01); // number attributes
|
buf.put((byte) 0x01); // number attributes
|
||||||
buf.put((byte) 0x01); // attribute id (title)
|
buf.put((byte) 0x01); // attribute id (title)
|
||||||
actionstring = "open on phone";
|
buf.putShort((short) dismiss_string.length());
|
||||||
buf.putShort((short) actionstring.length());
|
buf.put(dismiss_string.getBytes());
|
||||||
buf.put(actionstring.getBytes());
|
|
||||||
*/
|
// open action
|
||||||
|
if (hasHandle) {
|
||||||
|
buf.put((byte) 0x01);
|
||||||
|
buf.put((byte) 0x02); // dissmiss - FIXME: find out how to answer to 2.x generic actions
|
||||||
|
buf.put((byte) 0x01); // number attributes
|
||||||
|
buf.put((byte) 0x01); // attribute id (title)
|
||||||
|
buf.putShort((short) open_string.length());
|
||||||
|
buf.put(open_string.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
return buf.array();
|
return buf.array();
|
||||||
}
|
}
|
||||||
@ -547,6 +557,9 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, byte type, boolean hasHandle) {
|
private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, byte type, boolean hasHandle) {
|
||||||
|
final short NOTIFICATION_PIN_LENGTH = 46;
|
||||||
|
final short ACTION_LENGTH_MIN = 10;
|
||||||
|
|
||||||
String[] parts = {title, subtitle, body};
|
String[] parts = {title, subtitle, body};
|
||||||
|
|
||||||
int icon_id = 0x80000000 | 1;
|
int icon_id = 0x80000000 | 1;
|
||||||
@ -558,23 +571,24 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
icon_id = 0x80000000 | 45;
|
icon_id = 0x80000000 | 45;
|
||||||
}
|
}
|
||||||
// Calculate length first
|
// Calculate length first
|
||||||
|
byte actions_count;
|
||||||
String actionstring;
|
short actions_length;
|
||||||
byte action_id;
|
String dismiss_string;
|
||||||
|
String open_string = "Open on phone";
|
||||||
|
byte dismiss_action_id;
|
||||||
if (hasHandle) {
|
if (hasHandle) {
|
||||||
actionstring = "dismiss";
|
actions_count = 2;
|
||||||
action_id = 0x02;
|
dismiss_string = "Dismiss";
|
||||||
|
dismiss_action_id = 0x02;
|
||||||
|
actions_length = (short) (ACTION_LENGTH_MIN * actions_count + dismiss_string.length() + open_string.length());
|
||||||
} else {
|
} else {
|
||||||
actionstring = "dismiss all";
|
actions_count = 1;
|
||||||
action_id = 0x03;
|
dismiss_string = "Dismiss all";
|
||||||
|
dismiss_action_id = 0x03;
|
||||||
|
actions_length = (short) (ACTION_LENGTH_MIN * actions_count + dismiss_string.length() + open_string.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
final short NOTIFICATION_PIN_LENGTH = 46;
|
|
||||||
short actions_length = (short) (10 + actionstring.length());
|
|
||||||
|
|
||||||
byte attributes_count = 1; // icon
|
byte attributes_count = 1; // icon
|
||||||
byte actions_count = 1; // dismiss
|
|
||||||
|
|
||||||
short attributes_length = (short) (7 + actions_length); // icon
|
short attributes_length = (short) (7 + actions_length); // icon
|
||||||
if (parts != null) {
|
if (parts != null) {
|
||||||
for (String s : parts) {
|
for (String s : parts) {
|
||||||
@ -599,7 +613,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
buf.putLong(uuid.getMostSignificantBits());
|
buf.putLong(uuid.getMostSignificantBits());
|
||||||
buf.putInt((int) (uuid.getLeastSignificantBits() >>> 32));
|
buf.putInt((int) (uuid.getLeastSignificantBits() >>> 32));
|
||||||
buf.putInt(id);
|
buf.putInt(id);
|
||||||
LOG.info("id " + id);
|
|
||||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
buf.putInt(timestamp); // 32-bit timestamp
|
buf.putInt(timestamp); // 32-bit timestamp
|
||||||
buf.putShort((short) 0); // duration
|
buf.putShort((short) 0); // duration
|
||||||
@ -631,15 +644,23 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
buf.putShort((short) 4); // length of int
|
buf.putShort((short) 4); // length of int
|
||||||
buf.putInt(icon_id);
|
buf.putInt(icon_id);
|
||||||
|
|
||||||
// ACTION
|
// dismiss action
|
||||||
buf.put(action_id);
|
buf.put(dismiss_action_id);
|
||||||
buf.put((byte) 0x02); // generic action, dismiss did not do anything
|
buf.put((byte) 0x02); // generic action, dismiss did not do anything
|
||||||
buf.put((byte) 0x01); // number attributes
|
buf.put((byte) 0x01); // number attributes
|
||||||
buf.put((byte) 0x01); // attribute id (title)
|
buf.put((byte) 0x01); // attribute id (title)
|
||||||
|
buf.putShort((short) dismiss_string.length());
|
||||||
|
buf.put(dismiss_string.getBytes());
|
||||||
|
|
||||||
buf.putShort((short) actionstring.length());
|
// open action
|
||||||
buf.put(actionstring.getBytes());
|
if (hasHandle) {
|
||||||
|
buf.put((byte) 0x01);
|
||||||
|
buf.put((byte) 0x02); // generic action
|
||||||
|
buf.put((byte) 0x01); // number attributes
|
||||||
|
buf.put((byte) 0x01); // attribute id (title)
|
||||||
|
buf.putShort((short) open_string.length());
|
||||||
|
buf.put(open_string.getBytes());
|
||||||
|
}
|
||||||
return encodeBlobdb(UUID.randomUUID(), BLOBDB_INSERT, BLOBDB_NOTIFICATION, buf.array());
|
return encodeBlobdb(UUID.randomUUID(), BLOBDB_INSERT, BLOBDB_NOTIFICATION, buf.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1151,7 +1172,6 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
long uuid_high = buf.getLong();
|
long uuid_high = buf.getLong();
|
||||||
long uuid_low = buf.getLong();
|
long uuid_low = buf.getLong();
|
||||||
int id = (int) (uuid_low & 0xffffffff);
|
int id = (int) (uuid_low & 0xffffffff);
|
||||||
LOG.info("id " + id);
|
|
||||||
byte action = buf.get();
|
byte action = buf.get();
|
||||||
if (action >= 0x01 && action <= 0x03) {
|
if (action >= 0x01 && action <= 0x03) {
|
||||||
GBDeviceEventNotificationControl dismissNotification = new GBDeviceEventNotificationControl();
|
GBDeviceEventNotificationControl dismissNotification = new GBDeviceEventNotificationControl();
|
||||||
|
@ -12,6 +12,10 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
|
||||||
public class DateTimeUtils {
|
public class DateTimeUtils {
|
||||||
|
public static String formatDateTime(Date date) {
|
||||||
|
return DateUtils.formatDateTime(GBApplication.getContext(), date.getTime(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
public static String formatDate(Date date) {
|
public static String formatDate(Date date) {
|
||||||
return DateUtils.formatDateTime(GBApplication.getContext(), date.getTime(), DateUtils.FORMAT_SHOW_DATE);
|
return DateUtils.formatDateTime(GBApplication.getContext(), date.getTime(), DateUtils.FORMAT_SHOW_DATE);
|
||||||
// long dateMillis = date.getTime();
|
// long dateMillis = date.getTime();
|
||||||
|
Loading…
Reference in New Issue
Block a user