-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TIMOB-24510] Android: Support for custom quick settings tiles. (#9310)
* Support for QuickSettings tiles. * Add documentation. * Formatting. Optimize default label and icon code in build script. * Fix indentation. * Fix indentation again. * Add constants. Fix parameters. * Add names. * Extract dictionary with dialog show params. Add returns. * Fix return types. * More indentation. * Last attempt. * Update QuickSettingsService.yml * Change serviceParser. Fix default icon code. Fix parity.html template. * Docs formatting.
- Loading branch information
1 parent
dc4ea45
commit 50f7a4c
Showing
10 changed files
with
623 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
203 changes: 203 additions & 0 deletions
203
...android/src/java/ti/modules/titanium/android/quicksettings/QuickSettingsServiceProxy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
package ti.modules.titanium.android.quicksettings; | ||
|
||
import android.annotation.TargetApi; | ||
import android.app.AlertDialog; | ||
import android.app.Dialog; | ||
import android.content.DialogInterface; | ||
import android.graphics.drawable.Icon; | ||
import android.service.quicksettings.TileService; | ||
|
||
import org.appcelerator.kroll.KrollDict; | ||
import org.appcelerator.kroll.KrollRuntime; | ||
import org.appcelerator.kroll.annotations.Kroll; | ||
import org.appcelerator.kroll.common.Log; | ||
import org.appcelerator.titanium.TiApplication; | ||
import org.appcelerator.titanium.TiC; | ||
import org.appcelerator.titanium.proxy.IntentProxy; | ||
import org.appcelerator.titanium.proxy.ServiceProxy; | ||
import org.appcelerator.titanium.view.TiDrawableReference; | ||
|
||
@TargetApi(24) | ||
@Kroll.proxy | ||
public class QuickSettingsServiceProxy extends ServiceProxy { | ||
|
||
private static final String TAG = "QuickSettingsService"; | ||
|
||
private TileService tileService; | ||
//workaround for dealing with Icon class | ||
private Object pathObject = null; | ||
private AlertDialog.Builder builder; | ||
|
||
public QuickSettingsServiceProxy(TileService serviceInstance) { | ||
tileService = serviceInstance; | ||
} | ||
|
||
//Update the tile with the latest changes | ||
@Kroll.method | ||
public void updateTile() { | ||
tileService.getQsTile().updateTile(); | ||
} | ||
|
||
//Setting Tile's icon | ||
@Kroll.method | ||
public void setIcon(Object path) { | ||
tileService.getQsTile().setIcon(Icon.createWithBitmap(TiDrawableReference.fromObject(TiApplication.getAppRootOrCurrentActivity(),path).getBitmap())); | ||
pathObject = path; | ||
} | ||
|
||
//Setting Tile's state | ||
@Kroll.method | ||
public void setState(int state) { | ||
tileService.getQsTile().setState(state); | ||
} | ||
|
||
//Setting Tile's label | ||
@Kroll.method | ||
public void setLabel(String label) { | ||
tileService.getQsTile().setLabel(label); | ||
} | ||
|
||
//Getting Tile'c icon | ||
@Kroll.method | ||
public Object getIcon() { | ||
return pathObject; | ||
} | ||
|
||
//Getting Tile's state | ||
@Kroll.method | ||
public int getState() { | ||
return tileService.getQsTile().getState(); | ||
} | ||
|
||
//Getting Tile's label | ||
@Kroll.method | ||
public String getLabel() { | ||
return tileService.getQsTile().getLabel().toString(); | ||
} | ||
|
||
//Checks if the lock screen is showing. | ||
@Kroll.method | ||
public final boolean isLocked() { | ||
return tileService.isLocked(); | ||
} | ||
|
||
//Checks if the device is in a secure state. | ||
@Kroll.method | ||
public final boolean isSecure() { | ||
return tileService.isSecure(); | ||
} | ||
|
||
//Used to show a dialog. | ||
@Kroll.method | ||
public void showDialog(KrollDict krollDictionary) { | ||
tileService.showDialog(createDialogFromDictionary(krollDictionary)); | ||
} | ||
|
||
//Start an activity while collapsing the panel. | ||
@Kroll.method | ||
public void startActivityAndCollapse(IntentProxy intent) { | ||
tileService.startActivityAndCollapse(intent.getIntent()); | ||
} | ||
|
||
//Prompts the user to unlock the device before executing the JS file. | ||
@Kroll.method | ||
final void unlockAndRun(final String jsToEvaluate) { | ||
tileService.unlockAndRun(new Runnable() { | ||
@Override | ||
public void run() { | ||
KrollRuntime.getInstance().evalString(jsToEvaluate); | ||
} | ||
}); | ||
} | ||
|
||
private Dialog createDialogFromDictionary(KrollDict krollDict) { | ||
builder = new AlertDialog.Builder(tileService.getApplicationContext()); | ||
String[] buttonText = null; | ||
if (krollDict.containsKey(TiC.PROPERTY_TITLE)) { | ||
builder.setTitle(krollDict.getString(TiC.PROPERTY_TITLE)); | ||
} | ||
if (krollDict.containsKey(TiC.PROPERTY_MESSAGE)) { | ||
builder.setMessage(krollDict.getString(TiC.PROPERTY_MESSAGE)); | ||
} | ||
if (krollDict.containsKey(TiC.PROPERTY_BUTTON_NAMES)) { | ||
buttonText = krollDict.getStringArray(TiC.PROPERTY_BUTTON_NAMES); | ||
} else if (krollDict.containsKey(TiC.PROPERTY_OK)) { | ||
buttonText = new String[]{krollDict.getString(TiC.PROPERTY_OK)}; | ||
} | ||
if (krollDict.containsKey(TiC.PROPERTY_OPTIONS)) { | ||
String[] optionText = krollDict.getStringArray(TiC.PROPERTY_OPTIONS); | ||
int selectedIndex = krollDict.containsKey(TiC.PROPERTY_SELECTED_INDEX) ? krollDict.getInt(TiC.PROPERTY_SELECTED_INDEX) : -1; | ||
if(selectedIndex >= optionText.length){ | ||
Log.d(TAG, "Ooops invalid selected index specified: " + selectedIndex, Log.DEBUG_MODE); | ||
selectedIndex = -1; | ||
} | ||
|
||
processOptions(optionText, selectedIndex); | ||
} | ||
|
||
if (buttonText != null) { | ||
processButtons(buttonText); | ||
} | ||
return builder.create(); | ||
} | ||
|
||
private void processOptions(String[] optionText,int selectedIndex) | ||
{ | ||
builder.setSingleChoiceItems(optionText, selectedIndex , new DialogInterface.OnClickListener() { | ||
public void onClick(DialogInterface dialog, int which) { | ||
KrollDict eventDictionary = new KrollDict(); | ||
eventDictionary.put(TiC.PROPERTY_ITEM_INDEX,which); | ||
fireEvent(TiC.EVENT_TILE_DIALOG_OPTION_SELECTED, eventDictionary); | ||
} | ||
}); | ||
} | ||
|
||
private void processButtons(String[] buttonText) | ||
{ | ||
builder.setPositiveButton(null, null); | ||
builder.setNegativeButton(null, null); | ||
builder.setNeutralButton(null, null); | ||
builder.setOnCancelListener(new DialogInterface.OnCancelListener() { | ||
@Override | ||
public void onCancel(DialogInterface dialog) | ||
{ | ||
dialog.dismiss(); | ||
fireEvent(TiC.EVENT_TILE_DIALOG_CANCELED,null); | ||
} | ||
}); | ||
|
||
for (int id = 0; id < buttonText.length; id++) { | ||
String text = buttonText[id]; | ||
|
||
switch (id) { | ||
case 0: | ||
builder.setPositiveButton(text, new DialogInterface.OnClickListener() { | ||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
fireEvent(TiC.EVENT_TILE_DIALOG_POSITIVE, null); | ||
} | ||
}); | ||
break; | ||
case 1: | ||
builder.setNeutralButton(text, new DialogInterface.OnClickListener() { | ||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
fireEvent(TiC.EVENT_TILE_DIALOG_NEUTRAL, null); | ||
} | ||
}); | ||
break; | ||
case 2: | ||
builder.setNegativeButton(text, new DialogInterface.OnClickListener() { | ||
@Override | ||
public void onClick(DialogInterface dialog, int which) { | ||
fireEvent(TiC.EVENT_TILE_DIALOG_NEGATIVE, null); | ||
} | ||
}); | ||
break; | ||
default: | ||
Log.e(TAG, "Only 3 buttons are supported"); | ||
} | ||
} | ||
} | ||
|
||
} |
60 changes: 60 additions & 0 deletions
60
.../android/src/java/ti/modules/titanium/android/quicksettings/TiJSQuickSettingsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package ti.modules.titanium.android.quicksettings; | ||
|
||
import android.os.Build; | ||
import android.service.quicksettings.TileService; | ||
import android.support.annotation.RequiresApi; | ||
import org.appcelerator.kroll.KrollRuntime; | ||
import org.appcelerator.kroll.util.KrollAssetHelper; | ||
import org.appcelerator.titanium.TiC; | ||
import org.appcelerator.titanium.proxy.ServiceProxy; | ||
|
||
@RequiresApi(api = Build.VERSION_CODES.N) | ||
public class TiJSQuickSettingsService extends TileService{ | ||
|
||
private final ServiceProxy proxy; | ||
|
||
public TiJSQuickSettingsService(String url) { | ||
//create a proxy for this service | ||
proxy = new QuickSettingsServiceProxy(this); | ||
//get the source to be run | ||
String source = KrollAssetHelper.readAsset(url); | ||
//run the module | ||
KrollRuntime.getInstance().runModule(source, url, proxy) ; | ||
} | ||
|
||
//Called when the user clicks on this tile. | ||
@Override | ||
public void onClick() { | ||
proxy.fireEvent(TiC.EVENT_CLICK, null); | ||
} | ||
|
||
//Called when the user adds this tile to Quick Settings. | ||
@Override | ||
public void onTileAdded() { | ||
proxy.fireEvent(TiC.EVENT_TILE_ADDED, null); | ||
} | ||
|
||
//Called when the user removes this tile from Quick Settings. | ||
@Override | ||
public void onTileRemoved() { | ||
proxy.fireEvent(TiC.EVENT_TILE_REMOVED, null); | ||
} | ||
|
||
//Called by the system to notify a Service that it is no longer used and is being removed. | ||
@Override | ||
public void onDestroy() { | ||
proxy.fireEvent(TiC.EVENT_DESTROY, null); | ||
} | ||
|
||
//Called when this tile moves into a listening state. | ||
@Override | ||
public void onStartListening() { | ||
proxy.fireEvent(TiC.EVENT_START_LISTENING, null); | ||
} | ||
|
||
//Called when this tile moves out of the listening state. | ||
@Override | ||
public void onStopListening() { | ||
proxy.fireEvent(TiC.EVENT_STOP_LISTENING, null); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package <%- appid %>; | ||
|
||
import ti.modules.titanium.android.quicksettings.TiJSQuickSettingsService; | ||
|
||
public final class <%- service.classname %> extends TiJSQuickSettingsService { | ||
public <%- service.classname %>() { | ||
super("<%- service.url %>"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<service android:name="<%- serviceName %>" android:label="<%- label %>" android:icon="<%- icon %>" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> | ||
<intent-filter> | ||
<action android:name="android.service.quicksettings.action.QS_TILE"/> | ||
</intent-filter> | ||
</service> |
Oops, something went wrong.