A first stab on Google Device Actions (not working at all yet)
This commit is contained in:
parent
a32a588fa3
commit
c9c5752281
@ -73,6 +73,13 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service android:name="io.guh.nymeaapp.NymeaHomeControlsService" android:label="nymea:app" android:permission="android.permission.BIND_CONTROLS">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.service.controls.ControlProviderService"/>
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
|
||||||
|
|||||||
@ -30,6 +30,8 @@ dependencies {
|
|||||||
compile 'com.google.android.gms:play-services-base:15.0.1'
|
compile 'com.google.android.gms:play-services-base:15.0.1'
|
||||||
compile 'com.google.firebase:firebase-messaging:18.0.0'
|
compile 'com.google.firebase:firebase-messaging:18.0.0'
|
||||||
compile 'com.google.firebase.messaging.cpp:firebase_messaging_cpp@aar'
|
compile 'com.google.firebase.messaging.cpp:firebase_messaging_cpp@aar'
|
||||||
|
implementation 'org.reactivestreams:reactive-streams:1.0.3'
|
||||||
|
implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
|||||||
@ -0,0 +1,127 @@
|
|||||||
|
package io.guh.nymeaapp;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.provider.Settings.System;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.service.controls.ControlsProviderService;
|
||||||
|
import android.service.controls.actions.ControlAction;
|
||||||
|
import android.service.controls.actions.BooleanAction;
|
||||||
|
import android.service.controls.Control;
|
||||||
|
import android.service.controls.DeviceTypes;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.Flow.Publisher;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import io.reactivex.Flowable;
|
||||||
|
import io.reactivex.processors.ReplayProcessor;
|
||||||
|
import org.reactivestreams.FlowAdapters;
|
||||||
|
|
||||||
|
public class NymeaAppHomeControlsService extends ControlsProviderService {
|
||||||
|
|
||||||
|
private ReplayProcessor updatePublisher;
|
||||||
|
private PendingIntent pi;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Publisher createPublisherForAllAvailable() {
|
||||||
|
Context context = getBaseContext();
|
||||||
|
Intent i = new Intent();
|
||||||
|
// PendingIntent pi = PendingIntent.getActivity(context, 1, i, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
pi = PendingIntent.getActivity(context, 1, i, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
List controls = new ArrayList<>();
|
||||||
|
Control control = new Control.StatelessBuilder("123", pi)
|
||||||
|
// Required: The name of the control
|
||||||
|
.setTitle("TestControl")
|
||||||
|
// Required: Usually the room where the control is located
|
||||||
|
.setSubtitle("TestSubtitle")
|
||||||
|
// Optional: Structure where the control is located, an example would be a house
|
||||||
|
.setStructure("TestLocation")
|
||||||
|
// Required: Type of device, i.e., thermostat, light, switch
|
||||||
|
.setDeviceType(DeviceTypes.TYPE_LIGHT) // For example, DeviceTypes.TYPE_THERMOSTAT
|
||||||
|
.build();
|
||||||
|
controls.add(control);
|
||||||
|
// Create more controls here if needed and add it to the ArrayList
|
||||||
|
|
||||||
|
// Uses the RxJava 2 library
|
||||||
|
return FlowAdapters.toFlowPublisher(Flowable.fromIterable(controls));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Publisher createPublisherFor(List controlIds) {
|
||||||
|
Context context = getBaseContext();
|
||||||
|
/* Fill in details for the activity related to this device. On long press,
|
||||||
|
* this Intent will be launched in a bottomsheet. Please design the activity
|
||||||
|
* accordingly to fit a more limited space (about 2/3 screen height).
|
||||||
|
*/
|
||||||
|
Intent i = new Intent();
|
||||||
|
PendingIntent pi = PendingIntent.getActivity(context, 1, i, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
updatePublisher = ReplayProcessor.create();
|
||||||
|
|
||||||
|
// For each controlId in controlIds
|
||||||
|
|
||||||
|
if (controlIds.contains(123)) {
|
||||||
|
Control control = new Control.StatefulBuilder("123", pi)
|
||||||
|
// Required: The name of the control
|
||||||
|
.setTitle("TestTitle")
|
||||||
|
// Required: Usually the room where the control is located
|
||||||
|
.setSubtitle("TestSubTitle")
|
||||||
|
// Optional: Structure where the control is located, an example would be a house
|
||||||
|
.setStructure("TestStructure")
|
||||||
|
// Required: Type of device, i.e., thermostat, light, switch
|
||||||
|
.setDeviceType(DeviceTypes.TYPE_LIGHT) // For example, DeviceTypes.TYPE_THERMOSTAT
|
||||||
|
// Required: Current status of the device
|
||||||
|
.setStatus(Control.STATUS_OK) // For example, Control.STATUS_OK
|
||||||
|
.build();
|
||||||
|
|
||||||
|
updatePublisher.onNext(control);
|
||||||
|
}
|
||||||
|
// Uses the Reactive Streams API
|
||||||
|
return FlowAdapters.toFlowPublisher(updatePublisher);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performControlAction(String controlId, ControlAction action, Consumer consumer) {
|
||||||
|
/* First, locate the control identified by the controlId. Once it is located, you can
|
||||||
|
* interpret the action appropriately for that specific device. For instance, the following
|
||||||
|
* assumes that the controlId is associated with a light, and the light can be turned on
|
||||||
|
* or off.
|
||||||
|
*/
|
||||||
|
if (action instanceof BooleanAction) {
|
||||||
|
|
||||||
|
// Inform SystemUI that the action has been received and is being processed
|
||||||
|
consumer.accept(ControlAction.RESPONSE_OK);
|
||||||
|
|
||||||
|
BooleanAction bAction = (BooleanAction) action;
|
||||||
|
// In this example, action.getNewState() will have the requested action: true for “On”,
|
||||||
|
// false for “Off”.
|
||||||
|
|
||||||
|
/* This is where application logic/network requests would be invoked to update the state of
|
||||||
|
* the device.
|
||||||
|
* After updating, the application should use the publisher to update SystemUI with the new
|
||||||
|
* state.
|
||||||
|
*/
|
||||||
|
Control control = new Control.StatefulBuilder("123", pi)
|
||||||
|
// Required: The name of the control
|
||||||
|
.setTitle("TestControl")
|
||||||
|
// Required: Usually the room where the control is located
|
||||||
|
.setSubtitle("TestSubTitle")
|
||||||
|
// Optional: Structure where the control is located, an example would be a house
|
||||||
|
.setStructure("TestStructure")
|
||||||
|
// Required: Type of device, i.e., thermostat, light, switch
|
||||||
|
.setDeviceType(DeviceTypes.TYPE_LIGHT) // For example, DeviceTypes.TYPE_THERMOSTAT
|
||||||
|
// Required: Current status of the device
|
||||||
|
.setStatus(Control.STATUS_OK) // For example, Control.STATUS_OK
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// This is the publisher the application created during the call to createPublisherFor()
|
||||||
|
updatePublisher.onNext(control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user