2015-08-20 00:59:21 -07:00
|
|
|
/*
|
2020-08-17 16:17:20 +02:00
|
|
|
* SPDX-FileCopyrightText: 2014 Albert Vaca Cintora <albertvaka@gmail.com>
|
2015-08-20 00:59:21 -07:00
|
|
|
*
|
2020-08-17 16:17:20 +02:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
2018-09-30 20:27:31 +02:00
|
|
|
*/
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2015-09-07 01:49:12 -07:00
|
|
|
package org.kde.kdeconnect.UserInterface;
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
import android.content.Context;
|
2015-08-20 00:59:21 -07:00
|
|
|
import android.content.Intent;
|
2020-08-05 15:14:30 +05:30
|
|
|
import android.os.Build;
|
2015-08-20 00:59:21 -07:00
|
|
|
import android.os.Bundle;
|
|
|
|
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.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
2019-04-20 00:01:20 +02:00
|
|
|
import androidx.annotation.NonNull;
|
2019-04-19 23:34:42 +02:00
|
|
|
import androidx.annotation.Nullable;
|
2021-09-13 00:09:43 +00:00
|
|
|
import androidx.annotation.StringRes;
|
2019-04-19 23:34:42 +02:00
|
|
|
import androidx.appcompat.app.AlertDialog;
|
2020-01-14 22:57:48 +01:00
|
|
|
import androidx.fragment.app.DialogFragment;
|
2019-04-19 23:34:42 +02:00
|
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
|
2020-07-05 13:32:44 +05:30
|
|
|
import com.klinker.android.send_message.Utils;
|
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
import org.kde.kdeconnect.BackgroundService;
|
|
|
|
import org.kde.kdeconnect.Device;
|
2015-09-11 09:24:35 -07:00
|
|
|
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
2020-08-05 15:14:30 +05:30
|
|
|
import org.kde.kdeconnect.Helpers.TelephonyHelper;
|
2021-09-13 00:09:43 +00:00
|
|
|
import org.kde.kdeconnect.NetworkPacket;
|
|
|
|
import org.kde.kdeconnect.Plugins.BatteryPlugin.BatteryPlugin;
|
|
|
|
import org.kde.kdeconnect.Plugins.BatteryPlugin.DeviceBatteryInfo;
|
2015-08-20 00:59:21 -07:00
|
|
|
import org.kde.kdeconnect.Plugins.Plugin;
|
2020-07-05 13:32:44 +05:30
|
|
|
import org.kde.kdeconnect.Plugins.SMSPlugin.SMSPlugin;
|
2018-12-09 18:17:20 +01:00
|
|
|
import org.kde.kdeconnect.UserInterface.List.FailedPluginListItem;
|
2015-08-20 00:59:21 -07:00
|
|
|
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
|
2016-06-09 13:42:15 +02:00
|
|
|
import org.kde.kdeconnect.UserInterface.List.PluginItem;
|
2020-07-08 05:15:07 +05:30
|
|
|
import org.kde.kdeconnect.UserInterface.List.PluginListHeaderItem;
|
2020-07-05 13:32:44 +05:30
|
|
|
import org.kde.kdeconnect.UserInterface.List.SetDefaultAppPluginListItem;
|
2015-08-20 00:59:21 -07:00
|
|
|
import org.kde.kdeconnect_tp.R;
|
2020-07-08 05:15:07 +05:30
|
|
|
import org.kde.kdeconnect_tp.databinding.ActivityDeviceBinding;
|
2021-09-13 00:09:43 +00:00
|
|
|
import org.kde.kdeconnect_tp.databinding.ViewPairErrorBinding;
|
|
|
|
import org.kde.kdeconnect_tp.databinding.ViewPairRequestBinding;
|
2015-08-20 00:59:21 -07:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.ConcurrentModificationException;
|
2020-08-05 15:14:30 +05:30
|
|
|
import java.util.List;
|
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
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
private static final String ARG_DEVICE_ID = "deviceId";
|
|
|
|
private static final String ARG_FROM_DEVICE_LIST = "fromDeviceList";
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2019-05-21 00:21:01 +02:00
|
|
|
private static final String TAG = "KDE/DeviceFragment";
|
|
|
|
|
2019-01-06 13:10:58 +01:00
|
|
|
private String mDeviceId;
|
2018-10-26 23:53:58 +02:00
|
|
|
private Device device;
|
2015-08-20 01:00:05 -07:00
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
private MainActivity mActivity;
|
2015-09-03 03:05:34 -07:00
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
private ArrayList<ListAdapter.Item> pluginListItems;
|
2017-07-11 13:50:40 +02:00
|
|
|
|
2021-09-13 00:09:43 +00:00
|
|
|
/**
|
|
|
|
* Top-level ViewBinding for this fragment.
|
|
|
|
*
|
|
|
|
* Host for {@link #pluginListItems}.
|
|
|
|
*/
|
|
|
|
private ActivityDeviceBinding deviceBinding;
|
|
|
|
/**
|
|
|
|
* Not-yet-paired ViewBinding.
|
|
|
|
*
|
|
|
|
* Used to start and retry pairing.
|
|
|
|
*/
|
|
|
|
private ViewPairRequestBinding binding;
|
|
|
|
/**
|
|
|
|
* Cannot-communicate ViewBinding.
|
|
|
|
*
|
|
|
|
* Used when the remote device is unreachable.
|
|
|
|
*/
|
|
|
|
private ViewPairErrorBinding errorBinding;
|
2018-12-31 12:28:58 +01:00
|
|
|
|
2017-07-11 13:50:40 +02:00
|
|
|
public DeviceFragment() {
|
|
|
|
}
|
2015-08-20 00:59:21 -07:00
|
|
|
|
2018-12-06 19:09:47 +01:00
|
|
|
public static DeviceFragment newInstance(String deviceId, boolean fromDeviceList) {
|
|
|
|
DeviceFragment frag = new DeviceFragment();
|
|
|
|
|
2015-09-07 00:11:46 -07:00
|
|
|
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);
|
2018-12-06 19:09:47 +01:00
|
|
|
frag.setArguments(args);
|
|
|
|
|
|
|
|
return frag;
|
2015-09-07 00:11:46 -07:00
|
|
|
}
|
|
|
|
|
2015-08-20 01:00:05 -07:00
|
|
|
@Override
|
2020-07-08 05:15:07 +05:30
|
|
|
public void onAttach(@NonNull Context context) {
|
2019-04-19 23:34:14 +02:00
|
|
|
super.onAttach(context);
|
2018-03-03 17:21:16 +01:00
|
|
|
mActivity = ((MainActivity) getActivity());
|
2015-08-20 01:00:05 -07:00
|
|
|
}
|
|
|
|
|
2019-01-06 13:10:58 +01:00
|
|
|
@Override
|
|
|
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
|
|
|
if (getArguments() == null || !getArguments().containsKey(ARG_DEVICE_ID)) {
|
|
|
|
throw new RuntimeException("You must instantiate a new DeviceFragment using DeviceFragment.newInstance()");
|
|
|
|
}
|
|
|
|
|
|
|
|
mDeviceId = getArguments().getString(ARG_DEVICE_ID);
|
|
|
|
}
|
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
@Override
|
2019-04-20 00:01:20 +02:00
|
|
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
2015-08-20 00:59:21 -07:00
|
|
|
Bundle savedInstanceState) {
|
2021-09-13 00:09:43 +00:00
|
|
|
deviceBinding = ActivityDeviceBinding.inflate(inflater, container, false);
|
|
|
|
|
|
|
|
// Inner binding for the layout shown when we're not paired yet...
|
|
|
|
binding = deviceBinding.pairRequest;
|
|
|
|
// ...and for when pairing doesn't (or can't) work
|
|
|
|
errorBinding = deviceBinding.pairError;
|
2020-07-08 05:15:07 +05:30
|
|
|
|
|
|
|
binding.pairButton.setOnClickListener(v -> {
|
|
|
|
binding.pairButton.setVisibility(View.GONE);
|
|
|
|
binding.pairMessage.setText("");
|
2020-11-26 11:30:46 +01:00
|
|
|
binding.pairVerification.setVisibility(View.VISIBLE);
|
|
|
|
binding.pairVerification.setText(SslHelper.getVerificationKey(SslHelper.certificate, device.certificate));
|
2020-07-08 05:15:07 +05:30
|
|
|
binding.pairProgress.setVisibility(View.VISIBLE);
|
|
|
|
BackgroundService.RunCommand(mActivity, service -> {
|
|
|
|
device = service.getDevice(mDeviceId);
|
|
|
|
if (device == null) return;
|
|
|
|
device.requestPairing();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
binding.acceptButton.setOnClickListener(v -> {
|
|
|
|
if (device != null) {
|
|
|
|
device.acceptPairing();
|
|
|
|
binding.pairingButtons.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
binding.rejectButton.setOnClickListener(v -> {
|
|
|
|
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
|
|
|
|
2015-09-03 03:05:34 -07:00
|
|
|
setHasOptionsMenu(true);
|
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
BackgroundService.RunCommand(mActivity, service -> {
|
|
|
|
device = service.getDevice(mDeviceId);
|
|
|
|
if (device == null) {
|
2019-05-21 00:21:01 +02:00
|
|
|
Log.e(TAG, "Trying to display a device fragment but the device is not present");
|
2018-05-09 14:02:56 +02:00
|
|
|
mActivity.onDeviceSelected(null);
|
|
|
|
return;
|
|
|
|
}
|
2015-08-20 01:00:05 -07:00
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
mActivity.getSupportActionBar().setTitle(device.getName());
|
2015-08-20 01:00:05 -07:00
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
device.addPairingCallback(pairingCallback);
|
|
|
|
device.addPluginsChangedListener(pluginsChangedListener);
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
refreshUI();
|
2015-08-20 01:00:05 -07:00
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
});
|
|
|
|
|
2021-09-13 00:09:43 +00:00
|
|
|
return deviceBinding.getRoot();
|
2018-12-31 12:28:58 +01:00
|
|
|
}
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2019-01-06 13:10:58 +01:00
|
|
|
String getDeviceId() { return mDeviceId; }
|
|
|
|
|
2018-12-31 12:28:58 +01:00
|
|
|
private final Device.PluginsChangedListener pluginsChangedListener = device -> refreshUI();
|
2015-08-20 00:59:21 -07:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroyView() {
|
2018-05-09 14:02:56 +02:00
|
|
|
BackgroundService.RunCommand(mActivity, service -> {
|
|
|
|
Device device = service.getDevice(mDeviceId);
|
|
|
|
if (device == null) return;
|
|
|
|
device.removePluginsChangedListener(pluginsChangedListener);
|
|
|
|
device.removePairingCallback(pairingCallback);
|
2015-08-20 00:59:21 -07:00
|
|
|
});
|
2018-12-31 12:28:58 +01:00
|
|
|
|
2015-08-20 00:59:21 -07:00
|
|
|
super.onDestroyView();
|
2020-07-08 05:15:07 +05:30
|
|
|
binding = null;
|
2015-08-20 00:59:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-07-08 05:15:07 +05:30
|
|
|
public void onPrepareOptionsMenu(@NonNull Menu menu) {
|
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;
|
|
|
|
}
|
2018-05-09 14:02:56 +02:00
|
|
|
menu.add(p.getActionName()).setOnMenuItemClickListener(item -> {
|
|
|
|
p.startMainActivity(mActivity);
|
|
|
|
return true;
|
2015-08-20 00:59:21 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
menu.add(R.string.device_menu_plugins).setOnMenuItemClickListener(menuItem -> {
|
2019-05-13 21:32:47 +00:00
|
|
|
Intent intent = new Intent(mActivity, PluginSettingsActivity.class);
|
2018-05-09 14:02:56 +02:00
|
|
|
intent.putExtra("deviceId", mDeviceId);
|
|
|
|
startActivity(intent);
|
|
|
|
return true;
|
2015-08-20 00:59:21 -07:00
|
|
|
});
|
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
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
menu.add(R.string.encryption_info_title).setOnMenuItemClickListener(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), (dialog, id) -> dialog.dismiss());
|
2015-09-11 09:24:35 -07:00
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
if (device.certificate == null) {
|
|
|
|
builder.setMessage(R.string.encryption_info_msg_no_ssl);
|
|
|
|
} else {
|
|
|
|
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
|
|
|
}
|
2019-10-27 23:43:13 +01:00
|
|
|
builder.show();
|
2018-05-09 14:02:56 +02:00
|
|
|
return true;
|
2015-09-11 09:24:35 -07:00
|
|
|
});
|
2016-09-06 00:47:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (device.isPaired()) {
|
2015-09-11 09:24:35 -07:00
|
|
|
|
2018-05-09 14:02:56 +02:00
|
|
|
menu.add(R.string.device_menu_unpair).setOnMenuItemClickListener(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-09-07 00:11:46 -07:00
|
|
|
});
|
|
|
|
}
|
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();
|
2018-05-09 14:02:56 +02:00
|
|
|
getView().setOnKeyListener((v, keyCode, event) -> {
|
|
|
|
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
|
|
|
|
boolean fromDeviceList = getArguments().getBoolean(ARG_FROM_DEVICE_LIST, false);
|
|
|
|
// Handle back button so we go to the list of devices in case we came from there
|
|
|
|
if (fromDeviceList) {
|
|
|
|
mActivity.onDeviceSelected(null);
|
|
|
|
return true;
|
2015-09-07 00:11:46 -07:00
|
|
|
}
|
|
|
|
}
|
2018-05-09 14:02:56 +02:00
|
|
|
return false;
|
2015-09-07 00:11:46 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
private void refreshUI() {
|
2020-07-08 05:15:07 +05:30
|
|
|
if (device == null || binding.getRoot() == null) {
|
2015-09-07 00:11:46 -07:00
|
|
|
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()) {
|
2020-07-08 05:15:07 +05:30
|
|
|
binding.pairMessage.setText(R.string.pair_requested);
|
2020-11-26 11:30:46 +01:00
|
|
|
binding.pairVerification.setVisibility(View.VISIBLE);
|
|
|
|
binding.pairVerification.setText(SslHelper.getVerificationKey(SslHelper.certificate, device.certificate));
|
2020-07-08 05:15:07 +05:30
|
|
|
binding.pairingButtons.setVisibility(View.VISIBLE);
|
|
|
|
binding.pairProgress.setVisibility(View.GONE);
|
|
|
|
binding.pairButton.setVisibility(View.GONE);
|
|
|
|
binding.pairRequestButtons.setVisibility(View.VISIBLE);
|
2015-09-12 13:21:06 -07:00
|
|
|
} else {
|
|
|
|
boolean paired = device.isPaired();
|
|
|
|
boolean reachable = device.isReachable();
|
2015-09-07 00:11:46 -07:00
|
|
|
|
2020-07-08 05:15:07 +05:30
|
|
|
binding.pairingButtons.setVisibility(paired ? View.GONE : View.VISIBLE);
|
2021-09-13 00:09:43 +00:00
|
|
|
errorBinding.errorMessageContainer.setVisibility((paired && !reachable) ? View.VISIBLE : View.GONE);
|
|
|
|
errorBinding.notReachableMessage.setVisibility((paired && !reachable) ? View.VISIBLE : View.GONE);
|
|
|
|
deviceBinding.viewStatusContainer.setVisibility((paired && reachable) ? 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
|
|
|
|
2018-10-25 14:16:16 +02:00
|
|
|
if (paired && reachable) {
|
|
|
|
//Plugins button list
|
|
|
|
final Collection<Plugin> plugins = device.getLoadedPlugins().values();
|
|
|
|
for (final Plugin p : plugins) {
|
|
|
|
if (!p.hasMainActivity()) continue;
|
|
|
|
if (p.displayInContextMenu()) continue;
|
|
|
|
|
|
|
|
pluginListItems.add(new PluginItem(p, v -> p.startMainActivity(mActivity)));
|
|
|
|
}
|
2018-12-03 19:36:17 +01:00
|
|
|
DeviceFragment.this.createPluginsList(device.getPluginsWithoutPermissions(), R.string.plugins_need_permission, (plugin) -> {
|
2020-01-14 22:57:48 +01:00
|
|
|
DialogFragment dialog = plugin.getPermissionExplanationDialog();
|
2018-12-03 19:36:17 +01:00
|
|
|
if (dialog != null) {
|
2019-02-02 11:38:13 +00:00
|
|
|
dialog.show(getChildFragmentManager(), null);
|
2018-12-03 19:36:17 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
DeviceFragment.this.createPluginsList(device.getPluginsWithoutOptionalPermissions(), R.string.plugins_need_optional_permission, (plugin) -> {
|
2020-01-14 22:57:48 +01:00
|
|
|
DialogFragment dialog = plugin.getOptionalPermissionExplanationDialog();
|
2019-02-02 11:38:13 +00:00
|
|
|
|
2018-12-03 19:36:17 +01:00
|
|
|
if (dialog != null) {
|
2019-02-02 11:38:13 +00:00
|
|
|
dialog.show(getChildFragmentManager(), null);
|
2018-12-03 19:36:17 +01:00
|
|
|
}
|
|
|
|
});
|
2021-09-13 00:09:43 +00:00
|
|
|
|
|
|
|
DeviceFragment.this.displayBatteryInfoIfPossible();
|
2015-09-07 00:11:46 -07:00
|
|
|
}
|
|
|
|
|
2017-07-11 13:50:40 +02:00
|
|
|
ListAdapter adapter = new ListAdapter(mActivity, pluginListItems);
|
2021-09-13 00:09:43 +00:00
|
|
|
deviceBinding.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) {
|
|
|
|
//Ignore: The activity was closed while we were trying to update it
|
|
|
|
} catch (ConcurrentModificationException e) {
|
2019-05-21 00:21:01 +02:00
|
|
|
Log.e(TAG, "ConcurrentModificationException");
|
2015-09-12 13:21:06 -07:00
|
|
|
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
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
private 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) {
|
2018-05-09 14:02:56 +02:00
|
|
|
mActivity.runOnUiThread(() -> {
|
2020-07-08 05:15:07 +05:30
|
|
|
if (binding.getRoot() == null) return;
|
|
|
|
binding.pairMessage.setText(error);
|
2020-11-26 11:30:46 +01:00
|
|
|
binding.pairVerification.setText("");
|
|
|
|
binding.pairVerification.setVisibility(View.GONE);
|
2020-07-08 05:15:07 +05:30
|
|
|
binding.pairProgress.setVisibility(View.GONE);
|
|
|
|
binding.pairButton.setVisibility(View.VISIBLE);
|
|
|
|
binding.pairRequestButtons.setVisibility(View.GONE);
|
2018-05-09 14:02:56 +02:00
|
|
|
refreshUI();
|
2015-09-07 00:11:46 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void unpaired() {
|
2018-05-09 14:02:56 +02:00
|
|
|
mActivity.runOnUiThread(() -> {
|
2020-07-08 05:15:07 +05:30
|
|
|
if (binding.getRoot() == null) return;
|
|
|
|
binding.pairMessage.setText(R.string.device_not_paired);
|
2020-11-26 11:30:46 +01:00
|
|
|
binding.pairVerification.setVisibility(View.GONE);
|
2020-07-08 05:15:07 +05:30
|
|
|
binding.pairProgress.setVisibility(View.GONE);
|
|
|
|
binding.pairButton.setVisibility(View.VISIBLE);
|
|
|
|
binding.pairRequestButtons.setVisibility(View.GONE);
|
2018-05-09 14:02:56 +02:00
|
|
|
refreshUI();
|
2015-09-07 00:11:46 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
private void createPluginsList(ConcurrentHashMap<String, Plugin> plugins, int headerText, FailedPluginListItem.Action action) {
|
2019-05-13 21:31:03 +00:00
|
|
|
if (plugins.isEmpty())
|
|
|
|
return;
|
|
|
|
|
2019-05-13 22:34:10 +00:00
|
|
|
pluginListItems.add(new PluginListHeaderItem(headerText));
|
2019-05-13 21:31:03 +00:00
|
|
|
for (Plugin plugin : plugins.values()) {
|
|
|
|
if (!device.isPluginEnabled(plugin.getPluginKey())) {
|
|
|
|
continue;
|
2017-07-11 13:50:40 +02:00
|
|
|
}
|
2019-05-13 21:31:03 +00:00
|
|
|
pluginListItems.add(new FailedPluginListItem(plugin, action));
|
2017-07-11 13:50:40 +02:00
|
|
|
}
|
|
|
|
}
|
2021-09-13 00:09:43 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This method tries to display battery info for the remote device. Includes
|
|
|
|
* <ul>
|
|
|
|
* <li>Current charge as a percentage</li>
|
|
|
|
* <li>Whether the remote device is low on power</li>
|
|
|
|
* <li>Whether the remote device is currently charging</li>
|
|
|
|
* </ul>
|
|
|
|
* <p>
|
|
|
|
* This will show a simple message on the view instead if we don't have
|
|
|
|
* accurate info right now.
|
|
|
|
* </p>
|
|
|
|
*/
|
|
|
|
private void displayBatteryInfoIfPossible() {
|
|
|
|
boolean canDisplayBatteryInfo = false;
|
|
|
|
BatteryPlugin batteryPlugin = (BatteryPlugin) device.getLoadedPlugins().get(
|
|
|
|
Plugin.getPluginKey(BatteryPlugin.class)
|
|
|
|
);
|
|
|
|
|
|
|
|
if (batteryPlugin != null) {
|
|
|
|
DeviceBatteryInfo info = batteryPlugin.getRemoteBatteryInfo();
|
|
|
|
if (info != null) {
|
|
|
|
canDisplayBatteryInfo = true;
|
|
|
|
|
|
|
|
Context ctx = deviceBinding.viewBatteryStatus.getContext();
|
|
|
|
|
|
|
|
boolean isCharging = info.isCharging();
|
|
|
|
@StringRes
|
|
|
|
int resId;
|
|
|
|
if (isCharging) {
|
|
|
|
resId = R.string.battery_status_charging_format;
|
|
|
|
} else if (BatteryPlugin.isLowBattery(info)) {
|
|
|
|
resId = R.string.battery_status_low_format;
|
|
|
|
} else {
|
|
|
|
resId = R.string.battery_status_format;
|
|
|
|
}
|
|
|
|
|
|
|
|
deviceBinding.viewBatteryStatus.setChecked(isCharging);
|
|
|
|
deviceBinding.viewBatteryStatus.setText(ctx.getString(resId, info.getCurrentCharge()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!canDisplayBatteryInfo) {
|
|
|
|
deviceBinding.viewBatteryStatus.setText(R.string.battery_status_unknown);
|
|
|
|
}
|
|
|
|
}
|
2015-08-20 00:59:21 -07:00
|
|
|
}
|