mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-02-04 14:07:32 +01:00
Merge remote-tracking branch 'origin/master' into low_battery_notification
Conflicts: app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java
This commit is contained in:
commit
6ebc727f97
@ -1,5 +1,9 @@
|
||||
###Changelog
|
||||
|
||||
####Version 0.5.1
|
||||
* Pebble: support taking screenshot from Pebble Time
|
||||
* Fix broken "find lost device" which was broken in 0.5.0
|
||||
|
||||
####Version 0.5.0
|
||||
* Mi Band: fix setting wear location
|
||||
* Pebble: experimental watchapp installation support for FW 3.x/Pebble Time
|
||||
|
@ -11,6 +11,8 @@ need to create an account and transmit any of your data to the vendor's servers.
|
||||
|
||||
[![Gadgetbridge on F-Droid](/Get_it_on_F-Droid.svg.png?raw=true "Download from F-Droid")](https://f-droid.org/repository/browse/?fdid=nodomain.freeyourgadget.gadgetbridge)
|
||||
|
||||
[List of changes](CHANGELOG.md)
|
||||
|
||||
## Features (Pebble)
|
||||
|
||||
* Incoming calls notification and display (caller, phone number)
|
||||
|
@ -12,8 +12,8 @@ android {
|
||||
applicationId "nodomain.freeyourgadget.gadgetbridge"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 21
|
||||
versionCode 21
|
||||
versionName "0.5.0"
|
||||
versionCode 22
|
||||
versionName "0.5.1"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@ -31,9 +31,16 @@ android {
|
||||
// optional path to report (default will be lint-results.html in the builddir)
|
||||
htmlOutput file("$project.buildDir/reports/lint/lint.html")
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.returnDefaultValues = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "org.mockito:mockito-core:1.9.5"
|
||||
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:21.0.3'
|
||||
compile 'com.android.support:support-v4:21.0.3'
|
||||
@ -41,9 +48,6 @@ dependencies {
|
||||
compile 'org.slf4j:slf4j-api:1.7.7'
|
||||
compile 'com.github.PhilJay:MPAndroidChart:2.1.0'
|
||||
compile 'com.github.pfichtner:durationformatter:0.1.1'
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
// testCompile "org.mockito:mockito-core:1.9.5"
|
||||
}
|
||||
|
||||
check.dependsOn 'findbugs', 'pmd', 'lint'
|
||||
|
@ -25,6 +25,10 @@
|
||||
android:name="android.hardware.bluetooth_le"
|
||||
android:required="false" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.telephony"
|
||||
android:required="false" />
|
||||
|
||||
<application
|
||||
android:name=".GBApplication"
|
||||
android:allowBackup="true"
|
||||
|
@ -21,8 +21,8 @@ import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class GBApplication extends Application {
|
||||
// Since this class must not log to slf4j, we use plain android.util.Log
|
||||
@ -39,7 +39,7 @@ public class GBApplication extends Application {
|
||||
}
|
||||
|
||||
protected DeviceService createDeviceService() {
|
||||
return new GBDeviceService(this, DeviceCommunicationService.class);
|
||||
return new GBDeviceService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,6 +55,7 @@ public class GBApplication extends Application {
|
||||
// StatusPrinter.print(lc);
|
||||
// Logger logger = LoggerFactory.getLogger(GBApplication.class);
|
||||
|
||||
GB.environment = GBEnvironment.createDeviceEnvironment();
|
||||
mActivityDatabaseHandler = new ActivityDatabaseHandler(context);
|
||||
// for testing DB stuff
|
||||
// SQLiteDatabase db = mActivityDatabaseHandler.getWritableDatabase();
|
||||
|
@ -0,0 +1,26 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge;
|
||||
|
||||
public class GBEnvironment {
|
||||
private boolean localTest;
|
||||
private boolean deviceTest;
|
||||
|
||||
public static GBEnvironment createLocalTestEnvironment() {
|
||||
GBEnvironment env = new GBEnvironment();
|
||||
env.localTest = true;
|
||||
return env;
|
||||
}
|
||||
|
||||
public static GBEnvironment createDeviceEnvironment() {
|
||||
GBEnvironment env = new GBEnvironment();
|
||||
return env;
|
||||
}
|
||||
|
||||
public final boolean isTest() {
|
||||
return localTest || deviceTest;
|
||||
}
|
||||
|
||||
public boolean isLocalTest() {
|
||||
return localTest;
|
||||
}
|
||||
|
||||
}
|
@ -12,17 +12,18 @@ import java.util.UUID;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
|
||||
|
||||
public class GBDeviceService implements DeviceService {
|
||||
protected final Context mContext;
|
||||
protected final Class<? extends Service> mServiceClass;
|
||||
|
||||
public GBDeviceService(Context context, Class<? extends Service> serviceClass) {
|
||||
public GBDeviceService(Context context) {
|
||||
mContext = context;
|
||||
mServiceClass = serviceClass;
|
||||
mServiceClass = DeviceCommunicationService.class;
|
||||
}
|
||||
|
||||
private Intent createIntent() {
|
||||
protected Intent createIntent() {
|
||||
Intent startIntent = new Intent(mContext, mServiceClass);
|
||||
return startIntent;
|
||||
}
|
||||
@ -174,7 +175,7 @@ public class GBDeviceService implements DeviceService {
|
||||
@Override
|
||||
public void onFindDevice(boolean start) {
|
||||
Intent intent = createIntent().setAction(ACTION_FIND_DEVICE)
|
||||
.putExtra(EXTRA_APP_UUID, start);
|
||||
.putExtra(EXTRA_FIND_START, start);
|
||||
invokeService(intent);
|
||||
}
|
||||
|
||||
|
@ -3,5 +3,5 @@ package nodomain.freeyourgadget.gadgetbridge.model;
|
||||
public enum DeviceType {
|
||||
UNKNOWN,
|
||||
PEBBLE,
|
||||
MIBAND
|
||||
TEST, MIBAND
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import android.net.Uri;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -27,13 +28,48 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.*;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_CALLSTATE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_CONNECT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DELETEAPP;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DISCONNECT;
|
||||
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_REBOOT;
|
||||
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_SCREENSHOT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETMUSICINFO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETTIME;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_ALARMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_STARTAPP;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_ALARMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_UUID;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_COMMAND;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_PHONENUMBER;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_DEVICE_ADDRESS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_FIND_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ALBUM;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ARTIST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACK;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_BODY;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SENDER;
|
||||
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_PERFORM_PAIR;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI;
|
||||
|
||||
public class DeviceCommunicationService extends Service {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
|
||||
|
||||
private boolean mStarted = false;
|
||||
|
||||
private DeviceSupportFactory mFactory;
|
||||
private GBDevice mGBDevice = null;
|
||||
private DeviceSupport mDeviceSupport;
|
||||
|
||||
@ -60,6 +96,7 @@ public class DeviceCommunicationService extends Service {
|
||||
LOG.debug("DeviceCommunicationService is being created");
|
||||
super.onCreate();
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(GBDevice.ACTION_DEVICE_CHANGED));
|
||||
mFactory = new DeviceSupportFactory(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -107,32 +144,29 @@ public class DeviceCommunicationService extends Service {
|
||||
start(); // ensure started
|
||||
String btDeviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
if (btDeviceAddress == null) {
|
||||
btDeviceAddress = sharedPrefs.getString("last_device_address", null);
|
||||
} else {
|
||||
sharedPrefs.edit().putString("last_device_address", btDeviceAddress).apply();
|
||||
if (sharedPrefs != null) { // may be null in test cases
|
||||
if (btDeviceAddress == null) {
|
||||
btDeviceAddress = sharedPrefs.getString("last_device_address", null);
|
||||
} else {
|
||||
sharedPrefs.edit().putString("last_device_address", btDeviceAddress).apply();
|
||||
}
|
||||
}
|
||||
|
||||
if (btDeviceAddress != null && !isConnecting() && !isConnected()) {
|
||||
if (mDeviceSupport != null) {
|
||||
mDeviceSupport.dispose();
|
||||
mDeviceSupport = null;
|
||||
}
|
||||
setDeviceSupport(null);
|
||||
try {
|
||||
DeviceSupportFactory factory = new DeviceSupportFactory(this);
|
||||
mDeviceSupport = factory.createDeviceSupport(btDeviceAddress);
|
||||
if (mDeviceSupport != null) {
|
||||
mGBDevice = mDeviceSupport.getDevice();
|
||||
DeviceSupport deviceSupport = mFactory.createDeviceSupport(btDeviceAddress);
|
||||
if (deviceSupport != null) {
|
||||
setDeviceSupport(deviceSupport);
|
||||
if (pair) {
|
||||
mDeviceSupport.pair();
|
||||
deviceSupport.pair();
|
||||
} else {
|
||||
mDeviceSupport.connect();
|
||||
deviceSupport.connect();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
GB.toast(this, getString(R.string.cannot_connect, e.getMessage()), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
mDeviceSupport = null;
|
||||
mGBDevice = null;
|
||||
setDeviceSupport(null);
|
||||
}
|
||||
} else if (mGBDevice != null) {
|
||||
// send an update at least
|
||||
@ -231,6 +265,29 @@ public class DeviceCommunicationService extends Service {
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing!
|
||||
* @param factory
|
||||
*/
|
||||
public void setDeviceSupportFactory(DeviceSupportFactory factory) {
|
||||
mFactory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the current DeviceSupport instance (if any) and sets a new device support instance
|
||||
* (if not null).
|
||||
* @param deviceSupport
|
||||
*/
|
||||
private void setDeviceSupport(@Nullable DeviceSupport deviceSupport) {
|
||||
if (deviceSupport != mDeviceSupport && mDeviceSupport != null) {
|
||||
mDeviceSupport.dispose();
|
||||
mDeviceSupport = null;
|
||||
mGBDevice = null;
|
||||
}
|
||||
mDeviceSupport = deviceSupport;
|
||||
mGBDevice = mDeviceSupport != null ? mDeviceSupport.getDevice() : null;
|
||||
}
|
||||
|
||||
private void start() {
|
||||
if (!mStarted) {
|
||||
startForeground(GB.NOTIFICATION_ID, GB.createNotification(getString(R.string.gadgetbridge_running), this));
|
||||
@ -238,6 +295,10 @@ public class DeviceCommunicationService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return mStarted;
|
||||
}
|
||||
|
||||
private boolean isConnected() {
|
||||
return mGBDevice != null && mGBDevice.isConnected();
|
||||
}
|
||||
@ -258,9 +319,7 @@ public class DeviceCommunicationService extends Service {
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
|
||||
GB.setReceiversEnableState(false, this); // disable BroadcastReceivers
|
||||
|
||||
if (mDeviceSupport != null) {
|
||||
mDeviceSupport.dispose();
|
||||
}
|
||||
setDeviceSupport(null);
|
||||
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.cancel(GB.NOTIFICATION_ID); // need to do this because the updated notification wont be cancelled when service stops
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
@ -26,10 +27,17 @@ public class DeviceSupportFactory {
|
||||
|
||||
public synchronized DeviceSupport createDeviceSupport(String deviceAddress) throws GBException {
|
||||
DeviceSupport deviceSupport;
|
||||
if (deviceAddress.indexOf(":") == deviceAddress.lastIndexOf(":")) { // only one colon
|
||||
deviceSupport = createTCPDeviceSupport(deviceAddress);
|
||||
int indexFirstColon = deviceAddress.indexOf(":");
|
||||
if (indexFirstColon > 0) {
|
||||
if (indexFirstColon == deviceAddress.lastIndexOf(":")) { // only one colon
|
||||
deviceSupport = createTCPDeviceSupport(deviceAddress);
|
||||
} else {
|
||||
// multiple colons -- bt?
|
||||
deviceSupport = createBTDeviceSupport(deviceAddress);
|
||||
}
|
||||
} else {
|
||||
deviceSupport = createBTDeviceSupport(deviceAddress);
|
||||
// no colon at all, maybe a class name?
|
||||
deviceSupport = createClassNameDeviceSupport(deviceAddress);
|
||||
}
|
||||
|
||||
if (deviceSupport != null) {
|
||||
@ -41,6 +49,21 @@ public class DeviceSupportFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
private DeviceSupport createClassNameDeviceSupport(String className) throws GBException {
|
||||
try {
|
||||
Class<?> deviceSupportClass = Class.forName(className);
|
||||
Constructor<?> constructor = deviceSupportClass.getConstructor();
|
||||
DeviceSupport support = (DeviceSupport) constructor.newInstance();
|
||||
// has to create the device itself
|
||||
support.setContext(null, null, mContext);
|
||||
return support;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null; // not a class, or not known at least
|
||||
} catch (Exception e) {
|
||||
throw new GBException("Error creating DeviceSupport instance for " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBtAvailability() {
|
||||
if (mBtAdapter == null) {
|
||||
GB.toast(mContext.getString(R.string.bluetooth_is_not_supported_), Toast.LENGTH_SHORT, GB.WARN);
|
||||
|
@ -202,6 +202,97 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
GBDeviceEventScreenshot mDevEventScreenshot = null;
|
||||
int mScreenshotRemaining = -1;
|
||||
|
||||
//monochrome black + white
|
||||
static final byte[] clut_pebble = {
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
(byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00
|
||||
};
|
||||
|
||||
// linear BGR222 (6 bit, 64 entries)
|
||||
static final byte[] clut_pebbletime = new byte[]{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x55, 0x00, 0x00, 0x00,
|
||||
(byte) 0xaa, 0x00, 0x00, 0x00,
|
||||
(byte) 0xff, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x55, 0x00, 0x00,
|
||||
0x55, 0x55, 0x00, 0x00,
|
||||
(byte) 0xaa, 0x55, 0x00, 0x00,
|
||||
(byte) 0xff, 0x55, 0x00, 0x00,
|
||||
|
||||
0x00, (byte) 0xaa, 0x00, 0x00,
|
||||
0x55, (byte) 0xaa, 0x00, 0x00,
|
||||
(byte) 0xaa, (byte) 0xaa, 0x00, 0x00,
|
||||
(byte) 0xff, (byte) 0xaa, 0x00, 0x00,
|
||||
|
||||
0x00, (byte) 0xff, 0x00, 0x00,
|
||||
0x55, (byte) 0xff, 0x00, 0x00,
|
||||
(byte) 0xaa, (byte) 0xff, 0x00, 0x00,
|
||||
(byte) 0xff, (byte) 0xff, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x55, 0x00,
|
||||
0x55, 0x00, 0x55, 0x00,
|
||||
(byte) 0xaa, 0x00, 0x55, 0x00,
|
||||
(byte) 0xff, 0x00, 0x55, 0x00,
|
||||
|
||||
0x00, 0x55, 0x55, 0x00,
|
||||
0x55, 0x55, 0x55, 0x00,
|
||||
(byte) 0xaa, 0x55, 0x55, 0x00,
|
||||
(byte) 0xff, 0x55, 0x55, 0x00,
|
||||
|
||||
0x00, (byte) 0xaa, 0x55, 0x00,
|
||||
0x55, (byte) 0xaa, 0x55, 0x00,
|
||||
(byte) 0xaa, (byte) 0xaa, 0x55, 0x00,
|
||||
(byte) 0xff, (byte) 0xaa, 0x55, 0x00,
|
||||
|
||||
0x00, (byte) 0xff, 0x55, 0x00,
|
||||
0x55, (byte) 0xff, 0x55, 0x00,
|
||||
(byte) 0xaa, (byte) 0xff, 0x55, 0x00,
|
||||
(byte) 0xff, (byte) 0xff, 0x55, 0x00,
|
||||
|
||||
0x00, 0x00, (byte) 0xaa, 0x00,
|
||||
0x55, 0x00, (byte) 0xaa, 0x00,
|
||||
(byte) 0xaa, 0x00, (byte) 0xaa, 0x00,
|
||||
(byte) 0xff, 0x00, (byte) 0xaa, 0x00,
|
||||
|
||||
0x00, 0x55, (byte) 0xaa, 0x00,
|
||||
0x55, 0x55, (byte) 0xaa, 0x00,
|
||||
(byte) 0xaa, 0x55, (byte) 0xaa, 0x00,
|
||||
(byte) 0xff, 0x55, (byte) 0xaa, 0x00,
|
||||
|
||||
0x00, (byte) 0xaa, (byte) 0xaa, 0x00,
|
||||
0x55, (byte) 0xaa, (byte) 0xaa, 0x00,
|
||||
(byte) 0xaa, (byte) 0xaa, (byte) 0xaa, 0x00,
|
||||
(byte) 0xff, (byte) 0xaa, (byte) 0xaa, 0x00,
|
||||
|
||||
0x00, (byte) 0xff, (byte) 0xaa, 0x00,
|
||||
0x55, (byte) 0xff, (byte) 0xaa, 0x00,
|
||||
(byte) 0xaa, (byte) 0xff, (byte) 0xaa, 0x00,
|
||||
(byte) 0xff, (byte) 0xff, (byte) 0xaa, 0x00,
|
||||
|
||||
0x00, 0x00, (byte) 0xff, 0x00,
|
||||
0x55, 0x00, (byte) 0xff, 0x00,
|
||||
(byte) 0xaa, 0x00, (byte) 0xff, 0x00,
|
||||
(byte) 0xff, 0x00, (byte) 0xff, 0x00,
|
||||
|
||||
0x00, 0x55, (byte) 0xff, 0x00,
|
||||
0x55, 0x55, (byte) 0xff, 0x00,
|
||||
(byte) 0xaa, 0x55, (byte) 0xff, 0x00,
|
||||
(byte) 0xff, 0x55, (byte) 0xff, 0x00,
|
||||
|
||||
0x00, (byte) 0xaa, (byte) 0xff, 0x00,
|
||||
0x55, (byte) 0xaa, (byte) 0xff, 0x00,
|
||||
(byte) 0xaa, (byte) 0xaa, (byte) 0xff, 0x00,
|
||||
(byte) 0xff, (byte) 0xaa, (byte) 0xff, 0x00,
|
||||
|
||||
0x00, (byte) 0xff, (byte) 0xff, 0x00,
|
||||
0x55, (byte) 0xff, (byte) 0xff, 0x00,
|
||||
(byte) 0xaa, (byte) 0xff, (byte) 0xff, 0x00,
|
||||
(byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00,
|
||||
|
||||
};
|
||||
|
||||
|
||||
byte last_id = -1;
|
||||
private ArrayList<UUID> tmpUUIDS = new ArrayList<>();
|
||||
|
||||
@ -921,34 +1012,38 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
byte result = buf.get();
|
||||
mDevEventScreenshot = new GBDeviceEventScreenshot();
|
||||
int version = buf.getInt();
|
||||
if (result != 0 || version != 1) { // pebble time not yet
|
||||
if (result != 0) {
|
||||
return null;
|
||||
}
|
||||
mDevEventScreenshot.width = buf.getInt();
|
||||
mDevEventScreenshot.height = buf.getInt();
|
||||
mDevEventScreenshot.bpp = 1;
|
||||
mDevEventScreenshot.clut = new byte[]{
|
||||
0x00, 0x00, 0x00, 0x00, (byte) 0xff,
|
||||
(byte) 0xff, (byte) 0xff, 0x00
|
||||
};
|
||||
|
||||
mScreenshotRemaining = (mDevEventScreenshot.width * mDevEventScreenshot.height) / 8;
|
||||
if (mScreenshotRemaining > 50000) {
|
||||
mScreenshotRemaining = -1; // ignore too big values
|
||||
return null;
|
||||
if (version == 1) {
|
||||
mDevEventScreenshot.bpp = 1;
|
||||
mDevEventScreenshot.clut = clut_pebble;
|
||||
} else {
|
||||
mDevEventScreenshot.bpp = 8;
|
||||
mDevEventScreenshot.clut = clut_pebbletime;
|
||||
}
|
||||
|
||||
mScreenshotRemaining = (mDevEventScreenshot.width * mDevEventScreenshot.height * mDevEventScreenshot.bpp) / 8;
|
||||
|
||||
mDevEventScreenshot.data = new byte[mScreenshotRemaining];
|
||||
length -= 13;
|
||||
}
|
||||
if (mScreenshotRemaining == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
byte corrected = reverseBits(buf.get());
|
||||
byte corrected = buf.get();
|
||||
if (mDevEventScreenshot.bpp == 1) {
|
||||
corrected = reverseBits(corrected);
|
||||
} else {
|
||||
corrected = (byte) (corrected & 0b00111111);
|
||||
}
|
||||
|
||||
mDevEventScreenshot.data[mDevEventScreenshot.data.length - mScreenshotRemaining + i] = corrected;
|
||||
}
|
||||
|
||||
mScreenshotRemaining -= length;
|
||||
LOG.info("Screenshot remaining bytes " + mScreenshotRemaining);
|
||||
if (mScreenshotRemaining == 0) {
|
||||
|
@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBEnvironment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot;
|
||||
@ -43,6 +44,7 @@ public class GB {
|
||||
public static final int INFO = 1;
|
||||
public static final int WARN = 2;
|
||||
public static final int ERROR = 3;
|
||||
public static GBEnvironment environment;
|
||||
|
||||
public static Notification createNotification(String text, Context context) {
|
||||
Intent notificationIntent = new Intent(context, ControlCenter.class);
|
||||
@ -152,16 +154,16 @@ public class GB {
|
||||
headerbuf.putInt(screenshot.width);
|
||||
headerbuf.putInt(-screenshot.height);
|
||||
headerbuf.putShort((short) 1); // planes
|
||||
headerbuf.putShort((short) 1); // bit count
|
||||
headerbuf.putShort((short) screenshot.bpp);
|
||||
headerbuf.putInt(0); // compression
|
||||
headerbuf.putInt(0); // length of pixeldata in byte (uncompressed=0)
|
||||
headerbuf.putInt(0); // pixels per meter (x)
|
||||
headerbuf.putInt(0); // pixels per meter (y)
|
||||
headerbuf.putInt(2); // number of colors in CLUT
|
||||
headerbuf.putInt(2); // numbers of used colors
|
||||
headerbuf.putInt(screenshot.clut.length / 4); // number of colors in CLUT
|
||||
headerbuf.putInt(0); // numbers of used colors
|
||||
headerbuf.put(screenshot.clut);
|
||||
fos.write(headerbuf.array());
|
||||
int rowbytes = screenshot.width / 8;
|
||||
int rowbytes = (screenshot.width * screenshot.bpp) / 8;
|
||||
byte[] pad = new byte[rowbytes % 4];
|
||||
for (int i = 0; i < screenshot.height; i++) {
|
||||
fos.write(screenshot.data, rowbytes * i, rowbytes);
|
||||
@ -225,6 +227,9 @@ public class GB {
|
||||
* @param ex optional exception to be logged
|
||||
*/
|
||||
public static void toast(final Context context, final String message, final int displayTime, final int severity, final Throwable ex) {
|
||||
if (env().isLocalTest()) {
|
||||
return;
|
||||
}
|
||||
Looper mainLooper = Looper.getMainLooper();
|
||||
if (Thread.currentThread() == mainLooper.getThread()) {
|
||||
log(message, severity, ex);
|
||||
@ -321,4 +326,8 @@ public class GB {
|
||||
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify(NOTIFICATION_ID_LOW_BATTERY, notification);
|
||||
}
|
||||
|
||||
public static GBEnvironment env() {
|
||||
return environment;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,97 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.test.GBMockApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.test.GBMockContext;
|
||||
import nodomain.freeyourgadget.gadgetbridge.test.GBMockPackageManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.test.MockHelper;
|
||||
|
||||
public abstract class AbstractServiceTestCase<T extends Service> {
|
||||
private static final int ID = -1; // currently not supported
|
||||
private Class<T> mServiceClass;
|
||||
private T mServiceInstance;
|
||||
private Context mContext;
|
||||
private Application mApplication;
|
||||
private boolean wasStarted;
|
||||
private PackageManager mPackageManager;
|
||||
private NotificationManager mNotificationManager;
|
||||
private MockHelper mMockHelper;
|
||||
|
||||
protected AbstractServiceTestCase(Class<T> serviceClass) {
|
||||
mServiceClass = serviceClass;
|
||||
Assert.assertNotNull(serviceClass);
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public T getServiceInstance() {
|
||||
return mServiceInstance;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mMockHelper = new MockHelper();
|
||||
mPackageManager = createPackageManager();
|
||||
mApplication = createApplication(mPackageManager);
|
||||
mContext = createContext(mApplication);
|
||||
mNotificationManager = mMockHelper.createNotificationManager(mContext);
|
||||
mServiceInstance = createService(mServiceClass, mApplication, mNotificationManager);
|
||||
mServiceInstance.onCreate();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mServiceInstance != null) {
|
||||
stopService();
|
||||
}
|
||||
}
|
||||
|
||||
public void startService(Intent intent) {
|
||||
wasStarted = true;
|
||||
mServiceInstance.onStartCommand(intent, Service.START_FLAG_REDELIVERY, ID);
|
||||
}
|
||||
|
||||
public void stopService() {
|
||||
mServiceInstance.onDestroy();
|
||||
mServiceInstance = null;
|
||||
}
|
||||
|
||||
protected Application createApplication(PackageManager packageManager) {
|
||||
return new GBMockApplication(packageManager);
|
||||
}
|
||||
|
||||
protected PackageManager createPackageManager() {
|
||||
return new GBMockPackageManager();
|
||||
}
|
||||
|
||||
protected Application getApplication() {
|
||||
return mApplication;
|
||||
}
|
||||
|
||||
protected Context createContext(final Application application) {
|
||||
return new GBMockContext(application);
|
||||
}
|
||||
|
||||
private T createService(Class<T> serviceClass, Application application, NotificationManager notificationManager) throws Exception {
|
||||
T service = mMockHelper.createService(serviceClass, application);
|
||||
mMockHelper.addSystemServiceTo(service, Context.NOTIFICATION_SERVICE, getNotificationService());
|
||||
return service;
|
||||
}
|
||||
|
||||
private NotificationManager getNotificationService() {
|
||||
return mNotificationManager;
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DeviceCommunicationServiceTestCase extends AbstractServiceTestCase<DeviceCommunicationService> {
|
||||
private static final java.lang.String TEST_DEVICE_ADDRESS = TestDeviceSupport.class.getName();
|
||||
|
||||
/**
|
||||
* Factory that always returns the mockSupport instance
|
||||
*/
|
||||
private class TestDeviceSupportFactory extends DeviceSupportFactory {
|
||||
public TestDeviceSupportFactory(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized DeviceSupport createDeviceSupport(String deviceAddress) throws GBException {
|
||||
return mockSupport;
|
||||
}
|
||||
}
|
||||
|
||||
private TestDeviceService mDeviceService;
|
||||
@Mock
|
||||
private TestDeviceSupport realSupport;
|
||||
private TestDeviceSupport mockSupport;
|
||||
|
||||
public DeviceCommunicationServiceTestCase() {
|
||||
super(DeviceCommunicationService.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mockSupport = null;
|
||||
realSupport = new TestDeviceSupport();
|
||||
realSupport.setContext(new GBDevice(TEST_DEVICE_ADDRESS, "Test Device", DeviceType.TEST), null, getContext());
|
||||
mockSupport = Mockito.spy(realSupport);
|
||||
getServiceInstance().setDeviceSupportFactory(new TestDeviceSupportFactory(getContext()));
|
||||
|
||||
mDeviceService = new TestDeviceService(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStart() {
|
||||
assertFalse("Service was already", getServiceInstance().isStarted());
|
||||
mDeviceService.start();
|
||||
assertTrue("Service should be started", getServiceInstance().isStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureConnected() {
|
||||
mDeviceService.connect(TEST_DEVICE_ADDRESS);
|
||||
Mockito.verify(mockSupport, Mockito.times(1)).connect();
|
||||
assertTrue(realSupport.getDevice().isInitialized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindDevice() {
|
||||
ensureConnected();
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockSupport);
|
||||
mDeviceService.onFindDevice(true);
|
||||
mDeviceService.onFindDevice(false);
|
||||
inOrder.verify(mockSupport, Mockito.times(1)).onFindDevice(true);
|
||||
inOrder.verify(mockSupport, Mockito.times(1)).onFindDevice(false);
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.test.GBMockIntent;
|
||||
|
||||
public class TestDeviceService extends GBDeviceService {
|
||||
private final AbstractServiceTestCase<?> mTestCase;
|
||||
|
||||
public TestDeviceService(AbstractServiceTestCase<?> testCase) throws Exception {
|
||||
super(testCase.getContext());
|
||||
mTestCase = testCase;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent createIntent() {
|
||||
return new GBMockIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invokeService(Intent intent) {
|
||||
mTestCase.startService(intent);
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ServiceCommand;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
|
||||
|
||||
public class TestDeviceSupport extends AbstractDeviceSupport {
|
||||
|
||||
public TestDeviceSupport() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context) {
|
||||
gbDevice = new GBDevice(getClass().getName(), "Test Device", DeviceType.TEST);
|
||||
super.setContext(gbDevice, btAdapter, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connect() {
|
||||
gbDevice.setState(GBDevice.State.INITIALIZED);
|
||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAutoConnect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pair() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSMS(String from, String body) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmail(String from, String subject, String body) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericNotification(String title, String details) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetTime() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetCallState(@Nullable String number, @Nullable String name, ServiceCommand command) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetMusicInfo(String artist, String album, String track) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInstallApp(Uri uri) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppInfoReq() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppStart(UUID uuid) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppDelete(UUID uuid) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFetchActivityData() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReboot() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFindDevice(boolean start) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScreenshotReq() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.test.mock.MockApplication;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBEnvironment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class GBMockApplication extends MockApplication {
|
||||
private final PackageManager mPackageManager;
|
||||
|
||||
public GBMockApplication(PackageManager packageManager) {
|
||||
GB.environment = GBEnvironment.createDeviceEnvironment().createLocalTestEnvironment();
|
||||
mPackageManager = packageManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return mPackageManager;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.test.mock.MockContext;
|
||||
|
||||
public class GBMockContext extends MockContext {
|
||||
private final Application mApplication;
|
||||
|
||||
public GBMockContext(Application application) {
|
||||
mApplication = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return mApplication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return mApplication.getPackageManager();
|
||||
}
|
||||
}
|
@ -0,0 +1,387 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GBMockIntent extends Intent {
|
||||
private String mAction;
|
||||
private Map<String,Object> extras = new HashMap<>();
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent setAction(String action) {
|
||||
mAction = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAction() {
|
||||
return mAction;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, boolean value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, byte value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, char value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, short value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, int value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, long value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, float value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, double value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, String value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, CharSequence value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, Parcelable value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, Parcelable[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putStringArrayListExtra(String name, ArrayList<String> value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putCharSequenceArrayListExtra(String name, ArrayList<CharSequence> value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, Serializable value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, boolean[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, byte[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, short[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, char[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, int[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, long[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, float[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, double[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, String[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, CharSequence[] value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Intent putExtra(String name, Bundle value) {
|
||||
extras.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBooleanExtra(String name, boolean defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (boolean) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByteExtra(String name, byte defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (byte) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShortExtra(String name, short defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (short) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getCharExtra(String name, char defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (char) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntExtra(String name, int defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (int) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongExtra(String name, long defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (long) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloatExtra(String name, float defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (float) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDoubleExtra(String name, double defaultValue) {
|
||||
if (extras.containsKey(name)) {
|
||||
return (double) extras.get(name);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharSequenceExtra(String name) {
|
||||
return (CharSequence) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Parcelable> T getParcelableExtra(String name) {
|
||||
return (T) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable[] getParcelableArrayExtra(String name) {
|
||||
return (Parcelable[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
|
||||
return (ArrayList<T>) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getSerializableExtra(String name) {
|
||||
return (Serializable) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Integer> getIntegerArrayListExtra(String name) {
|
||||
return (ArrayList<Integer>) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getStringArrayListExtra(String name) {
|
||||
return (ArrayList<String>) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
|
||||
return (ArrayList<CharSequence>) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getBooleanArrayExtra(String name) {
|
||||
return (boolean[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getByteArrayExtra(String name) {
|
||||
return (byte[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short[] getShortArrayExtra(String name) {
|
||||
return (short[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getCharArrayExtra(String name) {
|
||||
return (char[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIntArrayExtra(String name) {
|
||||
return (int[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getLongArrayExtra(String name) {
|
||||
return (long[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getFloatArrayExtra(String name) {
|
||||
return (float[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getDoubleArrayExtra(String name) {
|
||||
return (double[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getStringArrayExtra(String name) {
|
||||
return (String[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence[] getCharSequenceArrayExtra(String name) {
|
||||
return (CharSequence[]) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringExtra(String name) {
|
||||
return (String) extras.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GBMockIntent: " + mAction;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.test.mock.MockPackageManager;
|
||||
|
||||
public class GBMockPackageManager extends MockPackageManager {
|
||||
@Override
|
||||
public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
public class MockHelper {
|
||||
public <T extends Service> NotificationManager createNotificationManager(Context mContext) throws Exception {
|
||||
Constructor<?>[] constructors = NotificationManager.class.getDeclaredConstructors();
|
||||
constructors[0].setAccessible(true);
|
||||
Class<?>[] parameterTypes = constructors[0].getParameterTypes();
|
||||
return (NotificationManager) constructors[0].newInstance();
|
||||
}
|
||||
|
||||
public <T extends Service> T createService(Class<T> serviceClass, Application application) throws Exception {
|
||||
Constructor<T> constructor = serviceClass.getConstructor();
|
||||
Assert.assertNotNull(constructor);
|
||||
T realService = constructor.newInstance();
|
||||
T mockedService = Mockito.spy(realService);
|
||||
Mockito.when(mockedService.getApplicationContext()).thenReturn(application);
|
||||
Mockito.when(mockedService.getPackageManager()).thenReturn(application.getPackageManager());
|
||||
return mockedService;
|
||||
}
|
||||
|
||||
public void addSystemServiceTo(Context context, String serviceName, Object service) {
|
||||
Mockito.when(context.getSystemService(serviceName)).thenReturn(service);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user