2015-08-20 00:59:21 -07: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/>.
|
|
|
|
*/
|
|
|
|
|
2015-09-07 01:49:12 -07:00
|
|
|
package org.kde.kdeconnect.UserInterface;
|
2015-08-20 00:59:21 -07:00
|
|
|
|
|
|
|
import android.app.Activity;
|
2015-09-11 09:24:35 -07:00
|
|
|
import android.app.AlertDialog;
|
2015-09-07 00:11:46 -07:00
|
|
|
import android.content.Context;
|
2015-09-11 09:24:35 -07:00
|
|
|
import android.content.DialogInterface;
|
2015-08-20 00:59:21 -07:00
|
|
|
import android.content.Intent;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.support.v4.app.Fragment;
|
|
|
|
import android.util.Log;
|
2015-09-07 00:11:46 -07:00
|
|
|
import android.view.KeyEvent;
|
2015-08-20 00:59:21 -07:00
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.widget.Button;
|
|
|
|
import android.widget.ListView;
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
import org.kde.kdeconnect.BackgroundService;
|
|
|
|
import org.kde.kdeconnect.Device;
|
2017-02-25 21:12:32 +01:00
|
|
|
import org.kde.kdeconnect.Helpers.NetworkHelper;
|
2015-09-11 09:24:35 -07:00
|
|
|
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
2015-08-20 00:59:21 -07:00
|
|
|
import org.kde.kdeconnect.Plugins.Plugin;
|
|
|
|
import org.kde.kdeconnect.UserInterface.List.CustomItem;
|
|
|
|
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
|
2016-06-09 13:42:15 +02:00
|
|
|
import org.kde.kdeconnect.UserInterface.List.PluginItem;
|
2015-08-20 00:59:21 -07:00
|
|
|
import org.kde.kdeconnect.UserInterface.List.SmallEntryItem;
|
|
|
|
import org.kde.kdeconnect_tp.R;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.ConcurrentModificationException;
|
2016-07-07 17:45:04 +02:00
|
|
|
import java.util.Map;
|
2015-11-12 06:41:14 -08:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
2015-08-20 00:59:21 -07:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Main view. Displays the current device and its plugins
|
|
|
|
*/
|
|
|
|
public class DeviceFragment extends Fragment {
|
2015-08-20 01:00:05 -07:00
|
|
|
|
2017-02-05 15:42:42 +01:00
|
|
|
static final String ARG_DEVICE_ID = "deviceId";
|
2017-07-25 18:14:38 +02:00
|
|
|
static final String ARG_FROM_DEVICE_LIST = "fromDeviceList";
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2017-02-05 15:42:42 +01:00
|
|
|
View rootView;
|
|
|
|
static String mDeviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
|
|
|
|
Device device;
|
2015-08-20 01:00:05 -07:00
|
|
|
|
2018-03-03 17:21:16 +01:00
|
|
|
MainActivity mActivity;
|
2015-09-03 03:05:34 -07:00
|
|
|
|
2017-07-11 13:50:40 +02:00
|
|
|
ArrayList<ListAdapter.Item> pluginListItems;
|
|
|
|
|
|
|
|
public DeviceFragment() {
|
|
|
|
}
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
public DeviceFragment(String deviceId, boolean fromDeviceList) {
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
args.putString(ARG_DEVICE_ID, deviceId);
|
2017-07-24 16:39:00 +02:00
|
|
|
args.putBoolean(ARG_FROM_DEVICE_LIST, fromDeviceList);
|
2015-09-07 00:11:46 -07:00
|
|
|
this.setArguments(args);
|
|
|
|
}
|
|
|
|
|
2018-03-03 17:21:16 +01:00
|
|
|
public DeviceFragment(String deviceId, MainActivity activity) {
|
2017-02-05 15:19:46 +01:00
|
|
|
this.mActivity = activity;
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
args.putString(ARG_DEVICE_ID, deviceId);
|
|
|
|
this.setArguments(args);
|
|
|
|
}
|
|
|
|
|
2015-08-20 01:00:05 -07:00
|
|
|
@Override
|
|
|
|
public void onAttach(Activity activity) {
|
|
|
|
super.onAttach(activity);
|
2018-03-03 17:21:16 +01:00
|
|
|
mActivity = ((MainActivity) getActivity());
|
2015-08-20 01:00:05 -07:00
|
|
|
}
|
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
@Override
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
|
Bundle savedInstanceState) {
|
|
|
|
|
2015-09-07 01:49:12 -07:00
|
|
|
rootView = inflater.inflate(R.layout.activity_device, container, false);
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
final String deviceId = getArguments().getString(ARG_DEVICE_ID);
|
2015-08-20 00:59:21 -07:00
|
|
|
if (deviceId != null) {
|
|
|
|
mDeviceId = deviceId;
|
|
|
|
}
|
|
|
|
|
2015-09-03 03:05:34 -07:00
|
|
|
setHasOptionsMenu(true);
|
|
|
|
|
2015-09-08 05:18:57 -07:00
|
|
|
//Log.e("DeviceFragment", "device: " + deviceId);
|
2015-08-20 00:59:21 -07:00
|
|
|
|
|
|
|
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
|
|
|
@Override
|
|
|
|
public void onServiceStart(BackgroundService service) {
|
|
|
|
device = service.getDevice(mDeviceId);
|
2015-09-03 03:05:34 -07:00
|
|
|
if (device == null) {
|
|
|
|
Log.e("DeviceFragment", "Trying to display a device fragment but the device is not present");
|
|
|
|
mActivity.onDeviceSelected(null);
|
2015-09-07 00:11:46 -07:00
|
|
|
return;
|
2015-09-03 03:05:34 -07:00
|
|
|
}
|
2015-08-20 01:00:05 -07:00
|
|
|
|
|
|
|
mActivity.getSupportActionBar().setTitle(device.getName());
|
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
device.addPairingCallback(pairingCallback);
|
2015-08-20 00:59:21 -07:00
|
|
|
device.addPluginsChangedListener(pluginsChangedListener);
|
2015-09-07 00:11:46 -07:00
|
|
|
|
|
|
|
refreshUI();
|
2015-08-20 01:00:05 -07:00
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-07-11 13:50:40 +02:00
|
|
|
final Button pairButton = (Button) rootView.findViewById(R.id.pair_button);
|
2015-09-07 00:11:46 -07:00
|
|
|
pairButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
|
|
|
pairButton.setVisibility(View.GONE);
|
|
|
|
((TextView) rootView.findViewById(R.id.pair_message)).setText("");
|
|
|
|
rootView.findViewById(R.id.pair_progress).setVisibility(View.VISIBLE);
|
|
|
|
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
|
|
|
@Override
|
|
|
|
public void onServiceStart(BackgroundService service) {
|
|
|
|
device = service.getDevice(deviceId);
|
|
|
|
if (device == null) return;
|
|
|
|
device.requestPairing();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
rootView.findViewById(R.id.accept_button).setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
|
|
|
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
|
|
|
@Override
|
|
|
|
public void onServiceStart(BackgroundService service) {
|
|
|
|
if (device != null) {
|
|
|
|
device.acceptPairing();
|
|
|
|
rootView.findViewById(R.id.pairing_buttons).setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
rootView.findViewById(R.id.reject_button).setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
|
|
|
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
|
|
|
@Override
|
|
|
|
public void onServiceStart(BackgroundService service) {
|
|
|
|
if (device != null) {
|
|
|
|
//Remove listener so buttons don't show for a while before changing the view
|
|
|
|
device.removePluginsChangedListener(pluginsChangedListener);
|
|
|
|
device.removePairingCallback(pairingCallback);
|
|
|
|
device.rejectPairing();
|
|
|
|
}
|
|
|
|
mActivity.onDeviceSelected(null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2015-08-20 00:59:21 -07:00
|
|
|
|
|
|
|
return rootView;
|
|
|
|
}
|
|
|
|
|
2017-02-05 15:42:42 +01:00
|
|
|
final Device.PluginsChangedListener pluginsChangedListener = new Device.PluginsChangedListener() {
|
2015-08-20 00:59:21 -07:00
|
|
|
@Override
|
|
|
|
public void onPluginsChanged(final Device device) {
|
2015-09-07 00:11:46 -07:00
|
|
|
refreshUI();
|
2015-08-20 00:59:21 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroyView() {
|
|
|
|
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
|
|
|
@Override
|
|
|
|
public void onServiceStart(BackgroundService service) {
|
|
|
|
Device device = service.getDevice(mDeviceId);
|
|
|
|
if (device == null) return;
|
|
|
|
device.removePluginsChangedListener(pluginsChangedListener);
|
2015-09-07 00:11:46 -07:00
|
|
|
device.removePairingCallback(pairingCallback);
|
2015-08-20 00:59:21 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
super.onDestroyView();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPrepareOptionsMenu(Menu menu) {
|
|
|
|
|
2015-09-08 05:18:57 -07:00
|
|
|
//Log.e("DeviceFragment", "onPrepareOptionsMenu");
|
2015-09-03 03:05:34 -07:00
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
super.onPrepareOptionsMenu(menu);
|
|
|
|
menu.clear();
|
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
if (device == null) {
|
2015-08-20 00:59:21 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Plugins button list
|
|
|
|
final Collection<Plugin> plugins = device.getLoadedPlugins().values();
|
|
|
|
for (final Plugin p : plugins) {
|
|
|
|
if (!p.displayInContextMenu()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
menu.add(p.getActionName()).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
p.startMainActivity(mActivity);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
menu.add(R.string.device_menu_plugins).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
|
|
|
Intent intent = new Intent(mActivity, SettingsActivity.class);
|
|
|
|
intent.putExtra("deviceId", mDeviceId);
|
|
|
|
startActivity(intent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2018-02-26 19:38:35 +01:00
|
|
|
if (device.isReachable()) {
|
2015-09-11 09:24:35 -07:00
|
|
|
|
|
|
|
menu.add(R.string.encryption_info_title).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
|
|
|
Context context = mActivity;
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
|
|
builder.setTitle(context.getResources().getString(R.string.encryption_info_title));
|
|
|
|
builder.setPositiveButton(context.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
|
|
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
|
|
dialog.dismiss();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (device.certificate == null) {
|
|
|
|
builder.setMessage(R.string.encryption_info_msg_no_ssl);
|
|
|
|
} else {
|
2016-06-04 02:21:28 +02:00
|
|
|
builder.setMessage(context.getResources().getString(R.string.my_device_fingerprint) + "\n" + SslHelper.getCertificateHash(SslHelper.certificate) + "\n\n"
|
|
|
|
+ context.getResources().getString(R.string.remote_device_fingerprint) + "\n" + SslHelper.getCertificateHash(device.certificate));
|
2015-09-11 09:24:35 -07:00
|
|
|
}
|
|
|
|
builder.create().show();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
2016-09-06 00:47:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (device.isPaired()) {
|
2015-09-11 09:24:35 -07:00
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
menu.add(R.string.device_menu_unpair).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
|
|
|
//Remove listener so buttons don't show for a while before changing the view
|
|
|
|
device.removePluginsChangedListener(pluginsChangedListener);
|
|
|
|
device.removePairingCallback(pairingCallback);
|
|
|
|
device.unpair();
|
|
|
|
mActivity.onDeviceSelected(null);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-08-20 00:59:21 -07:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-09-04 06:05:21 -07:00
|
|
|
@Override
|
|
|
|
public void onResume() {
|
|
|
|
super.onResume();
|
2016-07-06 17:45:01 +02:00
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
getView().setFocusableInTouchMode(true);
|
|
|
|
getView().requestFocus();
|
|
|
|
getView().setOnKeyListener(new View.OnKeyListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
|
|
|
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
|
2017-07-24 16:39:00 +02:00
|
|
|
boolean fromDeviceList = getArguments().getBoolean(ARG_FROM_DEVICE_LIST, false);
|
2015-09-07 00:11:46 -07:00
|
|
|
// Handle back button so we go to the list of devices in case we came from there
|
|
|
|
if (fromDeviceList) {
|
|
|
|
mActivity.onDeviceSelected(null);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void refreshUI() {
|
2015-09-08 05:18:57 -07:00
|
|
|
//Log.e("DeviceFragment", "refreshUI");
|
2015-09-07 00:11:46 -07:00
|
|
|
|
|
|
|
if (device == null || rootView == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
//Once in-app, there is no point in keep displaying the notification if any
|
|
|
|
device.hidePairingNotification();
|
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
mActivity.runOnUiThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
|
2016-01-10 03:16:14 -08:00
|
|
|
if (device.isPairRequestedByPeer()) {
|
2015-09-12 13:21:06 -07:00
|
|
|
((TextView) rootView.findViewById(R.id.pair_message)).setText(R.string.pair_requested);
|
2018-03-23 23:05:42 +01:00
|
|
|
rootView.findViewById(R.id.pairing_buttons).setVisibility(View.VISIBLE);
|
2015-09-12 13:21:06 -07:00
|
|
|
rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE);
|
|
|
|
rootView.findViewById(R.id.pair_button).setVisibility(View.GONE);
|
|
|
|
rootView.findViewById(R.id.pair_request).setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
boolean paired = device.isPaired();
|
|
|
|
boolean reachable = device.isReachable();
|
2017-02-25 21:12:32 +01:00
|
|
|
boolean onData = NetworkHelper.isOnMobileNetwork(getContext());
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
rootView.findViewById(R.id.pairing_buttons).setVisibility(paired ? View.GONE : View.VISIBLE);
|
Add a dark theme
Summary:
BUG: 375376
This revision adds dark mode support to the app ( T7044 ). It does so by injecting
theme information into each activity, and making sure that all Views
define their colors by reference to theme attributes.
In order to make this work, all of the buttons with images (like the list
of available devices) now are tinted according to the theme.
While all versions of android support the theme, only devices running
Android ICS or higher will have a toggle button in the drawer.
Test Plan: Open all the screens, both with and without the dark theme on.
Reviewers: #kde_connect, mtijink, #vdg, nicolasfella
Reviewed By: #kde_connect, mtijink, nicolasfella
Subscribers: apol, ngraham, nicolasfella, mtijink
Tags: #kde_connect
Differential Revision: https://phabricator.kde.org/D11694
2018-04-23 18:31:44 +02:00
|
|
|
rootView.findViewById(R.id.error_message_container).setVisibility((paired && !reachable) ? View.VISIBLE : View.GONE);
|
2017-02-25 21:12:32 +01:00
|
|
|
rootView.findViewById(R.id.not_reachable_message).setVisibility((paired && !reachable && !onData) ? View.VISIBLE : View.GONE);
|
|
|
|
rootView.findViewById(R.id.on_data_message).setVisibility((paired && !reachable && onData) ? View.VISIBLE : View.GONE);
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
try {
|
2017-07-11 13:50:40 +02:00
|
|
|
pluginListItems = new ArrayList<>();
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
//Plugins button list
|
|
|
|
final Collection<Plugin> plugins = device.getLoadedPlugins().values();
|
|
|
|
for (final Plugin p : plugins) {
|
|
|
|
if (!p.hasMainActivity()) continue;
|
|
|
|
if (p.displayInContextMenu()) continue;
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2017-07-11 13:50:40 +02:00
|
|
|
pluginListItems.add(new PluginItem(p, new View.OnClickListener() {
|
2015-09-12 07:17:14 -07:00
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
2015-09-12 13:21:06 -07:00
|
|
|
p.startMainActivity(mActivity);
|
2015-09-12 07:17:14 -07:00
|
|
|
}
|
|
|
|
}));
|
2015-09-07 00:11:46 -07:00
|
|
|
}
|
|
|
|
|
2017-07-11 13:50:40 +02:00
|
|
|
createPluginsList(device.getFailedPlugins(), R.string.plugins_failed_to_load, new PluginClickListener() {
|
|
|
|
@Override
|
|
|
|
void action() {
|
|
|
|
plugin.getErrorDialog(mActivity).show();
|
2015-09-07 00:11:46 -07:00
|
|
|
}
|
2017-07-11 13:50:40 +02:00
|
|
|
});
|
|
|
|
createPluginsList(device.getPluginsWithoutPermissions(), R.string.plugins_need_permission, new PluginClickListener() {
|
|
|
|
@Override
|
|
|
|
void action() {
|
|
|
|
plugin.getPermissionExplanationDialog(mActivity).show();
|
2017-05-31 15:51:07 +02:00
|
|
|
}
|
2017-07-11 13:50:40 +02:00
|
|
|
});
|
|
|
|
createPluginsList(device.getPluginsWithoutOptionalPermissions(), R.string.plugins_need_optional_permission, new PluginClickListener() {
|
|
|
|
@Override
|
|
|
|
void action() {
|
|
|
|
plugin.getOptionalPermissionExplanationDialog(mActivity).show();
|
2017-05-31 15:51:07 +02:00
|
|
|
}
|
2017-07-11 13:50:40 +02:00
|
|
|
});
|
2017-05-31 15:51:07 +02:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
ListView buttonsList = (ListView) rootView.findViewById(R.id.buttons_list);
|
2017-07-11 13:50:40 +02:00
|
|
|
ListAdapter adapter = new ListAdapter(mActivity, pluginListItems);
|
2015-09-12 13:21:06 -07:00
|
|
|
buttonsList.setAdapter(adapter);
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
mActivity.invalidateOptionsMenu();
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
} catch (IllegalStateException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
//Ignore: The activity was closed while we were trying to update it
|
|
|
|
} catch (ConcurrentModificationException e) {
|
|
|
|
Log.e("DeviceActivity", "ConcurrentModificationException");
|
|
|
|
this.run(); //Try again
|
|
|
|
}
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-12 13:21:06 -07:00
|
|
|
}
|
2015-09-04 06:05:21 -07:00
|
|
|
}
|
|
|
|
});
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2015-09-04 06:05:21 -07:00
|
|
|
}
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2017-02-05 15:42:42 +01:00
|
|
|
final Device.PairingCallback pairingCallback = new Device.PairingCallback() {
|
2015-09-07 00:11:46 -07:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void incomingRequest() {
|
2015-09-12 13:21:06 -07:00
|
|
|
refreshUI();
|
2015-09-07 00:11:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void pairingSuccessful() {
|
|
|
|
refreshUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void pairingFailed(final String error) {
|
|
|
|
mActivity.runOnUiThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2017-02-05 15:34:16 +01:00
|
|
|
if (rootView == null) return;
|
2015-09-07 00:11:46 -07:00
|
|
|
((TextView) rootView.findViewById(R.id.pair_message)).setText(error);
|
|
|
|
rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE);
|
|
|
|
rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE);
|
|
|
|
rootView.findViewById(R.id.pair_request).setVisibility(View.GONE);
|
|
|
|
refreshUI();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void unpaired() {
|
|
|
|
mActivity.runOnUiThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2017-02-05 15:34:16 +01:00
|
|
|
if (rootView == null) return;
|
2015-09-07 00:11:46 -07:00
|
|
|
((TextView) rootView.findViewById(R.id.pair_message)).setText(R.string.device_not_paired);
|
|
|
|
rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE);
|
|
|
|
rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE);
|
|
|
|
rootView.findViewById(R.id.pair_request).setVisibility(View.GONE);
|
|
|
|
refreshUI();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2018-03-03 17:21:16 +01:00
|
|
|
public static void acceptPairing(final String devId, final MainActivity activity) {
|
2017-02-05 15:19:46 +01:00
|
|
|
final DeviceFragment frag = new DeviceFragment(devId, activity);
|
|
|
|
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
|
|
|
public void onServiceStart(BackgroundService service) {
|
|
|
|
Device dev = service.getDevice(devId);
|
2017-05-24 00:21:45 +02:00
|
|
|
if (dev == null) {
|
2018-03-03 16:06:52 +01:00
|
|
|
Log.w("rejectPairing", "Device no longer exists: " + devId);
|
2017-05-24 00:21:45 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-02-05 15:19:46 +01:00
|
|
|
activity.getSupportActionBar().setTitle(dev.getName());
|
|
|
|
|
|
|
|
dev.addPairingCallback(frag.pairingCallback);
|
|
|
|
dev.addPluginsChangedListener(frag.pluginsChangedListener);
|
|
|
|
|
|
|
|
frag.device = dev;
|
|
|
|
frag.device.acceptPairing();
|
2017-02-05 15:42:03 +01:00
|
|
|
|
|
|
|
frag.refreshUI();
|
|
|
|
|
2017-02-05 15:19:46 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-03-03 17:21:16 +01:00
|
|
|
public static void rejectPairing(final String devId, final MainActivity activity) {
|
2017-02-05 15:19:46 +01:00
|
|
|
final DeviceFragment frag = new DeviceFragment(devId, activity);
|
|
|
|
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
|
|
|
public void onServiceStart(BackgroundService service) {
|
|
|
|
Device dev = service.getDevice(devId);
|
2017-05-24 00:21:45 +02:00
|
|
|
if (dev == null) {
|
2018-03-03 16:06:52 +01:00
|
|
|
Log.w("rejectPairing", "Device no longer exists: " + devId);
|
2017-05-24 00:21:45 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-02-05 15:19:46 +01:00
|
|
|
activity.getSupportActionBar().setTitle(dev.getName());
|
|
|
|
|
|
|
|
dev.addPairingCallback(frag.pairingCallback);
|
|
|
|
dev.addPluginsChangedListener(frag.pluginsChangedListener);
|
|
|
|
|
|
|
|
frag.device = dev;
|
2017-02-05 15:42:03 +01:00
|
|
|
|
2017-02-05 15:19:46 +01:00
|
|
|
//Remove listener so buttons don't show for a while before changing the view
|
|
|
|
frag.device.removePluginsChangedListener(frag.pluginsChangedListener);
|
|
|
|
frag.device.removePairingCallback(frag.pairingCallback);
|
|
|
|
frag.device.rejectPairing();
|
|
|
|
activity.onDeviceSelected(null);
|
2017-02-05 15:42:03 +01:00
|
|
|
|
|
|
|
frag.refreshUI();
|
2017-02-05 15:19:46 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-07-11 13:50:40 +02:00
|
|
|
|
2017-07-24 16:39:00 +02:00
|
|
|
void createPluginsList(ConcurrentHashMap<String, Plugin> plugins, int headerText, PluginClickListener onClickListener) {
|
2017-07-11 13:50:40 +02:00
|
|
|
if (!plugins.isEmpty()) {
|
|
|
|
|
|
|
|
TextView header = new TextView(mActivity);
|
|
|
|
header.setPadding(
|
|
|
|
0,
|
|
|
|
((int) (28 * getResources().getDisplayMetrics().density)),
|
|
|
|
0,
|
|
|
|
((int) (8 * getResources().getDisplayMetrics().density))
|
|
|
|
);
|
|
|
|
header.setOnClickListener(null);
|
|
|
|
header.setOnLongClickListener(null);
|
|
|
|
header.setText(headerText);
|
|
|
|
|
|
|
|
pluginListItems.add(new CustomItem(header));
|
|
|
|
for (Map.Entry<String, Plugin> entry : plugins.entrySet()) {
|
|
|
|
String pluginKey = entry.getKey();
|
|
|
|
final Plugin plugin = entry.getValue();
|
|
|
|
if (device.isPluginEnabled(pluginKey)) {
|
|
|
|
if (plugin == null) {
|
|
|
|
pluginListItems.add(new SmallEntryItem(pluginKey));
|
|
|
|
} else {
|
|
|
|
PluginClickListener listener = onClickListener.clone();
|
|
|
|
listener.plugin = plugin;
|
|
|
|
pluginListItems.add(new SmallEntryItem(plugin.getDisplayName(), listener));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private abstract class PluginClickListener implements View.OnClickListener, Cloneable {
|
|
|
|
|
|
|
|
Plugin plugin;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
action();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-03-03 16:06:52 +01:00
|
|
|
public PluginClickListener clone() {
|
2017-07-11 13:50:40 +02:00
|
|
|
try {
|
|
|
|
return (PluginClickListener) super.clone();
|
|
|
|
} catch (CloneNotSupportedException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract void action();
|
|
|
|
}
|
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
}
|