Index: AndroidManifest.xml
===================================================================
--- AndroidManifest.xml
+++ AndroidManifest.xml
@@ -30,6 +30,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:paddingStart="12dip"
+ android:id="@+id/list_item_entry">
Index: res/layout/widget_remotecommandplugin.xml
===================================================================
--- /dev/null
+++ res/layout/widget_remotecommandplugin.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
Index: res/layout/widget_remotecommandplugin_dialog.xml
===================================================================
--- /dev/null
+++ res/layout/widget_remotecommandplugin_dialog.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
Index: res/xml/remotecommandplugin_widget.xml
===================================================================
--- /dev/null
+++ res/xml/remotecommandplugin_widget.xml
@@ -0,0 +1,3 @@
+
+
Index: src/org/kde/kdeconnect/Plugins/RunCommandPlugin/CommandEntry.java
===================================================================
--- src/org/kde/kdeconnect/Plugins/RunCommandPlugin/CommandEntry.java
+++ src/org/kde/kdeconnect/Plugins/RunCommandPlugin/CommandEntry.java
@@ -37,4 +37,8 @@
public String getName() {
return title;
}
+
+ public String getCommand() {
+ return subtitle;
+ }
}
Index: src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandPlugin.java
===================================================================
--- src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandPlugin.java
+++ src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandPlugin.java
@@ -33,6 +33,8 @@
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
public class RunCommandPlugin extends Plugin {
@@ -43,6 +45,7 @@
private ArrayList commandList = new ArrayList<>();
private ArrayList callbacks = new ArrayList<>();
+ private final ArrayList< CommandEntry > commandItems = new ArrayList<>();
private boolean canAddCommand;
@@ -62,6 +65,10 @@
return commandList;
}
+ public ArrayList< CommandEntry > getCommandItems(){
+ return commandItems;
+ }
+
@Override
public String getDisplayName() {
return context.getResources().getString(R.string.pref_plugin_runcommand);
@@ -89,6 +96,7 @@
if (np.has("commandList")) {
commandList.clear();
try {
+ commandItems.clear();
JSONObject obj = new JSONObject(np.getString("commandList"));
Iterator keys = obj.keys();
while (keys.hasNext()) {
@@ -96,7 +104,31 @@
JSONObject o = obj.getJSONObject(s);
o.put("key", s);
commandList.add(o);
+
+ try{
+ commandItems.add(
+ new CommandEntry(
+ o.getString( "name" ),
+ o.getString( "command" ),
+ o.getString( "key" )
+ )
+ );
+ }
+ catch (JSONException e){
+ e.printStackTrace( );
+ }
}
+
+ Collections.sort( commandItems, new Comparator(){
+ @Override
+ public int compare( CommandEntry lhs, CommandEntry rhs ){
+ return lhs.getName( ).compareTo( rhs.getName( ) );
+ }
+ });
+
+ Intent updateWidget = new Intent( context, RunCommandWidget.class );
+ context.sendBroadcast( updateWidget );
+
} catch (JSONException e) {
e.printStackTrace();
}
Index: src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidget.java
===================================================================
--- /dev/null
+++ src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidget.java
@@ -0,0 +1,162 @@
+package org.kde.kdeconnect.Plugins.RunCommandPlugin;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import org.kde.kdeconnect.BackgroundService;
+import org.kde.kdeconnect.Device;
+import org.kde.kdeconnect.Helpers.DeviceHelper;
+import org.kde.kdeconnect_tp.R;
+
+@RequiresApi( api = Build.VERSION_CODES.ICE_CREAM_SANDWICH )
+public class RunCommandWidget extends AppWidgetProvider{
+
+ public static final String RUN_COMMAND_ACTION = "RUN_COMMAND_ACTION";
+ public static final String TARGET_COMMAND = "TARGET_COMMAND";
+ public static final String TARGET_DEVICE = "TARGET_DEVICE";
+ public static final String SET_CURRENT_DEVICE = "SET_CURRENT_DEVICE";
+
+ private static Device currentDevice;
+
+ @Override
+ public void onReceive( Context context, Intent intent ){
+
+ super.onReceive( context, intent );
+
+ if( intent != null && intent.getAction( ) != null && intent.getAction( ).equals( RUN_COMMAND_ACTION ) ){
+
+ final String targetCommand = intent.getStringExtra( TARGET_COMMAND );
+ final String targetDevice = intent.getStringExtra( TARGET_DEVICE );
+
+ BackgroundService.RunCommand( context, new BackgroundService.InstanceCallback( ){
+ @Override
+ public void onServiceStart( BackgroundService service ){
+ RunCommandPlugin plugin = service.getDevice( targetDevice ).getPlugin( RunCommandPlugin.class );
+
+ if( plugin != null ){
+ try{
+
+ plugin.runCommand( targetCommand );
+ }
+ catch( Exception ex ){
+ Log.e( "RunCommandWidget", "Error running command", ex );
+ }
+ }
+ }
+ } );
+ }
+ else if( intent != null && intent.getAction() != null && intent.getAction().equals( SET_CURRENT_DEVICE )){
+ setCurrentDevice( context );
+ }
+
+
+ final Intent newIntent = new Intent( context, RunCommandWidgetDataProviderService.class );
+ context.startService( newIntent );
+ updateWidget( context );
+
+ }
+
+ private void setCurrentDevice( final Context context ){
+ Intent popup = new Intent(context, RunCommandWidgetDeviceSelector.class);
+ popup.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+ context.startActivity( popup );
+ }
+
+ public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds ){
+ updateWidget( context );
+ }
+
+ private void updateWidget( final Context context ){
+
+ if( currentDevice == null || !currentDevice.isReachable() ){
+
+ BackgroundService.RunCommand( context, new BackgroundService.InstanceCallback( ){
+ @Override
+ public void onServiceStart( BackgroundService service ){
+ if( service.getDevices().size() > 0 )
+ currentDevice = service.getDevices().elements().nextElement();
+
+ updateWidgetImpl( context );
+ }
+ } );
+ }
+
+ updateWidgetImpl( context );
+ }
+
+ private void updateWidgetImpl( Context context ){
+
+
+ try{
+
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance( context );
+ int[] appWidgetIds = appWidgetManager.getAppWidgetIds( new ComponentName( context, RunCommandWidget.class ) );
+ RemoteViews views = new RemoteViews( context.getPackageName( ), R.layout.widget_remotecommandplugin );;
+
+ PendingIntent pendingIntent;
+ Intent intent;
+
+ intent = new Intent( context, RunCommandWidget.class );
+ intent.setAction( SET_CURRENT_DEVICE );
+ pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT );
+ views.setOnClickPendingIntent( R.id.runcommandWidgetTitleHeader, pendingIntent );
+
+ if( currentDevice == null || !currentDevice.isReachable() ){
+ views.setTextViewText( R.id.runcommandWidgetTitle, context.getString( R.string.pref_plugin_runcommand ) );
+ views.setViewVisibility( R.id.runcommandslist, View.GONE );
+ views.setViewVisibility( R.id.not_reachable_message, View.VISIBLE );
+ }
+ else{
+ views.setTextViewText( R.id.runcommandWidgetTitle, DeviceHelper.getDeviceName( context ) + "@" + currentDevice.getName( ) );
+ views.setViewVisibility( R.id.runcommandslist, View.VISIBLE );
+ views.setViewVisibility( R.id.not_reachable_message, View.GONE );
+ }
+
+ for( int i = 0; i < appWidgetIds.length; i++ ){
+
+ intent = new Intent( context, RunCommandWidgetDataProviderService.class );
+ intent.putExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[ i ] );
+ intent.setData( Uri.parse( intent.toUri( Intent.URI_INTENT_SCHEME ) ) );
+ views.setRemoteAdapter( R.id.runcommandslist, intent );
+
+ intent = new Intent( context, RunCommandWidget.class );
+ pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT );
+ views.setPendingIntentTemplate( R.id.runcommandslist, pendingIntent );
+
+ AppWidgetManager.getInstance( context ).updateAppWidget( appWidgetIds[ i ], views );
+ }
+
+ }
+ catch( Exception ex ){
+ Log.e( "RunCommandWidget", "Error updating widget", ex );
+ }
+ }
+
+ public static Device getCurrentDevice(){
+ return currentDevice;
+ }
+
+ public static void setCurrentDevice( final Context context, final String DeviceId ){
+ BackgroundService.RunCommand( context, new BackgroundService.InstanceCallback( ){
+ @Override
+ public void onServiceStart( BackgroundService service ){
+ if( service.getDevices().size() > 0 ){
+ currentDevice = service.getDevice( DeviceId );
+ Intent updateWidget = new Intent( context, RunCommandWidget.class );
+ context.sendBroadcast( updateWidget );
+ }
+ }
+ } );
+ }
+}
\ No newline at end of file
Index: src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidgetDataProvider.java
===================================================================
--- /dev/null
+++ src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidgetDataProvider.java
@@ -0,0 +1,89 @@
+package org.kde.kdeconnect.Plugins.RunCommandPlugin;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+import org.kde.kdeconnect_tp.R;
+
+
+@RequiresApi( api = Build.VERSION_CODES.ICE_CREAM_SANDWICH )
+public class RunCommandWidgetDataProvider implements RemoteViewsService.RemoteViewsFactory{
+
+ private RunCommandPlugin runCommandPlugin;
+ private Context mContext;
+
+ public RunCommandWidgetDataProvider( Context context, Intent intent ){
+ mContext = context;
+ }
+
+ private boolean checkPlugin(){
+ if( RunCommandWidget.getCurrentDevice() == null || !RunCommandWidget.getCurrentDevice().isReachable() )
+ return false;
+
+ runCommandPlugin = RunCommandWidget.getCurrentDevice().getPlugin( RunCommandPlugin.class );
+ return runCommandPlugin != null;
+ }
+
+ @Override
+ public void onCreate( ){
+ }
+
+ @Override
+ public void onDataSetChanged( ){
+
+ }
+
+ @Override
+ public void onDestroy( ){
+ }
+
+ @Override
+ public int getCount( ){
+ return checkPlugin() ? runCommandPlugin.getCommandItems().size( ) : 0;
+ }
+
+ @Override
+ public RemoteViews getViewAt( int i ){
+
+ RemoteViews remoteView = new RemoteViews( mContext.getPackageName( ), R.layout.list_item_entry );
+ CommandEntry listItem = runCommandPlugin.getCommandItems().get( i );
+
+ final Intent configIntent = new Intent( mContext, RunCommandWidget.class );
+ configIntent.setAction( RunCommandWidget.RUN_COMMAND_ACTION );
+ configIntent.putExtra( RunCommandWidget.TARGET_COMMAND, listItem.getKey() );
+ configIntent.putExtra( RunCommandWidget.TARGET_DEVICE, RunCommandWidget.getCurrentDevice().getDeviceId() );
+
+ remoteView.setTextViewText( R.id.list_item_entry_title, listItem.getName( ) );
+ remoteView.setTextViewText( R.id.list_item_entry_summary, listItem.getCommand() );
+ remoteView.setViewVisibility( R.id.list_item_entry_summary, View.VISIBLE );
+
+ remoteView.setOnClickFillInIntent( R.id.list_item_entry, configIntent );
+
+ return remoteView;
+ }
+
+ @Override
+ public RemoteViews getLoadingView( ){
+ return null;
+ }
+
+ @Override
+ public int getViewTypeCount( ){
+ return 1;
+ }
+
+ @Override
+ public long getItemId( int i ){
+ return runCommandPlugin.getCommandItems().get( i ).getKey().hashCode( );
+ }
+
+ @Override
+ public boolean hasStableIds( ){
+ return false;
+ }
+}
\ No newline at end of file
Index: src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidgetDataProviderService.java
===================================================================
--- /dev/null
+++ src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidgetDataProviderService.java
@@ -0,0 +1,16 @@
+package org.kde.kdeconnect.Plugins.RunCommandPlugin;
+
+import android.content.Intent;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+import android.widget.RemoteViewsService;
+
+@RequiresApi( api = Build.VERSION_CODES.ICE_CREAM_SANDWICH )
+public class RunCommandWidgetDataProviderService extends RemoteViewsService{
+
+ @Override
+ public RemoteViewsFactory onGetViewFactory( Intent intent ){
+
+ return ( new RunCommandWidgetDataProvider( RunCommandWidgetDataProviderService.this, intent ) );
+ }
+}
\ No newline at end of file
Index: src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidgetDeviceSelector.java
===================================================================
--- /dev/null
+++ src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandWidgetDeviceSelector.java
@@ -0,0 +1,76 @@
+package org.kde.kdeconnect.Plugins.RunCommandPlugin;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.RequiresApi;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import org.kde.kdeconnect.BackgroundService;
+import org.kde.kdeconnect.Device;
+import org.kde.kdeconnect.UserInterface.List.ListAdapter;
+import org.kde.kdeconnect_tp.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+@RequiresApi( api = Build.VERSION_CODES.ICE_CREAM_SANDWICH )
+public class RunCommandWidgetDeviceSelector extends AppCompatActivity{
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+
+ requestWindowFeature( Window.FEATURE_NO_TITLE);
+ setContentView( R.layout.widget_remotecommandplugin_dialog);
+
+ BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
+ @Override
+ public void onServiceStart(final BackgroundService service) {
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ListView view = (ListView) findViewById(R.id.runcommandsdevicelist);
+
+ final ArrayList commandItems = new ArrayList<>();
+
+ for( Device device : service.getDevices().values() ){
+ commandItems.add(
+ new CommandEntry(
+ device.getName(),
+ null,
+ device.getDeviceId()
+ )
+ );
+ }
+
+ Collections.sort(commandItems, new Comparator() {
+ @Override
+ public int compare(ListAdapter.Item lhs, ListAdapter.Item rhs) {
+ String lName = ((CommandEntry) lhs).getName();
+ String rName = ((CommandEntry) rhs).getName();
+ return lName.compareTo(rName);
+ }
+ });
+
+ ListAdapter adapter = new ListAdapter(RunCommandWidgetDeviceSelector.this, commandItems);
+
+ view.setAdapter(adapter);
+ view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick( AdapterView> adapterView, View view, int i, long l) {
+ CommandEntry entry = (CommandEntry) commandItems.get(i);
+ RunCommandWidget.setCurrentDevice( RunCommandWidgetDeviceSelector.this, entry.getKey() );
+ finish();
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+}