Refactoring

The notfification APIs now use NotificationSpec as their only parameter, which
contains all information (required and optional ones).
We no longer have separate methods and actions for SMS/EMAIL/GENERIC anymore.
The type of notification is important now, not how we received them technically.
live-activity-data
Andreas Shimokawa 2015-09-24 14:45:21 +02:00
parent e1ea8270ca
commit 1d41f2f8e4
63 changed files with 275 additions and 279 deletions

View File

@ -101,9 +101,10 @@ public class GBApplication extends Application {
* when that was not successful
* If acquiring was successful, callers must call #releaseDB when they
* are done (from the same thread that acquired the lock!
*
* @return the DBHandler
* @see #releaseDB()
* @throws GBException
* @see #releaseDB()
*/
public static DBHandler acquireDB() throws GBException {
try {
@ -118,6 +119,7 @@ public class GBApplication extends Application {
/**
* Releases the database lock.
*
* @throws IllegalMonitorStateException if the current thread is not owning the lock
* @see #acquireDB()
*/

View File

@ -4,12 +4,15 @@ public class GBException extends Exception {
public GBException(String message, Throwable cause) {
super(message, cause);
}
public GBException(String message) {
super(message);
}
public GBException(Throwable cause) {
super(cause);
}
public GBException() {
super();
}

View File

@ -1,13 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.support.v4.app.Fragment;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
/**
* Abstract base class for fragments. Provides hooks that are called when
* the fragment is made visible and invisible in the activity. also allows
* the fragment to define the title to be shown in the activity.
*
* @see AbstractGBFragmentActivity
*/
public abstract class AbstractGBFragment extends Fragment {
@ -25,6 +26,7 @@ public abstract class AbstractGBFragment extends Fragment {
/**
* Called when this fragment has been scrolled out of the activity.
*
* @see #isVisibleInActivity()
* @see #onMadeVisibleInActivity()
*/
@ -54,6 +56,7 @@ public abstract class AbstractGBFragment extends Fragment {
/**
* Internal
*
* @hide
*/
public void onMadeVisibleInActivityInternal() {

View File

@ -1,20 +1,15 @@
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.content.Context;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.util.AttributeSet;
import android.view.View;
/**
* A base activity that supports paging through fragments by swiping.
* Subclasses will have to add a ViewPager to their layout and add something
* like this to hook it to the fragments:
*
* <p/>
* <pre>
* // Set up the ViewPager with the sections adapter.
* ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
@ -50,6 +45,7 @@ public abstract class AbstractGBFragmentActivity extends FragmentActivity {
/**
* Creates a PagerAdapter that will create the fragments to be used with this
* activity. The fragments should typically extend AbstractGBFragment
*
* @param fragmentManager
* @return
*/

View File

@ -8,9 +8,9 @@ import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.TimePicker;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
public class AlarmDetails extends Activity {

View File

@ -12,10 +12,9 @@ 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;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ALARMS;

View File

@ -37,7 +37,6 @@ import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;

View File

@ -26,6 +26,8 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -70,17 +72,25 @@ public class DebugActivity extends Activity {
sendSMSButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GBApplication.deviceService().onSMS(getResources().getText(R.string.app_name).toString(), editContent.getText().toString());
NotificationSpec notificationSpec = new NotificationSpec();
notificationSpec.sender = getResources().getText(R.string.app_name).toString();
notificationSpec.body = editContent.getText().toString();
notificationSpec.type = NotificationType.SMS;
notificationSpec.id = -1;
GBApplication.deviceService().onNotification(notificationSpec);
}
});
sendEmailButton = (Button) findViewById(R.id.sendEmailButton);
sendEmailButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GBApplication.deviceService().onEmail(
getResources().getText(R.string.app_name).toString(),
getResources().getText(R.string.test).toString(),
editContent.getText().toString());
NotificationSpec notificationSpec = new NotificationSpec();
notificationSpec.sender = getResources().getText(R.string.app_name).toString();
notificationSpec.subject = editContent.getText().toString();
notificationSpec.body = editContent.getText().toString();
notificationSpec.type = NotificationType.EMAIL;
notificationSpec.id = -1;
GBApplication.deviceService().onNotification(notificationSpec);
}
});

View File

@ -24,13 +24,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.DeviceCandidateAdapter;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.DeviceCandidateAdapter;
public class DiscoveryActivity extends Activity implements AdapterView.OnItemClickListener {
private static final Logger LOG = LoggerFactory.getLogger(DiscoveryActivity.class);

View File

@ -12,7 +12,6 @@ import android.support.v4.content.LocalBroadcastManager;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

View File

@ -4,6 +4,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails;
public interface InstallActivity {
void setInfoText(String text);
void setInstallEnabled(boolean enable);
void clearInstallItems();

View File

@ -12,9 +12,12 @@ public interface ChartsHost {
GBDevice getDevice();
void setStartDate(Date startDate);
void setEndDate(Date endDate);
Date getStartDate();
Date getEndDate();
void setDateInfo(String dateInfo);
}

View File

@ -10,10 +10,10 @@ import android.widget.TextView;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class DeviceCandidateAdapter extends ArrayAdapter<GBDeviceCandidate> {

View File

@ -15,9 +15,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;

View File

@ -13,8 +13,8 @@ import android.widget.TextView;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
public class GBDeviceAdapter extends ArrayAdapter<GBDevice> {

View File

@ -10,8 +10,8 @@ import android.widget.TextView;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
public class GBDeviceAppAdapter extends ArrayAdapter<GBDeviceApp> {

View File

@ -12,13 +12,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.impl.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.impl.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.DATABASE_NAME;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_INTENSITY;
@ -179,7 +179,7 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
}
ArrayList<ActivitySample> samples = new ArrayList<ActivitySample>();
final String where = "(provider=" + provider.getID() + " and timestamp>=" + timestamp_from + " and timestamp<=" + timestamp_to + getWhereClauseFor(activityTypes, provider) + ")";
LOG.info("Activity query where: "+ where);
LOG.info("Activity query where: " + where);
final String order = "timestamp";
try (SQLiteDatabase db = this.getReadableDatabase()) {
try (Cursor cursor = db.query(TABLE_GBACTIVITYSAMPLES, null, where, null, null, null, order)) {

View File

@ -4,9 +4,9 @@ import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public abstract class DBAccess extends AsyncTask {
private final String mTask;

View File

@ -6,8 +6,8 @@ import android.database.sqlite.SQLiteOpenHelper;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
public interface DBHandler {
public SQLiteOpenHelper getHelper();

View File

@ -6,9 +6,9 @@ import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
/**
* Specifies all events that GadgetBridge intends to send to the gadget device.
@ -16,11 +16,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
* Implementations need to send/encode event to the connected device.
*/
public interface EventHandler {
void onSMS(String from, String body);
void onEmail(String from, String subject, String body);
void onGenericNotification(String title, String details, int handle, NotificationKind notificationKind);
void onNotification(NotificationSpec notificationSpec);
void onSetTime();

View File

@ -4,11 +4,11 @@ import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class UnknownDeviceCoordinator implements DeviceCoordinator {
private final UnknownSampleProvider sampleProvider;

View File

@ -9,18 +9,16 @@ import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class MiBandCoordinator implements DeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(MiBandCoordinator.class);

View File

@ -13,6 +13,7 @@ public class MiBandDateConverter {
/**
* uses the standard algorithm to convert bytes received from the MiBand to a Calendar object
*
* @param value
* @return
*/
@ -25,6 +26,7 @@ public class MiBandDateConverter {
/**
* uses the standard algorithm to convert bytes received from the MiBand to a Calendar object
*
* @param value
* @return
*/
@ -46,6 +48,7 @@ public class MiBandDateConverter {
/**
* uses the standard algorithm to convert a Calendar object to a byte array to send to MiBand
*
* @param timestamp
* @return
*/

View File

@ -12,7 +12,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
public class MiBandFWHelper {
@ -48,7 +47,7 @@ public class MiBandFWHelper {
throw new IOException("Firmware has a filename that looks like a Pebble app/firmware.");
}
try (InputStream in = new BufferedInputStream(cr.openInputStream(uri))){
try (InputStream in = new BufferedInputStream(cr.openInputStream(uri))) {
this.fw = FileUtils.readAll(in, 1024 * 1024); // 1 MB
if (fw.length <= firmwareVersionMajor || fw[firmwareVersionMajor] != 1) {
throw new IOException("Firmware major version should be 1, probably this isn't a MiBand firmware.");

View File

@ -13,12 +13,11 @@ import android.widget.TextView;
import android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.activities.DiscoveryActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DiscoveryActivity;
public class MiBandPairingActivity extends Activity {

View File

@ -5,9 +5,9 @@ import android.os.Bundle;
import android.preference.Preference;
import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_GENERIC;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_INCOMING_CALL;
@ -15,8 +15,8 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.OR
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_PEBBLEMSG;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_SMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ADDRESS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_FITNESS_GOAL;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_DONT_ACK_TRANSFER;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_FITNESS_GOAL;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_WEARSIDE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_USER_ALIAS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_USER_GENDER;

View File

@ -1,7 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.devices.miband;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
public class MiBandSampleProvider implements SampleProvider {
public static final byte TYPE_DEEP_SLEEP = 5;

View File

@ -179,12 +179,12 @@ public class MiBandService {
*/
/* MODES: probably related to the sample data structure
*/
*/
public static final byte MODE_REGULAR_DATA_LEN_BYTE = 0x0;
public static final byte MODE_REGULAR_DATA_LEN_BYTE = 0x0;
// was MODE_REGULAR_DATA_LEN_MINITE
public static final byte MODE_REGULAR_DATA_LEN_MINUTE = 0x1;
public static final byte MODE_REGULAR_DATA_LEN_MINUTE = 0x1;
/* PROFILE: unknown

View File

@ -1,7 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.devices.pebble;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
public class MorpheuzSampleProvider implements SampleProvider {
// raw types

View File

@ -10,7 +10,6 @@ import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
public class BluetoothStateChangeReceiver extends BroadcastReceiver {
@Override

View File

@ -13,6 +13,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
public class K9Receiver extends BroadcastReceiver {
@ -42,9 +44,9 @@ public class K9Receiver extends BroadcastReceiver {
"uri"
};
String sender = "";
String subject = "";
String preview = "";
NotificationSpec notificationSpec = new NotificationSpec();
notificationSpec.id = -1;
notificationSpec.type = NotificationType.EMAIL;
/*
* there seems to be no way to specify the the uri in the where clause.
@ -57,14 +59,14 @@ public class K9Receiver extends BroadcastReceiver {
do {
String uri = c.getString(c.getColumnIndex("uri"));
if (uri.equals(uriWanted)) {
sender = c.getString(c.getColumnIndex("senderAddress"));
subject = c.getString(c.getColumnIndex("subject"));
preview = c.getString(c.getColumnIndex("preview"));
notificationSpec.sender = c.getString(c.getColumnIndex("senderAddress"));
notificationSpec.subject = c.getString(c.getColumnIndex("subject"));
notificationSpec.body = c.getString(c.getColumnIndex("preview"));
break;
}
} while (c.moveToNext());
c.close();
GBApplication.deviceService().onEmail(sender, subject, preview);
GBApplication.deviceService().onNotification(notificationSpec);
}
}

View File

@ -3,8 +3,6 @@ package nodomain.freeyourgadget.gadgetbridge.externalevents;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -22,7 +22,8 @@ import org.slf4j.LoggerFactory;
import java.util.HashSet;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
public class NotificationListener extends NotificationListenerService {
@ -159,47 +160,45 @@ public class NotificationListener extends NotificationListenerService {
}
// Set application icons for generic notifications
NotificationKind notificationKind;
NotificationSpec notificationSpec = new NotificationSpec();
switch (source) {
case "org.mariotaku.twidere":
case "com.twitter.android":
case "org.andstatus.app":
case "org.mustard.android":
notificationKind = NotificationKind.TWITTER;
notificationSpec.type = NotificationType.TWITTER;
break;
case "com.fsck.k9":
case "com.android.email":
notificationKind = NotificationKind.EMAIL;
notificationSpec.type = NotificationType.EMAIL;
break;
case "com.moez.QKSMS":
notificationKind = NotificationKind.SMS;
notificationSpec.type = NotificationType.SMS;
break;
case "eu.siacs.conversations":
notificationKind = NotificationKind.CHAT;
notificationSpec.type = NotificationType.CHAT;
break;
case "org.indywidualni.fblite":
notificationKind = NotificationKind.FACEBOOK;
notificationSpec.type = NotificationType.FACEBOOK;
break;
default:
notificationKind = NotificationKind.UNDEFINED;
notificationSpec.type = NotificationType.UNDEFINED;
break;
}
LOG.info("Processing notification from source " + source);
Bundle extras = notification.extras;
String title = extras.getCharSequence(Notification.EXTRA_TITLE).toString();
String content = null;
notificationSpec.title = extras.getCharSequence(Notification.EXTRA_TITLE).toString();
if (extras.containsKey(Notification.EXTRA_TEXT)) {
CharSequence contentCS = extras.getCharSequence(Notification.EXTRA_TEXT);
if (contentCS != null) {
content = contentCS.toString();
notificationSpec.body = contentCS.toString();
}
}
if (content != null) {
GBApplication.deviceService().onGenericNotification(title, content, (int) sbn.getPostTime(), notificationKind); //FIMXE: a truly unique id would be better
}
notificationSpec.id = (int) sbn.getPostTime(); //FIMXE: a truly unique id would be better
GBApplication.deviceService().onNotification(notificationSpec);
}
private boolean isServiceRunning() {

View File

@ -13,7 +13,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
public class PebbleReceiver extends BroadcastReceiver {
@ -33,9 +34,6 @@ public class PebbleReceiver extends BroadcastReceiver {
}
}
String title;
String body;
String messageType = intent.getStringExtra("messageType");
if (!messageType.equals("PEBBLE_ALERT")) {
LOG.info("non PEBBLE_ALERT message type not supported");
@ -47,24 +45,25 @@ public class PebbleReceiver extends BroadcastReceiver {
return;
}
NotificationSpec notificationSpec = new NotificationSpec();
String notificationData = intent.getStringExtra("notificationData");
try {
JSONArray notificationJSON = new JSONArray(notificationData);
title = notificationJSON.getJSONObject(0).getString("title");
body = notificationJSON.getJSONObject(0).getString("body");
notificationSpec.title = notificationJSON.getJSONObject(0).getString("title");
notificationSpec.body = notificationJSON.getJSONObject(0).getString("body");
} catch (JSONException e) {
e.printStackTrace();
return;
}
if (title != null && body != null) {
NotificationKind notificationKind = NotificationKind.UNDEFINED;
if (notificationSpec.title != null) {
notificationSpec.type = NotificationType.UNDEFINED;
String sender = intent.getStringExtra("sender");
if ("Conversations".equals(sender)) {
notificationKind = NotificationKind.CHAT;
notificationSpec.type = NotificationType.CHAT;
}
GBApplication.deviceService().onGenericNotification(title, body, -1, notificationKind);
GBApplication.deviceService().onNotification(notificationSpec);
}
}
}

View File

@ -10,6 +10,8 @@ import android.preference.PreferenceManager;
import android.telephony.SmsMessage;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
public class SMSReceiver extends BroadcastReceiver {
@ -27,16 +29,20 @@ public class SMSReceiver extends BroadcastReceiver {
}
}
NotificationSpec notificationSpec = new NotificationSpec();
notificationSpec.id = -1;
notificationSpec.type = NotificationType.SMS;
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
for (Object pdu1 : pdus) {
byte[] pdu = (byte[]) pdu1;
SmsMessage message = SmsMessage.createFromPdu(pdu);
String body = message.getDisplayMessageBody();
String sender = message.getOriginatingAddress();
if (sender != null && body != null) {
GBApplication.deviceService().onSMS(sender, body);
notificationSpec.body = message.getDisplayMessageBody();
notificationSpec.phoneNumber = message.getOriginatingAddress();
if (notificationSpec.phoneNumber != null) {
GBApplication.deviceService().onNotification(notificationSpec);
}
}
}

View File

@ -9,10 +9,10 @@ import android.support.v4.content.LocalBroadcastManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class GBDevice implements Parcelable {
public static final String ACTION_DEVICE_CHANGED

View File

@ -4,9 +4,9 @@ import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
/**
*/

View File

@ -11,7 +11,7 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
@ -80,29 +80,16 @@ public class GBDeviceService implements DeviceService {
}
@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, int handle, NotificationKind notificationKind) {
Intent intent = createIntent().setAction(ACTION_NOTIFICATION_GENERIC)
.putExtra(EXTRA_NOTIFICATION_TITLE, title)
.putExtra(EXTRA_NOTIFICATION_BODY, details)
.putExtra(EXTRA_NOTIFICATION_HANDLE, handle)
.putExtra(EXTRA_NOTIFICATION_KIND, notificationKind);
public void onNotification(NotificationSpec notificationSpec) {
Intent intent = createIntent().setAction(ACTION_NOTIFICATION)
.putExtra(EXTRA_NOTIFICATION_PHONENUMBER, notificationSpec.phoneNumber)
.putExtra(EXTRA_NOTIFICATION_SENDER, notificationSpec.sender)
.putExtra(EXTRA_NOTIFICATION_SUBJECT, notificationSpec.subject)
.putExtra(EXTRA_NOTIFICATION_TITLE, notificationSpec.title)
.putExtra(EXTRA_NOTIFICATION_BODY, notificationSpec.body)
.putExtra(EXTRA_NOTIFICATION_ID, notificationSpec.id)
.putExtra(EXTRA_NOTIFICATION_TYPE, notificationSpec.type)
.putExtra(EXTRA_NOTIFICATION_SOURCENAME, notificationSpec.sourceName);
invokeService(intent);
}

View File

@ -2,8 +2,6 @@ package nodomain.freeyourgadget.gadgetbridge.model;
import android.content.Context;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
public class ActivityAmount {
private int activityKind;
private short percent;

View File

@ -13,9 +13,8 @@ public interface DeviceService extends EventHandler {
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 = PREFIX + ".action.notification";
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";
@ -32,12 +31,14 @@ public interface DeviceService extends EventHandler {
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_ID = "notification_id";
static final String EXTRA_NOTIFICATION_PHONENUMBER = "notification_phonenumber";
static final String EXTRA_NOTIFICATION_SENDER = "notification_sender";
static final String EXTRA_NOTIFICATION_SOURCENAME = "notification_sourcename";
static final String EXTRA_NOTIFICATION_SUBJECT = "notification_subject";
static final String EXTRA_NOTIFICATION_HANDLE = "notification_handle";
static final String EXTRA_NOTIFICATION_KIND = "notificationKind";
static final String EXTRA_NOTIFICATION_TITLE = "notification_title";
static final String EXTRA_NOTIFICATION_TYPE = "notification_type";
static final String EXTRA_FIND_START = "find_start";
static final String EXTRA_CALL_COMMAND = "call_command";
static final String EXTRA_CALL_PHONENUMBER = "call_phonenumber";
@ -51,15 +52,18 @@ public interface DeviceService extends EventHandler {
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.

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.model;
public interface ItemWithDetails {
String getName();
String getDetails();
int getIcon();
}

View File

@ -0,0 +1,12 @@
package nodomain.freeyourgadget.gadgetbridge.model;
public class NotificationSpec {
public int id;
public String sender;
public String phoneNumber;
public String title;
public String subject;
public String body;
public NotificationType type;
public String sourceName;
}

View File

@ -1,6 +1,6 @@
package nodomain.freeyourgadget.gadgetbridge.model;
public enum NotificationKind {
public enum NotificationType {
UNDEFINED,

View File

@ -26,7 +26,8 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -37,9 +38,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DI
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_FETCH_ACTIVITY_DATA;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_FIND_DEVICE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_INSTALL;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION_EMAIL;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION_GENERIC;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION_SMS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REBOOT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_APPINFO;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_DEVICEINFO;
@ -60,11 +59,13 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUS
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ARTIST;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACK;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_BODY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_HANDLE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_KIND;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_PHONENUMBER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SENDER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SOURCENAME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SUBJECT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_TITLE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_TYPE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_PERFORM_PAIR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI;
@ -180,26 +181,20 @@ public class DeviceCommunicationService extends Service {
case ACTION_REQUEST_DEVICEINFO:
mGBDevice.sendDeviceUpdateIntent(this);
break;
case ACTION_NOTIFICATION_GENERIC: {
String title = intent.getStringExtra(EXTRA_NOTIFICATION_TITLE);
String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
int handle = intent.getIntExtra(EXTRA_NOTIFICATION_HANDLE, -1);
NotificationKind notificationKind = (NotificationKind) intent.getSerializableExtra(EXTRA_NOTIFICATION_KIND);
mDeviceSupport.onGenericNotification(title, body, handle, notificationKind);
break;
}
case ACTION_NOTIFICATION_SMS: {
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(EXTRA_NOTIFICATION_SENDER);
String subject = intent.getStringExtra(EXTRA_NOTIFICATION_SUBJECT);
String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
mDeviceSupport.onEmail(sender, subject, body);
case ACTION_NOTIFICATION: {
NotificationSpec notificationSpec = new NotificationSpec();
notificationSpec.phoneNumber = intent.getStringExtra(EXTRA_NOTIFICATION_PHONENUMBER);
notificationSpec.sender = intent.getStringExtra(EXTRA_NOTIFICATION_SENDER);
notificationSpec.subject = intent.getStringExtra(EXTRA_NOTIFICATION_SUBJECT);
notificationSpec.title = intent.getStringExtra(EXTRA_NOTIFICATION_TITLE);
notificationSpec.body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY);
notificationSpec.type = (NotificationType) intent.getSerializableExtra(EXTRA_NOTIFICATION_TYPE);
notificationSpec.id = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
notificationSpec.sourceName = intent.getStringExtra(EXTRA_NOTIFICATION_SOURCENAME);
if (notificationSpec.type == NotificationType.SMS && notificationSpec.phoneNumber != null) {
notificationSpec.sender = getContactDisplayNameByNumber(notificationSpec.phoneNumber);
}
mDeviceSupport.onNotification(notificationSpec);
break;
}
case ACTION_REBOOT: {

View File

@ -22,14 +22,16 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public interface DeviceSupport extends EventHandler {
/**
* Sets all context information needed for the instance to operate.
* @param gbDevice the device to operate with
*
* @param gbDevice the device to operate with
* @param btAdapter the bluetooth adapter to use
* @param context the android context, e.g. to look up resources
* @param context the android context, e.g. to look up resources
*/
void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context);
/**
* Returns whether a transport-level connection is established with the device
*
* @return whether the device is connected with the system running this software
*/
boolean isConnected();
@ -40,9 +42,10 @@ public interface DeviceSupport extends EventHandler {
* Returns true if a connection attempt was made. If the implementation is synchronous
* it may also return true if the connection was successfully established, however
* callers shall not rely on that.
*
* <p/>
* The actual connection state change (successful or not) will be reported via the
* #getDevice device as a device change Intent.
*
* @see GBDevice#ACTION_DEVICE_CHANGED
*/
boolean connect();
@ -62,6 +65,7 @@ public interface DeviceSupport extends EventHandler {
/**
* Attempts to pair and connect this device with the gadget device. Success
* will be reported via a device change Intent.
*
* @see GBDevice#ACTION_DEVICE_CHANGED
*/
void pair();

View File

@ -13,8 +13,8 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
/**
* Wraps another device support instance and supports busy-checking and throttling of events.
@ -25,6 +25,7 @@ public class ServiceDeviceSupport implements DeviceSupport {
THROTTLING,
BUSY_CHECKING,
}
private static final Logger LOG = LoggerFactory.getLogger(ServiceDeviceSupport.class);
private static final long THROTTLING_THRESHOLD = 1000; // throttle multiple events in between one second
@ -112,27 +113,11 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
@Override
public void onSMS(String from, String body) {
if (checkBusy("sms") || checkThrottle("sms")) {
return;
}
delegate.onSMS(from, body);
}
@Override
public void onEmail(String from, String subject, String body) {
if (checkBusy("email") || checkThrottle("email")) {
return;
}
delegate.onEmail(from, subject, body);
}
@Override
public void onGenericNotification(String title, String details, int handle, NotificationKind notificationKind) {
public void onNotification(NotificationSpec notificationSpec) {
if (checkBusy("generic notification") || checkThrottle("generic notification")) {
return;
}
delegate.onGenericNotification(title, details, handle, notificationKind);
delegate.onNotification(notificationSpec);
}
@Override

View File

@ -14,10 +14,10 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
* Abstract base class for a BTLEOperation, i.e. an operation that does more than
* just sending a few bytes to the device. It typically involves exchanging many messages
* between the mobile and the device.
*
* <p/>
* One operation may execute multiple @{link Transaction transactions} with each
* multiple @{link BTLEAction actions}.
*
* <p/>
* This class implements GattCallback so that subclasses may override those methods
* to handle those events.
* Note: by default all Gatt events are forwarded to AbstractBTLEDeviceSupport, subclasses may override
@ -33,6 +33,7 @@ public abstract class AbstractBTLEOperation<T extends AbstractBTLEDeviceSupport>
/**
* Delegates to the DeviceSupport instance and additionally sets this instance as the Gatt
* callback for the transaction.
*
* @param taskName
* @return
* @throws IOException

View File

@ -2,8 +2,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle;
import java.io.IOException;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport;
public interface BTLEOperation {
public void perform() throws IOException;
}

View File

@ -207,6 +207,7 @@ public final class BtLEQueue {
/**
* Depending on certain criteria, connects to the BluetoothGatt.
*
* @return true if a reconnection attempt was made, or false otherwise
*/
private boolean maybeReconnect() {
@ -275,7 +276,9 @@ public final class BtLEQueue {
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final class InternalGattCallback extends BluetoothGattCallback {
private @Nullable GattCallback mTransactionGattCallback;
private
@Nullable
GattCallback mTransactionGattCallback;
private GattCallback mExternalGattCallback;
public InternalGattCallback(GattCallback externalGattCallback) {
@ -449,5 +452,7 @@ public final class BtLEQueue {
}
mTransactionGattCallback = null;
}
};
}
;
}

View File

@ -19,7 +19,9 @@ public class Transaction {
private String mName;
private List<BtLEAction> mActions = new ArrayList<>(4);
private long creationTimestamp = System.currentTimeMillis();
private @Nullable GattCallback gattCallback;
private
@Nullable
GattCallback gattCallback;
public Transaction(String taskName) {
this.mName = taskName;
@ -57,7 +59,9 @@ public class Transaction {
/**
* Returns the GattCallback for this transaction, or null if none.
*/
public @Nullable GattCallback getGattCallback() {
public
@Nullable
GattCallback getGattCallback() {
return gattCallback;
}
}

View File

@ -64,13 +64,16 @@ public class TransactionBuilder {
/**
* Sets a GattCallback instance that will be called when the transaction is executed,
* resulting in GattCallback events.
*
* @param callback the callback to set, may be null
*/
public void setGattCallback(@Nullable GattCallback callback) {
mTransaction.setGattCallback(callback);
}
public @Nullable GattCallback getGattCallback() {
public
@Nullable
GattCallback getGattCallback() {
return mTransaction.getGattCallback();
}

View File

@ -14,6 +14,7 @@ public class SetProgressAction extends PlainAction {
/**
* When run, will update the progress notification.
*
* @param text
* @param ongoing
* @param percentage

View File

@ -11,7 +11,7 @@ public class BatteryInfo extends AbstractInfo {
public static final byte DEVICE_BATTERY_CHARGING = 2;
public static final byte DEVICE_BATTERY_CHARGING_FULL = 3;
public static final byte DEVICE_BATTERY_CHARGE_OFF = 4;
public BatteryInfo(byte[] data) {
super(data);
}

View File

@ -28,8 +28,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
@ -54,6 +54,7 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.FL
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.FLASH_ORIGINAL_COLOUR;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_GENERIC;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_K9MAIL;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_PEBBLEMSG;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_SMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_COUNT;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_DURATION;
@ -402,18 +403,21 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
}
@Override
public void onSMS(String from, String body) {
performPreferredNotification("sms received", ORIGIN_SMS, null);
}
@Override
public void onEmail(String from, String subject, String body) {
performPreferredNotification("email received", ORIGIN_K9MAIL, null);
}
@Override
public void onGenericNotification(String title, String details, int handle, NotificationKind notificationKind) {
performPreferredNotification("generic notification received", ORIGIN_GENERIC, null);
public void onNotification(NotificationSpec notificationSpec) {
// FIXME: these ORIGIN contants do not really make sense anymore
switch (notificationSpec.type) {
case SMS:
performPreferredNotification("sms received", ORIGIN_SMS, null);
break;
case EMAIL:
performPreferredNotification("email received", ORIGIN_K9MAIL, null);
break;
case CHAT:
performPreferredNotification("chat message received", ORIGIN_PEBBLEMSG, null);
break;
default:
performPreferredNotification("generic notification received", ORIGIN_GENERIC, null);
}
}
@Override
@ -598,7 +602,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
handleBatteryInfo(characteristic.getValue(), BluetoothGatt.GATT_SUCCESS);
} else if (MiBandService.UUID_CHARACTERISTIC_NOTIFICATION.equals(characteristicUUID)) {
handleNotificationNotif(characteristic.getValue());
} else{
} else {
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
}
}

View File

@ -151,12 +151,11 @@ public class FetchActivityOperation extends AbstractBTLEOperation<MiBandSupport>
* There are two kind of messages we currently know:
* - the first one is 11 bytes long and contains metadata (how many bytes to expect, when the data starts, etc.)
* - the second one is 20 bytes long and contains the actual activity data
*
* <p/>
* The first message type is parsed by this method, for every other length of the value param, bufferActivityData is called.
* @see #bufferActivityData(byte[])
*
*
* @param value
* @see #bufferActivityData(byte[])
*/
private void handleActivityNotif(byte[] value) {
if (value.length == 11) {
@ -205,7 +204,7 @@ public class FetchActivityOperation extends AbstractBTLEOperation<MiBandSupport>
/**
* Method to store temporarily the activity data values got from the Mi Band.
*
* <p/>
* Since we expect chunks of 20 bytes each, we do not store the received bytes it the length is different.
*
* @param value
@ -275,7 +274,7 @@ public class FetchActivityOperation extends AbstractBTLEOperation<MiBandSupport>
/**
* Acknowledge the transfer of activity data to the Mi Band.
*
* <p/>
* After receiving data from the band, it has to be acknowledged. This way the Mi Band will delete
* the data it has on record.
*

View File

@ -72,21 +72,21 @@ public class UpdateFirmwareOperation extends AbstractBTLEOperation<MiBandSupport
* characteristic,
* These messages appear to be always 1 byte long, with values that are listed in MiBandService.
* It is not excluded that there are further values which are still unknown.
*
* <p/>
* Upon receiving known values that request further action by GB, the appropriate method is called.
*
* @param value
*/
private void handleNotificationNotif(byte[] value) {
if(value.length != 1) {
if (value.length != 1) {
LOG.error("Notifications should be 1 byte long.");
getSupport().logMessageContent(value);
return;
}
switch (value[0]) {
case MiBandService.NOTIFY_FW_CHECK_SUCCESS:
if(firmwareInfoSent && newFirmware != null) {
if(sendFirmwareData(newFirmware)) {
if (firmwareInfoSent && newFirmware != null) {
if (sendFirmwareData(newFirmware)) {
rebootWhenBandReady = true;
} else {
//TODO: the firmware transfer failed, but the miband should be still functional with the old firmware. What should we do?
@ -131,14 +131,14 @@ public class UpdateFirmwareOperation extends AbstractBTLEOperation<MiBandSupport
* Prepare the MiBand to receive the new firmware data.
* Some information about the new firmware version have to be pushed to the MiBand before sending
* the actual firmare.
*
* <p/>
* The Mi Band will send a notification after receiving these data to confirm if the metadata looks good to it.
* @see MiBandSupport#handleNotificationNotif
*
* @param currentFwVersion
* @param newFwVersion
* @param newFwSize
* @param checksum
* @see MiBandSupport#handleNotificationNotif
*/
private void sendFirmwareInfo(int currentFwVersion, int newFwVersion, int newFwSize, int checksum) throws IOException {
byte[] fwInfo = new byte[]{
@ -165,13 +165,13 @@ public class UpdateFirmwareOperation extends AbstractBTLEOperation<MiBandSupport
/**
* Method that uploads a firmware (fwbytes) to the MiBand.
* The firmware has to be splitted into chunks of 20 bytes each, and periodically a COMMAND_SYNC comand has to be issued to the MiBand.
*
* <p/>
* The Mi Band will send a notification after receiving these data to confirm if the firmware looks good to it.
* @see MiBandSupport#handleNotificationNotif
*
* @param fwbytes
* @return whether the transfer succeeded or not. Only a BT layer exception will cause the transmission to fail.
* */
* @see MiBandSupport#handleNotificationNotif
*/
private boolean sendFirmwareData(byte fwbytes[]) {
int len = fwbytes.length;
final int packetLength = 20;

View File

@ -30,7 +30,8 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInf
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
@ -384,7 +385,21 @@ public class PebbleProtocol extends GBDeviceProtocol {
return buf.array();
}
private byte[] encodeNotification(int id, String title, String subtitle, String body, byte type, boolean hasHandle, NotificationKind notificationKind) {
@Override
public byte[] encodeNotification(NotificationSpec notificationSpec) {
boolean hasHandle = notificationSpec.id != -1;
int id = notificationSpec.id != -1 ? notificationSpec.id : mRandom.nextInt();
String title;
String subtitle = null;
// for SMS and EMAIL that came in though SMS or K9 receiver
if (notificationSpec.sender != null) {
title = notificationSpec.sender;
subtitle = notificationSpec.subject;
} else {
title = notificationSpec.title;
}
Long ts = System.currentTimeMillis();
if (!isFw3x) {
ts += (SimpleTimeZone.getDefault().getOffset(ts));
@ -394,33 +409,18 @@ public class PebbleProtocol extends GBDeviceProtocol {
if (isFw3x) {
// 3.x notification
//return encodeTimelinePin(id, (int) ((ts + 600) & 0xffffffffL), (short) 90, PebbleIconID.TIMELINE_CALENDAR, title); // really, this is just for testing
return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, body, type, hasHandle, notificationKind);
} else if (mForceProtocol || type != NOTIFICATION_EMAIL) {
return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, hasHandle, notificationSpec.type);
} else if (mForceProtocol || notificationSpec.type != NotificationType.EMAIL) {
// 2.x notification
return encodeExtensibleNotification(id, (int) (ts & 0xffffffffL), title, subtitle, body, type, hasHandle);
return encodeExtensibleNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, hasHandle);
} else {
// 1.x notification on FW 2.X
String[] parts = {title, body, ts.toString(), subtitle};
String[] parts = {title, notificationSpec.body, ts.toString(), subtitle};
// be aware that type is at this point always NOTIFICATION_EMAIL
return encodeMessage(ENDPOINT_NOTIFICATION, type, 0, parts);
return encodeMessage(ENDPOINT_NOTIFICATION, NOTIFICATION_EMAIL, 0, parts);
}
}
@Override
public byte[] encodeSMS(String from, String body) {
return encodeNotification(mRandom.nextInt(), from, null, body, NOTIFICATION_SMS, false, NotificationKind.UNDEFINED);
}
@Override
public byte[] encodeEmail(String from, String subject, String body) {
return encodeNotification(mRandom.nextInt(), from, subject, body, NOTIFICATION_EMAIL, false, NotificationKind.UNDEFINED);
}
@Override
public byte[] encodeGenericNotification(String title, String details, int handle, NotificationKind notificationKind) {
return encodeNotification(handle != -1 ? handle : mRandom.nextInt(), title, null, details, NOTIFICATION_UNDEFINED, handle != -1, notificationKind);
}
@Override
public byte[] encodeSetTime() {
long ts = System.currentTimeMillis();
@ -455,7 +455,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
return encodeSetCallState("Where are you?", "Gadgetbridge", start ? ServiceCommand.CALL_INCOMING : ServiceCommand.CALL_END);
}
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, boolean hasHandle) {
final short ACTION_LENGTH_MIN = 10;
String[] parts = {title, subtitle, body};
@ -619,7 +619,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
return encodeBlobdb(uuid, BLOBDB_INSERT, BLOBDB_PIN, buf.array());
}
private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, byte type, boolean hasHandle, NotificationKind notificationKind) {
private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, boolean hasHandle, NotificationType notificationType) {
final short NOTIFICATION_PIN_LENGTH = 46;
final short ACTION_LENGTH_MIN = 10;
@ -627,17 +627,17 @@ public class PebbleProtocol extends GBDeviceProtocol {
int icon_id;
byte color_id;
switch (type) {
case NOTIFICATION_EMAIL:
switch (notificationType) {
case EMAIL:
icon_id = PebbleIconID.GENERIC_EMAIL;
color_id = PebbleColor.JaegerGreen;
break;
case NOTIFICATION_SMS:
case SMS:
icon_id = PebbleIconID.GENERIC_SMS;
color_id = PebbleColor.VividViolet;
break;
default:
switch (notificationKind) {
switch (notificationType) {
case TWITTER:
icon_id = PebbleIconID.NOTIFICATION_TWITTER;
color_id = PebbleColor.BlueMoon;

View File

@ -51,6 +51,6 @@ public class WeatherNeatSupport {
public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes();
sendBytes.encodedBytes = encodeWeatherNeatMessage("Berlin", "22 C", "cloudy", 0);
return new GBDeviceEvent[] {sendBytes};
return new GBDeviceEvent[]{sendBytes};
}
}

View File

@ -8,7 +8,7 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
@ -108,20 +108,8 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
}
@Override
public void onSMS(String from, String body) {
byte[] bytes = gbDeviceProtocol.encodeSMS(from, body);
sendToDevice(bytes);
}
@Override
public void onEmail(String from, String subject, String body) {
byte[] bytes = gbDeviceProtocol.encodeEmail(from, subject, body);
sendToDevice(bytes);
}
@Override
public void onGenericNotification(String title, String details, int handle, NotificationKind notificationKind) {
byte[] bytes = gbDeviceProtocol.encodeGenericNotification(title, details, handle, notificationKind);
public void onNotification(NotificationSpec notificationSpec) {
byte[] bytes = gbDeviceProtocol.encodeNotification(notificationSpec);
sendToDevice(bytes);
}

View File

@ -3,20 +3,12 @@ package nodomain.freeyourgadget.gadgetbridge.service.serial;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationKind;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
public abstract class GBDeviceProtocol {
public byte[] encodeSMS(String from, String body) {
return null;
}
public byte[] encodeEmail(String from, String subject, String body) {
return null;
}
public byte[] encodeGenericNotification(String title, String details, int handle, NotificationKind notificationKind) {
public byte[] encodeNotification(NotificationSpec notificationSpec) {
return null;
}

View File

@ -5,10 +5,10 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
public class DeviceHelper {
private static DeviceHelper instance = new DeviceHelper();

View File

@ -51,7 +51,8 @@ public class FileUtils {
* Reads the contents of the given InputStream into a byte array, but does not
* read more than maxLen bytes. If the stream provides more than maxLen bytes,
* an IOException is thrown.
* @param in the stream to read from
*
* @param in the stream to read from
* @param maxLen the maximum number of bytes to read/return
* @return the bytes read from the InputStream
* @throws IOException when reading failed or when maxLen was exceeded

View File

@ -355,7 +355,7 @@ public class GB {
notificationIntent, 0);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context)
.setContentTitle( context.getString(R.string.notif_battery_low_title))
.setContentTitle(context.getString(R.string.notif_battery_low_title))
.setContentText(text)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_notification_low_battery)