2014-11-16 23:14:06 -08:00
|
|
|
/*
|
|
|
|
* Copyright 2014 Albert Vaca Cintora <albertvaka@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of
|
|
|
|
* the License or (at your option) version 3 or any later version
|
|
|
|
* accepted by the membership of KDE e.V. (or its successor approved
|
|
|
|
* by the membership of KDE e.V.), which shall act as a proxy
|
|
|
|
* defined in Section 14 of version 3 of the license.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2013-09-05 01:37:59 +02:00
|
|
|
package org.kde.kdeconnect.Plugins;
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
import android.app.Activity;
|
|
|
|
import android.app.AlertDialog;
|
2013-08-16 10:31:01 +02:00
|
|
|
import android.content.Context;
|
2017-05-31 15:51:07 +02:00
|
|
|
import android.content.DialogInterface;
|
2015-01-10 00:31:07 -08:00
|
|
|
import android.content.Intent;
|
2017-05-31 15:51:07 +02:00
|
|
|
import android.content.pm.PackageManager;
|
2013-08-19 19:57:29 +02:00
|
|
|
import android.graphics.drawable.Drawable;
|
2018-01-03 20:49:51 +01:00
|
|
|
import android.os.Build;
|
2017-05-31 15:51:07 +02:00
|
|
|
import android.support.annotation.StringRes;
|
|
|
|
import android.support.v4.app.ActivityCompat;
|
|
|
|
import android.support.v4.content.ContextCompat;
|
2015-04-12 00:11:30 -07:00
|
|
|
import android.view.View;
|
2013-09-03 17:58:59 +02:00
|
|
|
import android.widget.Button;
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2013-09-05 01:37:59 +02:00
|
|
|
import org.kde.kdeconnect.Device;
|
|
|
|
import org.kde.kdeconnect.NetworkPackage;
|
2015-01-10 00:31:07 -08:00
|
|
|
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
|
|
|
import org.kde.kdeconnect.UserInterface.SettingsActivity;
|
2017-05-31 15:51:07 +02:00
|
|
|
import org.kde.kdeconnect_tp.R;
|
2013-08-16 10:31:01 +02:00
|
|
|
|
|
|
|
public abstract class Plugin {
|
|
|
|
|
|
|
|
protected Device device;
|
|
|
|
protected Context context;
|
2017-05-31 15:51:07 +02:00
|
|
|
protected int permissionExplanation = R.string.permission_explanation;
|
2017-07-11 13:50:40 +02:00
|
|
|
protected int optionalPermissionExplanation = R.string.optional_permission_explanation;
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2015-01-10 00:31:07 -08:00
|
|
|
public final void setContext(Context context, Device device) {
|
2013-08-16 10:31:01 +02:00
|
|
|
this.device = device;
|
|
|
|
this.context = context;
|
|
|
|
}
|
|
|
|
|
2015-08-19 21:27:27 +05:30
|
|
|
/**
|
2015-08-27 13:06:24 +05:30
|
|
|
* To receive the network package from the unpaired device, override
|
|
|
|
* listensToUnpairedDevices to return true and this method.
|
2015-08-19 21:27:27 +05:30
|
|
|
*/
|
|
|
|
public boolean onUnpairedDevicePackageReceived(NetworkPackage np) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-27 13:06:24 +05:30
|
|
|
/**
|
|
|
|
* Returns whether this plugin should be loaded or not, to listen to NetworkPackages
|
|
|
|
* from the unpaired devices. By default, returns false.
|
|
|
|
*/
|
|
|
|
public boolean listensToUnpairedDevices() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
/**
|
|
|
|
* Return the internal plugin name, that will be used as a
|
2015-06-06 00:38:51 -07:00
|
|
|
* unique key to distinguish it. Use the class name as key.
|
2013-08-19 19:57:29 +02:00
|
|
|
*/
|
2015-06-06 00:38:51 -07:00
|
|
|
public String getPluginKey() {
|
|
|
|
return getPluginKey(this.getClass());
|
|
|
|
}
|
2018-03-03 16:06:52 +01:00
|
|
|
|
2015-06-06 00:38:51 -07:00
|
|
|
public static String getPluginKey(Class<? extends Plugin> p) {
|
|
|
|
return p.getSimpleName();
|
|
|
|
}
|
2013-08-19 19:57:29 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the human-readable plugin name. This function can
|
|
|
|
* access this.context to provide translated text.
|
|
|
|
*/
|
|
|
|
public abstract String getDisplayName();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the human-readable description of this plugin. This
|
|
|
|
* function can access this.context to provide translated text.
|
|
|
|
*/
|
|
|
|
public abstract String getDescription();
|
|
|
|
|
2015-04-12 00:11:30 -07:00
|
|
|
/**
|
|
|
|
* Return the action name displayed in the main activity, that
|
|
|
|
* will call startMainActivity when clicked
|
|
|
|
*/
|
|
|
|
public String getActionName() {
|
|
|
|
return getDisplayName();
|
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
/**
|
|
|
|
* Return an icon associated to this plugin. This function can
|
|
|
|
* access this.context to load the image from resources.
|
|
|
|
*/
|
2015-04-12 00:11:30 -07:00
|
|
|
public Drawable getIcon() {
|
|
|
|
return null;
|
|
|
|
}
|
2013-08-19 19:57:29 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if this plugin should be enabled on new devices.
|
|
|
|
* This function can access this.context and perform compatibility
|
|
|
|
* checks with the Android version, but can not access this.device.
|
|
|
|
*/
|
2015-04-12 00:11:30 -07:00
|
|
|
public boolean isEnabledByDefault() {
|
|
|
|
return true;
|
|
|
|
}
|
2013-08-19 19:57:29 +02:00
|
|
|
|
2014-09-16 15:45:31 +02:00
|
|
|
/**
|
|
|
|
* Return true if this plugin needs an specific UI settings.
|
|
|
|
*/
|
2015-04-12 00:11:30 -07:00
|
|
|
public boolean hasSettings() {
|
|
|
|
return false;
|
|
|
|
}
|
2014-09-16 15:45:31 +02:00
|
|
|
|
2015-01-10 00:31:07 -08:00
|
|
|
/**
|
|
|
|
* If hasSettings returns true, this will be called when the user
|
|
|
|
* wants to access this plugin preferences and should launch some
|
|
|
|
* kind of interface. The default implementation will launch a
|
|
|
|
* SettingsActivity with content from "yourplugin"_preferences.xml.
|
|
|
|
*/
|
|
|
|
public void startPreferencesActivity(SettingsActivity parentActivity) {
|
|
|
|
Intent intent = new Intent(parentActivity, PluginSettingsActivity.class);
|
|
|
|
intent.putExtra("plugin_display_name", getDisplayName());
|
2015-06-06 00:38:51 -07:00
|
|
|
intent.putExtra("plugin_key", getPluginKey());
|
2015-01-10 00:31:07 -08:00
|
|
|
parentActivity.startActivity(intent);
|
|
|
|
}
|
|
|
|
|
2015-04-12 00:11:30 -07:00
|
|
|
/**
|
|
|
|
* Return true if the plugin should display something in the Device main view
|
|
|
|
*/
|
|
|
|
public boolean hasMainActivity() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implement here what your plugin should do when clicked
|
|
|
|
*/
|
2018-03-03 16:06:52 +01:00
|
|
|
public void startMainActivity(Activity parentActivity) {
|
|
|
|
}
|
2015-04-12 00:11:30 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if the entry for this app should appear in the context menu instead of the main view
|
|
|
|
*/
|
|
|
|
public boolean displayInContextMenu() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
/**
|
|
|
|
* Initialize the listeners and structures in your plugin.
|
|
|
|
* Should return true if initialization was successful.
|
|
|
|
*/
|
2015-04-12 00:11:30 -07:00
|
|
|
public boolean onCreate() {
|
|
|
|
return true;
|
|
|
|
}
|
2013-08-19 19:57:29 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Finish any ongoing operations, remove listeners... so
|
2013-09-03 17:58:59 +02:00
|
|
|
* this object could be garbage collected.
|
2013-08-19 19:57:29 +02:00
|
|
|
*/
|
2018-03-03 16:06:52 +01:00
|
|
|
public void onDestroy() {
|
|
|
|
}
|
2013-08-19 19:57:29 +02:00
|
|
|
|
|
|
|
/**
|
2016-12-11 16:40:11 +01:00
|
|
|
* Called when a plugin receives a package. By convention we return true
|
|
|
|
* when we have done something in response to the package or false
|
|
|
|
* otherwise, even though that value is unused as of now.
|
2013-08-19 19:57:29 +02:00
|
|
|
*/
|
2018-03-03 16:06:52 +01:00
|
|
|
public boolean onPackageReceived(NetworkPackage np) {
|
|
|
|
return false;
|
|
|
|
}
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2015-09-08 14:54:04 -07:00
|
|
|
/**
|
|
|
|
* Should return the list of NetworkPackage types that this plugin can handle
|
|
|
|
*/
|
|
|
|
public abstract String[] getSupportedPackageTypes();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Should return the list of NetworkPackage types that this plugin can send
|
|
|
|
*/
|
|
|
|
public abstract String[] getOutgoingPackageTypes();
|
|
|
|
|
2013-09-03 17:58:59 +02:00
|
|
|
/**
|
|
|
|
* Creates a button that will be displayed in the user interface
|
|
|
|
* It can open an activity or perform any other action that the
|
|
|
|
* plugin would wants to expose to the user. Return null if no
|
|
|
|
* button should be displayed.
|
|
|
|
*/
|
2015-04-12 00:11:30 -07:00
|
|
|
@Deprecated
|
|
|
|
public Button getInterfaceButton(final Activity activity) {
|
|
|
|
if (!hasMainActivity()) return null;
|
|
|
|
Button b = new Button(activity);
|
|
|
|
b.setText(getActionName());
|
|
|
|
b.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
|
|
|
startMainActivity(activity);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return b;
|
|
|
|
}
|
2013-08-21 21:30:25 +02:00
|
|
|
|
2017-05-31 15:51:07 +02:00
|
|
|
public String[] getRequiredPermissions() {
|
|
|
|
return new String[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
public String[] getOptionalPermissions() {
|
|
|
|
return new String[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
//Permission from Manifest.permission.*
|
|
|
|
protected boolean isPermissionGranted(String permission) {
|
|
|
|
int result = ContextCompat.checkSelfPermission(context, permission);
|
|
|
|
return (result == PackageManager.PERMISSION_GRANTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected boolean arePermissionsGranted(String[] permissions) {
|
2018-03-03 16:06:52 +01:00
|
|
|
for (String permission : permissions) {
|
|
|
|
if (!isPermissionGranted(permission)) {
|
2017-05-31 15:51:07 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected AlertDialog requestPermissionDialog(Activity activity, String permissions, @StringRes int reason) {
|
|
|
|
return requestPermissionDialog(activity, new String[]{permissions}, reason);
|
|
|
|
}
|
|
|
|
|
2018-03-03 16:06:52 +01:00
|
|
|
protected AlertDialog requestPermissionDialog(final Activity activity, final String[] permissions, @StringRes int reason) {
|
2017-05-31 15:51:07 +02:00
|
|
|
return new AlertDialog.Builder(activity)
|
|
|
|
.setTitle(getDisplayName())
|
|
|
|
.setMessage(reason)
|
|
|
|
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
|
|
ActivityCompat.requestPermissions(activity, permissions, 0);
|
|
|
|
}
|
|
|
|
})
|
2018-03-03 16:06:52 +01:00
|
|
|
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
2017-05-31 15:51:07 +02:00
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
|
|
//Do nothing
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.create();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If onCreate returns false, should create a dialog explaining
|
|
|
|
* the problem (and how to fix it, if possible) to the user.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public AlertDialog getErrorDialog(Activity deviceActivity) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public AlertDialog getPermissionExplanationDialog(Activity deviceActivity) {
|
2018-03-03 16:06:52 +01:00
|
|
|
return requestPermissionDialog(deviceActivity, getRequiredPermissions(), permissionExplanation);
|
2017-05-31 15:51:07 +02:00
|
|
|
}
|
|
|
|
|
2017-07-11 13:50:40 +02:00
|
|
|
public AlertDialog getOptionalPermissionExplanationDialog(Activity deviceActivity) {
|
2018-03-03 16:06:52 +01:00
|
|
|
return requestPermissionDialog(deviceActivity, getOptionalPermissions(), optionalPermissionExplanation);
|
2017-07-11 13:50:40 +02:00
|
|
|
}
|
|
|
|
|
2018-03-03 16:06:52 +01:00
|
|
|
public boolean checkRequiredPermissions() {
|
2017-07-11 13:50:40 +02:00
|
|
|
return arePermissionsGranted(getRequiredPermissions());
|
|
|
|
}
|
|
|
|
|
2018-03-03 16:06:52 +01:00
|
|
|
public boolean checkOptionalPermissions() {
|
|
|
|
return arePermissionsGranted(getOptionalPermissions());
|
2017-05-31 15:51:07 +02:00
|
|
|
}
|
|
|
|
|
2018-01-03 20:49:51 +01:00
|
|
|
public int getMinSdk() {
|
|
|
|
return Build.VERSION_CODES.BASE;
|
|
|
|
}
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|