1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-29 05:16:51 +01:00

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,10 +12,9 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; 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.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter; import nodomain.freeyourgadget.gadgetbridge.adapter.GBAlarmListAdapter;
import nodomain.freeyourgadget.gadgetbridge.impl.GBAlarm;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ALARMS; 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.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB; 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.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; 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.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -70,17 +72,25 @@ public class DebugActivity extends Activity {
sendSMSButton.setOnClickListener(new View.OnClickListener() { sendSMSButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { 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 = (Button) findViewById(R.id.sendEmailButton);
sendEmailButton.setOnClickListener(new View.OnClickListener() { sendEmailButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
GBApplication.deviceService().onEmail( NotificationSpec notificationSpec = new NotificationSpec();
getResources().getText(R.string.app_name).toString(), notificationSpec.sender = getResources().getText(R.string.app_name).toString();
getResources().getText(R.string.test).toString(), notificationSpec.subject = editContent.getText().toString();
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 java.util.ArrayList;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.DeviceCandidateAdapter;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB; 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 { public class DiscoveryActivity extends Activity implements AdapterView.OnItemClickListener {
private static final Logger LOG = LoggerFactory.getLogger(DiscoveryActivity.class); 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.MenuItem;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,13 +12,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; 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.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript; import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; 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.DATABASE_NAME;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_INTENSITY; 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>(); ArrayList<ActivitySample> samples = new ArrayList<ActivitySample>();
final String where = "(provider=" + provider.getID() + " and timestamp>=" + timestamp_from + " and timestamp<=" + timestamp_to + getWhereClauseFor(activityTypes, provider) + ")"; 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"; final String order = "timestamp";
try (SQLiteDatabase db = this.getReadableDatabase()) { try (SQLiteDatabase db = this.getReadableDatabase()) {
try (Cursor cursor = db.query(TABLE_GBACTIVITYSAMPLES, null, where, null, null, null, order)) { 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.os.AsyncTask;
import android.widget.Toast; import android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public abstract class DBAccess extends AsyncTask { public abstract class DBAccess extends AsyncTask {
private final String mTask; private final String mTask;

View File

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

View File

@ -6,9 +6,9 @@ import android.support.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.UUID; 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.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. * 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. * Implementations need to send/encode event to the connected device.
*/ */
public interface EventHandler { public interface EventHandler {
void onSMS(String from, String body); void onNotification(NotificationSpec notificationSpec);
void onEmail(String from, String subject, String body);
void onGenericNotification(String title, String details, int handle, NotificationKind notificationKind);
void onSetTime(); void onSetTime();

View File

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

View File

@ -9,18 +9,16 @@ import android.preference.PreferenceManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Calendar; 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.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; 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.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 { public class MiBandCoordinator implements DeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(MiBandCoordinator.class); 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 * uses the standard algorithm to convert bytes received from the MiBand to a Calendar object
*
* @param value * @param value
* @return * @return
*/ */
@ -25,6 +26,7 @@ public class MiBandDateConverter {
/** /**
* uses the standard algorithm to convert bytes received from the MiBand to a Calendar object * uses the standard algorithm to convert bytes received from the MiBand to a Calendar object
*
* @param value * @param value
* @return * @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 * uses the standard algorithm to convert a Calendar object to a byte array to send to MiBand
*
* @param timestamp * @param timestamp
* @return * @return
*/ */

View File

@ -12,7 +12,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Locale; import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
public class MiBandFWHelper { public class MiBandFWHelper {
@ -48,7 +47,7 @@ public class MiBandFWHelper {
throw new IOException("Firmware has a filename that looks like a Pebble app/firmware."); 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 this.fw = FileUtils.readAll(in, 1024 * 1024); // 1 MB
if (fw.length <= firmwareVersionMajor || fw[firmwareVersionMajor] != 1) { if (fw.length <= firmwareVersionMajor || fw[firmwareVersionMajor] != 1) {
throw new IOException("Firmware major version should be 1, probably this isn't a MiBand firmware."); 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 android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; 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.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.activities.DiscoveryActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DiscoveryActivity;
public class MiBandPairingActivity extends Activity { public class MiBandPairingActivity extends Activity {

View File

@ -5,9 +5,9 @@ import android.os.Bundle;
import android.preference.Preference; import android.preference.Preference;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity; 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_GENERIC;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_INCOMING_CALL; 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_PEBBLEMSG;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_SMS; 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_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_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_MIBAND_WEARSIDE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_USER_ALIAS; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_USER_ALIAS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_USER_GENDER; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_USER_GENDER;

View File

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

View File

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

View File

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

View File

@ -13,6 +13,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
public class K9Receiver extends BroadcastReceiver { public class K9Receiver extends BroadcastReceiver {
@ -42,9 +44,9 @@ public class K9Receiver extends BroadcastReceiver {
"uri" "uri"
}; };
String sender = ""; NotificationSpec notificationSpec = new NotificationSpec();
String subject = ""; notificationSpec.id = -1;
String preview = ""; notificationSpec.type = NotificationType.EMAIL;
/* /*
* there seems to be no way to specify the the uri in the where clause. * 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 { do {
String uri = c.getString(c.getColumnIndex("uri")); String uri = c.getString(c.getColumnIndex("uri"));
if (uri.equals(uriWanted)) { if (uri.equals(uriWanted)) {
sender = c.getString(c.getColumnIndex("senderAddress")); notificationSpec.sender = c.getString(c.getColumnIndex("senderAddress"));
subject = c.getString(c.getColumnIndex("subject")); notificationSpec.subject = c.getString(c.getColumnIndex("subject"));
preview = c.getString(c.getColumnIndex("preview")); notificationSpec.body = c.getString(c.getColumnIndex("preview"));
break; break;
} }
} while (c.moveToNext()); } while (c.moveToNext());
c.close(); 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.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

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

View File

@ -13,7 +13,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; 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 { public class PebbleReceiver extends BroadcastReceiver {
@ -33,9 +34,6 @@ public class PebbleReceiver extends BroadcastReceiver {
} }
} }
String title;
String body;
String messageType = intent.getStringExtra("messageType"); String messageType = intent.getStringExtra("messageType");
if (!messageType.equals("PEBBLE_ALERT")) { if (!messageType.equals("PEBBLE_ALERT")) {
LOG.info("non PEBBLE_ALERT message type not supported"); LOG.info("non PEBBLE_ALERT message type not supported");
@ -47,24 +45,25 @@ public class PebbleReceiver extends BroadcastReceiver {
return; return;
} }
NotificationSpec notificationSpec = new NotificationSpec();
String notificationData = intent.getStringExtra("notificationData"); String notificationData = intent.getStringExtra("notificationData");
try { try {
JSONArray notificationJSON = new JSONArray(notificationData); JSONArray notificationJSON = new JSONArray(notificationData);
title = notificationJSON.getJSONObject(0).getString("title"); notificationSpec.title = notificationJSON.getJSONObject(0).getString("title");
body = notificationJSON.getJSONObject(0).getString("body"); notificationSpec.body = notificationJSON.getJSONObject(0).getString("body");
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
return; return;
} }
if (title != null && body != null) { if (notificationSpec.title != null) {
NotificationKind notificationKind = NotificationKind.UNDEFINED; notificationSpec.type = NotificationType.UNDEFINED;
String sender = intent.getStringExtra("sender"); String sender = intent.getStringExtra("sender");
if ("Conversations".equals(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 android.telephony.SmsMessage;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
public class SMSReceiver extends BroadcastReceiver { 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(); Bundle bundle = intent.getExtras();
if (bundle != null) { if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus"); Object[] pdus = (Object[]) bundle.get("pdus");
for (Object pdu1 : pdus) { for (Object pdu1 : pdus) {
byte[] pdu = (byte[]) pdu1; byte[] pdu = (byte[]) pdu1;
SmsMessage message = SmsMessage.createFromPdu(pdu); SmsMessage message = SmsMessage.createFromPdu(pdu);
String body = message.getDisplayMessageBody(); notificationSpec.body = message.getDisplayMessageBody();
String sender = message.getOriginatingAddress(); notificationSpec.phoneNumber = message.getOriginatingAddress();
if (sender != null && body != null) { if (notificationSpec.phoneNumber != null) {
GBApplication.deviceService().onSMS(sender, body); GBApplication.deviceService().onNotification(notificationSpec);
} }
} }
} }

View File

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

View File

@ -4,9 +4,9 @@ import android.bluetooth.BluetoothDevice;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R; 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.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; 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.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService; import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
@ -80,29 +80,16 @@ public class GBDeviceService implements DeviceService {
} }
@Override @Override
public void onSMS(String from, String body) { public void onNotification(NotificationSpec notificationSpec) {
Intent intent = createIntent().setAction(ACTION_NOTIFICATION_SMS) Intent intent = createIntent().setAction(ACTION_NOTIFICATION)
.putExtra(EXTRA_NOTIFICATION_SENDER, from) .putExtra(EXTRA_NOTIFICATION_PHONENUMBER, notificationSpec.phoneNumber)
.putExtra(EXTRA_NOTIFICATION_BODY, body); .putExtra(EXTRA_NOTIFICATION_SENDER, notificationSpec.sender)
invokeService(intent); .putExtra(EXTRA_NOTIFICATION_SUBJECT, notificationSpec.subject)
} .putExtra(EXTRA_NOTIFICATION_TITLE, notificationSpec.title)
.putExtra(EXTRA_NOTIFICATION_BODY, notificationSpec.body)
@Override .putExtra(EXTRA_NOTIFICATION_ID, notificationSpec.id)
public void onEmail(String from, String subject, String body) { .putExtra(EXTRA_NOTIFICATION_TYPE, notificationSpec.type)
Intent intent = createIntent().setAction(ACTION_NOTIFICATION_EMAIL) .putExtra(EXTRA_NOTIFICATION_SOURCENAME, notificationSpec.sourceName);
.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);
invokeService(intent); invokeService(intent);
} }

View File

@ -2,8 +2,6 @@ package nodomain.freeyourgadget.gadgetbridge.model;
import android.content.Context; import android.content.Context;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
public class ActivityAmount { public class ActivityAmount {
private int activityKind; private int activityKind;
private short percent; 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_START = PREFIX + ".action.start";
static final String ACTION_CONNECT = PREFIX + ".action.connect"; 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_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_CALLSTATE = PREFIX + ".action.callstate";
static final String ACTION_SETTIME = PREFIX + ".action.settime"; static final String ACTION_SETTIME = PREFIX + ".action.settime";
static final String ACTION_SETMUSICINFO = PREFIX + ".action.setmusicinfo"; 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 ACTION_SET_ALARMS = PREFIX + ".action.set_alarms";
static final String EXTRA_DEVICE_ADDRESS = "device_address"; 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_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_SENDER = "notification_sender";
static final String EXTRA_NOTIFICATION_SOURCENAME = "notification_sourcename";
static final String EXTRA_NOTIFICATION_SUBJECT = "notification_subject"; static final String EXTRA_NOTIFICATION_SUBJECT = "notification_subject";
static final String EXTRA_NOTIFICATION_HANDLE = "notification_handle"; static final String EXTRA_NOTIFICATION_TITLE = "notification_title";
static final String EXTRA_NOTIFICATION_KIND = "notificationKind"; static final String EXTRA_NOTIFICATION_TYPE = "notification_type";
static final String EXTRA_FIND_START = "find_start"; static final String EXTRA_FIND_START = "find_start";
static final String EXTRA_CALL_COMMAND = "call_command"; static final String EXTRA_CALL_COMMAND = "call_command";
static final String EXTRA_CALL_PHONENUMBER = "call_phonenumber"; 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"; static final String EXTRA_PERFORM_PAIR = "perform_pair";
void start(); void start();
void connect(); void connect();
void connect(@Nullable String deviceAddress); void connect(@Nullable String deviceAddress);
void connect(@Nullable String deviceAddress, boolean performPair); void connect(@Nullable String deviceAddress, boolean performPair);
void disconnect(); void disconnect();
void quit(); void quit();
/** /**
* Requests information from the {@link DeviceCommunicationService} about the connection state, * Requests information from the {@link DeviceCommunicationService} about the connection state,
* firmware info, etc. * firmware info, etc.

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.model;
public interface ItemWithDetails { public interface ItemWithDetails {
String getName(); String getName();
String getDetails(); String getDetails();
int getIcon(); 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; package nodomain.freeyourgadget.gadgetbridge.model;
public enum NotificationKind { public enum NotificationType {
UNDEFINED, UNDEFINED,

View File

@ -26,7 +26,8 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm; 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.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.util.GB; 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_FETCH_ACTIVITY_DATA;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_FIND_DEVICE; 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_INSTALL;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION_EMAIL; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION;
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_REBOOT; 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_APPINFO;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_DEVICEINFO; 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_ARTIST;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACK; 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_BODY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_HANDLE; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_KIND; 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_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_SUBJECT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_TITLE; 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_PERFORM_PAIR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI;
@ -180,26 +181,20 @@ public class DeviceCommunicationService extends Service {
case ACTION_REQUEST_DEVICEINFO: case ACTION_REQUEST_DEVICEINFO:
mGBDevice.sendDeviceUpdateIntent(this); mGBDevice.sendDeviceUpdateIntent(this);
break; break;
case ACTION_NOTIFICATION_GENERIC: { case ACTION_NOTIFICATION: {
String title = intent.getStringExtra(EXTRA_NOTIFICATION_TITLE); NotificationSpec notificationSpec = new NotificationSpec();
String body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY); notificationSpec.phoneNumber = intent.getStringExtra(EXTRA_NOTIFICATION_PHONENUMBER);
int handle = intent.getIntExtra(EXTRA_NOTIFICATION_HANDLE, -1); notificationSpec.sender = intent.getStringExtra(EXTRA_NOTIFICATION_SENDER);
NotificationKind notificationKind = (NotificationKind) intent.getSerializableExtra(EXTRA_NOTIFICATION_KIND); notificationSpec.subject = intent.getStringExtra(EXTRA_NOTIFICATION_SUBJECT);
mDeviceSupport.onGenericNotification(title, body, handle, notificationKind); notificationSpec.title = intent.getStringExtra(EXTRA_NOTIFICATION_TITLE);
break; 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);
} }
case ACTION_NOTIFICATION_SMS: { mDeviceSupport.onNotification(notificationSpec);
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);
break; break;
} }
case ACTION_REBOOT: { case ACTION_REBOOT: {

View File

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

View File

@ -13,8 +13,8 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand; 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. * Wraps another device support instance and supports busy-checking and throttling of events.
@ -25,6 +25,7 @@ public class ServiceDeviceSupport implements DeviceSupport {
THROTTLING, THROTTLING,
BUSY_CHECKING, BUSY_CHECKING,
} }
private static final Logger LOG = LoggerFactory.getLogger(ServiceDeviceSupport.class); private static final Logger LOG = LoggerFactory.getLogger(ServiceDeviceSupport.class);
private static final long THROTTLING_THRESHOLD = 1000; // throttle multiple events in between one second private static final long THROTTLING_THRESHOLD = 1000; // throttle multiple events in between one second
@ -112,27 +113,11 @@ public class ServiceDeviceSupport implements DeviceSupport {
} }
@Override @Override
public void onSMS(String from, String body) { public void onNotification(NotificationSpec notificationSpec) {
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) {
if (checkBusy("generic notification") || checkThrottle("generic notification")) { if (checkBusy("generic notification") || checkThrottle("generic notification")) {
return; return;
} }
delegate.onGenericNotification(title, details, handle, notificationKind); delegate.onNotification(notificationSpec);
} }
@Override @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 * 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 * just sending a few bytes to the device. It typically involves exchanging many messages
* between the mobile and the device. * between the mobile and the device.
* * <p/>
* One operation may execute multiple @{link Transaction transactions} with each * One operation may execute multiple @{link Transaction transactions} with each
* multiple @{link BTLEAction actions}. * multiple @{link BTLEAction actions}.
* * <p/>
* This class implements GattCallback so that subclasses may override those methods * This class implements GattCallback so that subclasses may override those methods
* to handle those events. * to handle those events.
* Note: by default all Gatt events are forwarded to AbstractBTLEDeviceSupport, subclasses may override * 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 * Delegates to the DeviceSupport instance and additionally sets this instance as the Gatt
* callback for the transaction. * callback for the transaction.
*
* @param taskName * @param taskName
* @return * @return
* @throws IOException * @throws IOException

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,8 +28,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile; import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm; import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand; 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.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; 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.FLASH_ORIGINAL_COLOUR;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_GENERIC; 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_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.ORIGIN_SMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_COUNT; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_COUNT;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_DURATION; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_DURATION;
@ -402,19 +403,22 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
} }
@Override @Override
public void onSMS(String from, String body) { 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); performPreferredNotification("sms received", ORIGIN_SMS, null);
} break;
case EMAIL:
@Override
public void onEmail(String from, String subject, String body) {
performPreferredNotification("email received", ORIGIN_K9MAIL, null); performPreferredNotification("email received", ORIGIN_K9MAIL, null);
} break;
case CHAT:
@Override performPreferredNotification("chat message received", ORIGIN_PEBBLEMSG, null);
public void onGenericNotification(String title, String details, int handle, NotificationKind notificationKind) { break;
default:
performPreferredNotification("generic notification received", ORIGIN_GENERIC, null); performPreferredNotification("generic notification received", ORIGIN_GENERIC, null);
} }
}
@Override @Override
public void onSetTime() { public void onSetTime() {
@ -598,7 +602,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
handleBatteryInfo(characteristic.getValue(), BluetoothGatt.GATT_SUCCESS); handleBatteryInfo(characteristic.getValue(), BluetoothGatt.GATT_SUCCESS);
} else if (MiBandService.UUID_CHARACTERISTIC_NOTIFICATION.equals(characteristicUUID)) { } else if (MiBandService.UUID_CHARACTERISTIC_NOTIFICATION.equals(characteristicUUID)) {
handleNotificationNotif(characteristic.getValue()); handleNotificationNotif(characteristic.getValue());
} else{ } else {
LOG.info("Unhandled characteristic changed: " + characteristicUUID); 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: * 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 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 * - 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. * 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 * @param value
* @see #bufferActivityData(byte[])
*/ */
private void handleActivityNotif(byte[] value) { private void handleActivityNotif(byte[] value) {
if (value.length == 11) { 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. * 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. * Since we expect chunks of 20 bytes each, we do not store the received bytes it the length is different.
* *
* @param value * @param value
@ -275,7 +274,7 @@ public class FetchActivityOperation extends AbstractBTLEOperation<MiBandSupport>
/** /**
* Acknowledge the transfer of activity data to the Mi Band. * 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 * After receiving data from the band, it has to be acknowledged. This way the Mi Band will delete
* the data it has on record. * the data it has on record.
* *

View File

@ -72,21 +72,21 @@ public class UpdateFirmwareOperation extends AbstractBTLEOperation<MiBandSupport
* characteristic, * characteristic,
* These messages appear to be always 1 byte long, with values that are listed in MiBandService. * 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. * 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. * Upon receiving known values that request further action by GB, the appropriate method is called.
* *
* @param value * @param value
*/ */
private void handleNotificationNotif(byte[] value) { private void handleNotificationNotif(byte[] value) {
if(value.length != 1) { if (value.length != 1) {
LOG.error("Notifications should be 1 byte long."); LOG.error("Notifications should be 1 byte long.");
getSupport().logMessageContent(value); getSupport().logMessageContent(value);
return; return;
} }
switch (value[0]) { switch (value[0]) {
case MiBandService.NOTIFY_FW_CHECK_SUCCESS: case MiBandService.NOTIFY_FW_CHECK_SUCCESS:
if(firmwareInfoSent && newFirmware != null) { if (firmwareInfoSent && newFirmware != null) {
if(sendFirmwareData(newFirmware)) { if (sendFirmwareData(newFirmware)) {
rebootWhenBandReady = true; rebootWhenBandReady = true;
} else { } else {
//TODO: the firmware transfer failed, but the miband should be still functional with the old firmware. What should we do? //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. * 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 * Some information about the new firmware version have to be pushed to the MiBand before sending
* the actual firmare. * the actual firmare.
* * <p/>
* The Mi Band will send a notification after receiving these data to confirm if the metadata looks good to it. * 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 currentFwVersion
* @param newFwVersion * @param newFwVersion
* @param newFwSize * @param newFwSize
* @param checksum * @param checksum
* @see MiBandSupport#handleNotificationNotif
*/ */
private void sendFirmwareInfo(int currentFwVersion, int newFwVersion, int newFwSize, int checksum) throws IOException { private void sendFirmwareInfo(int currentFwVersion, int newFwVersion, int newFwSize, int checksum) throws IOException {
byte[] fwInfo = new byte[]{ byte[] fwInfo = new byte[]{
@ -165,13 +165,13 @@ public class UpdateFirmwareOperation extends AbstractBTLEOperation<MiBandSupport
/** /**
* Method that uploads a firmware (fwbytes) to the MiBand. * 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. * 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. * 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 * @param fwbytes
* @return whether the transfer succeeded or not. Only a BT layer exception will cause the transmission to fail. * @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[]) { private boolean sendFirmwareData(byte fwbytes[]) {
int len = fwbytes.length; int len = fwbytes.length;
final int packetLength = 20; 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.PebbleColor;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID; import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp; 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.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol; import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
@ -384,7 +385,21 @@ public class PebbleProtocol extends GBDeviceProtocol {
return buf.array(); 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(); Long ts = System.currentTimeMillis();
if (!isFw3x) { if (!isFw3x) {
ts += (SimpleTimeZone.getDefault().getOffset(ts)); ts += (SimpleTimeZone.getDefault().getOffset(ts));
@ -394,33 +409,18 @@ public class PebbleProtocol extends GBDeviceProtocol {
if (isFw3x) { if (isFw3x) {
// 3.x notification // 3.x notification
//return encodeTimelinePin(id, (int) ((ts + 600) & 0xffffffffL), (short) 90, PebbleIconID.TIMELINE_CALENDAR, title); // really, this is just for testing //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); return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, hasHandle, notificationSpec.type);
} else if (mForceProtocol || type != NOTIFICATION_EMAIL) { } else if (mForceProtocol || notificationSpec.type != NotificationType.EMAIL) {
// 2.x notification // 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 { } else {
// 1.x notification on FW 2.X // 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 // 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 @Override
public byte[] encodeSetTime() { public byte[] encodeSetTime() {
long ts = System.currentTimeMillis(); 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); 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; final short ACTION_LENGTH_MIN = 10;
String[] parts = {title, subtitle, body}; String[] parts = {title, subtitle, body};
@ -619,7 +619,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
return encodeBlobdb(uuid, BLOBDB_INSERT, BLOBDB_PIN, buf.array()); 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 NOTIFICATION_PIN_LENGTH = 46;
final short ACTION_LENGTH_MIN = 10; final short ACTION_LENGTH_MIN = 10;
@ -627,17 +627,17 @@ public class PebbleProtocol extends GBDeviceProtocol {
int icon_id; int icon_id;
byte color_id; byte color_id;
switch (type) { switch (notificationType) {
case NOTIFICATION_EMAIL: case EMAIL:
icon_id = PebbleIconID.GENERIC_EMAIL; icon_id = PebbleIconID.GENERIC_EMAIL;
color_id = PebbleColor.JaegerGreen; color_id = PebbleColor.JaegerGreen;
break; break;
case NOTIFICATION_SMS: case SMS:
icon_id = PebbleIconID.GENERIC_SMS; icon_id = PebbleIconID.GENERIC_SMS;
color_id = PebbleColor.VividViolet; color_id = PebbleColor.VividViolet;
break; break;
default: default:
switch (notificationKind) { switch (notificationType) {
case TWITTER: case TWITTER:
icon_id = PebbleIconID.NOTIFICATION_TWITTER; icon_id = PebbleIconID.NOTIFICATION_TWITTER;
color_id = PebbleColor.BlueMoon; color_id = PebbleColor.BlueMoon;

View File

@ -51,6 +51,6 @@ public class WeatherNeatSupport {
public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) { public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes(); GBDeviceEventSendBytes sendBytes = new GBDeviceEventSendBytes();
sendBytes.encodedBytes = encodeWeatherNeatMessage("Berlin", "22 C", "cloudy", 0); 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.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler; 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.model.ServiceCommand;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
@ -108,20 +108,8 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
} }
@Override @Override
public void onSMS(String from, String body) { public void onNotification(NotificationSpec notificationSpec) {
byte[] bytes = gbDeviceProtocol.encodeSMS(from, body); byte[] bytes = gbDeviceProtocol.encodeNotification(notificationSpec);
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);
sendToDevice(bytes); sendToDevice(bytes);
} }

View File

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

View File

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

View File

@ -51,6 +51,7 @@ public class FileUtils {
* Reads the contents of the given InputStream into a byte array, but does not * 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, * read more than maxLen bytes. If the stream provides more than maxLen bytes,
* an IOException is thrown. * 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 * @param maxLen the maximum number of bytes to read/return
* @return the bytes read from the InputStream * @return the bytes read from the InputStream

View File

@ -355,7 +355,7 @@ public class GB {
notificationIntent, 0); notificationIntent, 0);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context) 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) .setContentText(text)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_notification_low_battery) .setSmallIcon(R.drawable.ic_notification_low_battery)