mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 18:07:55 +00:00
Display battery status at the bottom of each device on its DeviceFragment
kdeconnect-android!105
This commit is contained in:
parent
0f4aaa286d
commit
5940e957a8
@ -1,126 +1,68 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="org.kde.kdeconnect.UserInterface.DeviceFragment">
|
tools:context="org.kde.kdeconnect.UserInterface.DeviceFragment">
|
||||||
|
|
||||||
<LinearLayout
|
<!-- Layout shown when device is reachable but not yet paired -->
|
||||||
android:id="@+id/pairing_buttons"
|
<include
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/pair_request"
|
||||||
android:layout_height="wrap_content"
|
layout="@layout/view_pair_request"
|
||||||
android:layout_gravity="center"
|
tools:visibility="gone"/>
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="@dimen/activity_vertical_margin"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/pair_progress"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/pair_message"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dip"
|
|
||||||
android:text="@string/device_not_paired"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/pair_verification"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawablePadding="5dp"
|
|
||||||
android:drawableLeft="@drawable/ic_key"
|
|
||||||
android:drawableStart="@drawable/ic_key"
|
|
||||||
android:layout_marginBottom="8dip"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:text=""
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/pair_button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/button_round"
|
|
||||||
android:text="@string/request_pairing"
|
|
||||||
android:textColor="@android:color/white"/>
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/pair_request_buttons"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/accept_button"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="4dip"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/button_round"
|
|
||||||
android:text="@string/pairing_accept"
|
|
||||||
android:textColor="@android:color/white"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/reject_button"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="4dip"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/button_round"
|
|
||||||
android:text="@string/pairing_reject"
|
|
||||||
android:textColor="@android:color/white"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/error_message_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
|
||||||
android:id="@+id/error_message_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:paddingEnd="8dip"
|
|
||||||
android:paddingLeft="0dip"
|
|
||||||
android:paddingRight="8dip"
|
|
||||||
android:paddingStart="0dip"
|
|
||||||
android:src="@drawable/ic_error_outline_48dp"
|
|
||||||
app:tint="?attr/colorHighContrast"
|
|
||||||
tools:ignore="UnusedAttribute"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/not_reachable_message"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:text="@string/unreachable_description"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:visibility="gone" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
<!-- Layout shown when we can't pair with device or device is not reachable -->
|
||||||
|
<include
|
||||||
|
android:id="@+id/pair_error"
|
||||||
|
layout="@layout/view_pair_error"
|
||||||
|
tools:visibility="gone"/>
|
||||||
|
|
||||||
|
<!-- Layout shown when device is paired and reachable -->
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/buttons_list"
|
android:id="@+id/buttons_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
tools:context=".DeviceActivity"
|
tools:context=".DeviceActivity"
|
||||||
tools:listitem="@layout/list_item_with_icon_entry"
|
tools:listitem="@layout/list_item_with_icon_entry"
|
||||||
|
android:layout_weight=".8"
|
||||||
android:divider="@null"
|
android:divider="@null"
|
||||||
android:dividerHeight="0dp" />
|
android:dividerHeight="0dp" />
|
||||||
|
|
||||||
|
<!-- Extra information about the current device -->
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/view_status_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="4dp"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/view_status_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:text="@string/view_status_title"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CheckedTextView
|
||||||
|
android:id="@+id/view_battery_status"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/view_status_title"
|
||||||
|
android:checkMark="@null"
|
||||||
|
android:clickable="false"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
android:text="@string/battery_status_unknown"
|
||||||
|
tools:text="100%"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
@ -40,7 +41,9 @@
|
|||||||
android:fadingEdge="horizontal"
|
android:fadingEdge="horizontal"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text=""
|
android:text=""
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
tools:maxLength="20"
|
||||||
|
tools:text="@tools:sample/lorem/random"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/list_item_entry_summary"
|
android:id="@+id/list_item_entry_summary"
|
||||||
@ -52,8 +55,10 @@
|
|||||||
android:text=""
|
android:text=""
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:textColor="#CC2222"
|
android:textColor="#CC2222"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"
|
||||||
|
tools:text="Other (optional) info"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
37
res/layout/view_pair_error.xml
Normal file
37
res/layout/view_pair_error.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/error_message_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/error_message_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:paddingEnd="8dip"
|
||||||
|
android:paddingLeft="0dip"
|
||||||
|
android:paddingRight="8dip"
|
||||||
|
android:paddingStart="0dip"
|
||||||
|
android:src="@drawable/ic_error_outline_48dp"
|
||||||
|
app:tint="?attr/colorHighContrast"
|
||||||
|
tools:ignore="UnusedAttribute" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/not_reachable_message"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="@string/unreachable_description"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</LinearLayout>
|
77
res/layout/view_pair_request.xml
Normal file
77
res/layout/view_pair_request.xml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/pairing_buttons"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/activity_vertical_margin"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/pair_progress"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pair_message"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dip"
|
||||||
|
android:text="@string/device_not_paired"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pair_verification"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:drawableLeft="@drawable/ic_key"
|
||||||
|
android:drawableStart="@drawable/ic_key"
|
||||||
|
android:layout_marginBottom="8dip"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:text=""
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/pair_button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/button_round"
|
||||||
|
android:text="@string/request_pairing"
|
||||||
|
android:textColor="@android:color/white" />
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/pair_request_buttons"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/accept_button"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="4dip"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/button_round"
|
||||||
|
android:text="@string/pairing_accept"
|
||||||
|
android:textColor="@android:color/white" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/reject_button"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="4dip"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/button_round"
|
||||||
|
android:text="@string/pairing_reject"
|
||||||
|
android:textColor="@android:color/white" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
@ -135,6 +135,13 @@
|
|||||||
<string name="mouse_receiver_plugin_description">Receive remote mouse movement</string>
|
<string name="mouse_receiver_plugin_description">Receive remote mouse movement</string>
|
||||||
<string name="mouse_receiver_plugin_name">Mouse receiver</string>
|
<string name="mouse_receiver_plugin_name">Mouse receiver</string>
|
||||||
<string name="mouse_receiver_no_permissions">You need to enable Accessibility Service</string>
|
<string name="mouse_receiver_no_permissions">You need to enable Accessibility Service</string>
|
||||||
|
|
||||||
|
<string name="view_status_title">Status</string>
|
||||||
|
<string name="battery_status_format">Battery: %d%%</string>
|
||||||
|
<string name="battery_status_low_format">Battery: %d%% Low Battery</string>
|
||||||
|
<string name="battery_status_charging_format">Battery: %d%% charging</string>
|
||||||
|
<string name="battery_status_unknown">Battery information not available</string>
|
||||||
|
|
||||||
<string name="category_connected_devices">Connected devices</string>
|
<string name="category_connected_devices">Connected devices</string>
|
||||||
<string name="category_not_paired_devices">Available devices</string>
|
<string name="category_not_paired_devices">Available devices</string>
|
||||||
<string name="category_remembered_devices">Remembered devices</string>
|
<string name="category_remembered_devices">Remembered devices</string>
|
||||||
|
@ -11,6 +11,8 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.kde.kdeconnect.NetworkPacket;
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
import org.kde.kdeconnect.Plugins.Plugin;
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
@ -27,8 +29,15 @@ public class BatteryPlugin extends Plugin {
|
|||||||
private static final int THRESHOLD_EVENT_NONE = 0;
|
private static final int THRESHOLD_EVENT_NONE = 0;
|
||||||
private static final int THRESHOLD_EVENT_BATTERY_LOW = 1;
|
private static final int THRESHOLD_EVENT_BATTERY_LOW = 1;
|
||||||
|
|
||||||
|
public static boolean isLowBattery(@NonNull DeviceBatteryInfo info) {
|
||||||
|
return info.getThresholdEvent() == THRESHOLD_EVENT_BATTERY_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
private final NetworkPacket batteryInfo = new NetworkPacket(PACKET_TYPE_BATTERY);
|
private final NetworkPacket batteryInfo = new NetworkPacket(PACKET_TYPE_BATTERY);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private DeviceBatteryInfo remoteBatteryInfo;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
return context.getResources().getString(R.string.pref_plugin_battery);
|
return context.getResources().getString(R.string.pref_plugin_battery);
|
||||||
@ -73,6 +82,11 @@ public class BatteryPlugin extends Plugin {
|
|||||||
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
||||||
Intent currentState = context.registerReceiver(receiver, intentFilter);
|
Intent currentState = context.registerReceiver(receiver, intentFilter);
|
||||||
receiver.onReceive(context, currentState);
|
receiver.onReceive(context, currentState);
|
||||||
|
|
||||||
|
// Request new battery info from the linked device
|
||||||
|
NetworkPacket np = new NetworkPacket(PACKET_TYPE_BATTERY_REQUEST);
|
||||||
|
np.set("request", true);
|
||||||
|
device.sendPacket(np);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,17 +103,36 @@ public class BatteryPlugin extends Plugin {
|
|||||||
device.sendPacket(batteryInfo);
|
device.sendPacket(batteryInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PACKET_TYPE_BATTERY.equals(np.getType())) {
|
||||||
|
remoteBatteryInfo = new DeviceBatteryInfo(np);
|
||||||
|
device.onPluginsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The latest battery information about the linked device. Will be null if the linked device
|
||||||
|
* has not sent us any such information yet.
|
||||||
|
* <p>
|
||||||
|
* See {@link DeviceBatteryInfo} for info on which fields we expect to find.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return the most recent packet received from the remote device. May be null
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public DeviceBatteryInfo getRemoteBatteryInfo() {
|
||||||
|
return remoteBatteryInfo;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getSupportedPacketTypes() {
|
public String[] getSupportedPacketTypes() {
|
||||||
return new String[]{PACKET_TYPE_BATTERY_REQUEST};
|
return new String[]{PACKET_TYPE_BATTERY_REQUEST, PACKET_TYPE_BATTERY};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getOutgoingPacketTypes() {
|
public String[] getOutgoingPacketTypes() {
|
||||||
return new String[]{PACKET_TYPE_BATTERY};
|
return new String[]{PACKET_TYPE_BATTERY_REQUEST, PACKET_TYPE_BATTERY};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.kde.kdeconnect.Plugins.BatteryPlugin
|
||||||
|
|
||||||
|
import org.kde.kdeconnect.NetworkPacket
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialised data representation of the packets received by [BatteryPlugin].
|
||||||
|
*
|
||||||
|
* Constants for [thresholdEvent] may be found in [BatteryPlugin].
|
||||||
|
*
|
||||||
|
* @param currentCharge the amount of charge in the device's battery
|
||||||
|
* @param isCharging whether the device is charging
|
||||||
|
* @param thresholdEvent status classifier (used to indicate low battery, etc.)
|
||||||
|
* @see BatteryPlugin.isLowBattery
|
||||||
|
*/
|
||||||
|
data class DeviceBatteryInfo(
|
||||||
|
val currentCharge: Int,
|
||||||
|
val isCharging: Boolean,
|
||||||
|
val thresholdEvent: Int,
|
||||||
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use with packets of type [BatteryPlugin.PACKET_TYPE_BATTERY].
|
||||||
|
*/
|
||||||
|
constructor(np: NetworkPacket) :
|
||||||
|
this(
|
||||||
|
np.getInt("currentCharge"),
|
||||||
|
np.getBoolean("isCharging"),
|
||||||
|
np.getInt("thresholdEvent", 0)
|
||||||
|
)
|
||||||
|
}
|
@ -19,6 +19,7 @@ import android.view.ViewGroup;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
@ -29,6 +30,9 @@ import org.kde.kdeconnect.BackgroundService;
|
|||||||
import org.kde.kdeconnect.Device;
|
import org.kde.kdeconnect.Device;
|
||||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||||
import org.kde.kdeconnect.Helpers.TelephonyHelper;
|
import org.kde.kdeconnect.Helpers.TelephonyHelper;
|
||||||
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
|
import org.kde.kdeconnect.Plugins.BatteryPlugin.BatteryPlugin;
|
||||||
|
import org.kde.kdeconnect.Plugins.BatteryPlugin.DeviceBatteryInfo;
|
||||||
import org.kde.kdeconnect.Plugins.Plugin;
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
import org.kde.kdeconnect.Plugins.SMSPlugin.SMSPlugin;
|
import org.kde.kdeconnect.Plugins.SMSPlugin.SMSPlugin;
|
||||||
import org.kde.kdeconnect.UserInterface.List.FailedPluginListItem;
|
import org.kde.kdeconnect.UserInterface.List.FailedPluginListItem;
|
||||||
@ -38,6 +42,8 @@ import org.kde.kdeconnect.UserInterface.List.PluginListHeaderItem;
|
|||||||
import org.kde.kdeconnect.UserInterface.List.SetDefaultAppPluginListItem;
|
import org.kde.kdeconnect.UserInterface.List.SetDefaultAppPluginListItem;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
import org.kde.kdeconnect_tp.databinding.ActivityDeviceBinding;
|
import org.kde.kdeconnect_tp.databinding.ActivityDeviceBinding;
|
||||||
|
import org.kde.kdeconnect_tp.databinding.ViewPairErrorBinding;
|
||||||
|
import org.kde.kdeconnect_tp.databinding.ViewPairRequestBinding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -63,7 +69,24 @@ public class DeviceFragment extends Fragment {
|
|||||||
|
|
||||||
private ArrayList<ListAdapter.Item> pluginListItems;
|
private ArrayList<ListAdapter.Item> pluginListItems;
|
||||||
|
|
||||||
private ActivityDeviceBinding binding;
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
public DeviceFragment() {
|
public DeviceFragment() {
|
||||||
}
|
}
|
||||||
@ -99,7 +122,12 @@ public class DeviceFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
binding = ActivityDeviceBinding.inflate(inflater, container, false);
|
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;
|
||||||
|
|
||||||
binding.pairButton.setOnClickListener(v -> {
|
binding.pairButton.setOnClickListener(v -> {
|
||||||
binding.pairButton.setVisibility(View.GONE);
|
binding.pairButton.setVisibility(View.GONE);
|
||||||
@ -148,7 +176,7 @@ public class DeviceFragment extends Fragment {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return binding.getRoot();
|
return deviceBinding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getDeviceId() { return mDeviceId; }
|
String getDeviceId() { return mDeviceId; }
|
||||||
@ -272,8 +300,9 @@ public class DeviceFragment extends Fragment {
|
|||||||
boolean reachable = device.isReachable();
|
boolean reachable = device.isReachable();
|
||||||
|
|
||||||
binding.pairingButtons.setVisibility(paired ? View.GONE : View.VISIBLE);
|
binding.pairingButtons.setVisibility(paired ? View.GONE : View.VISIBLE);
|
||||||
binding.errorMessageContainer.setVisibility((paired && !reachable) ? View.VISIBLE : View.GONE);
|
errorBinding.errorMessageContainer.setVisibility((paired && !reachable) ? View.VISIBLE : View.GONE);
|
||||||
binding.notReachableMessage.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);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pluginListItems = new ArrayList<>();
|
pluginListItems = new ArrayList<>();
|
||||||
@ -300,10 +329,12 @@ public class DeviceFragment extends Fragment {
|
|||||||
dialog.show(getChildFragmentManager(), null);
|
dialog.show(getChildFragmentManager(), null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DeviceFragment.this.displayBatteryInfoIfPossible();
|
||||||
}
|
}
|
||||||
|
|
||||||
ListAdapter adapter = new ListAdapter(mActivity, pluginListItems);
|
ListAdapter adapter = new ListAdapter(mActivity, pluginListItems);
|
||||||
binding.buttonsList.setAdapter(adapter);
|
deviceBinding.buttonsList.setAdapter(adapter);
|
||||||
|
|
||||||
mActivity.invalidateOptionsMenu();
|
mActivity.invalidateOptionsMenu();
|
||||||
|
|
||||||
@ -373,4 +404,50 @@ public class DeviceFragment extends Fragment {
|
|||||||
pluginListItems.add(new FailedPluginListItem(plugin, action));
|
pluginListItems.add(new FailedPluginListItem(plugin, action));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user