mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-30 13:47:41 +00:00
Merge branch '1.x'
# Conflicts: # src/org/kde/kdeconnect/Plugins/TelepathyPlugin/TelepathyPlugin.java
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.kde.kdeconnect_tp"
|
package="org.kde.kdeconnect_tp"
|
||||||
android:versionCode="1621"
|
android:versionCode="1650"
|
||||||
android:versionName="1.6.2">
|
android:versionName="1.6.5">
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="9"
|
<uses-sdk android:minSdkVersion="9"
|
||||||
android:targetSdkVersion="25" />
|
android:targetSdkVersion="25" />
|
||||||
|
@@ -59,7 +59,7 @@ public class ContactsHelper {
|
|||||||
, PhoneLookup.ID */
|
, PhoneLookup.ID */
|
||||||
},
|
},
|
||||||
null, null, null);
|
null, null, null);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (Exception e) {
|
||||||
return contactInfo;
|
return contactInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,25 +6,53 @@ import android.net.Network;
|
|||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.LineNumberReader;
|
||||||
|
|
||||||
public class NetworkHelper {
|
public class NetworkHelper {
|
||||||
|
|
||||||
public static boolean isOnMobileNetwork(Context context) {
|
public static boolean isOnMobileNetwork(Context context) {
|
||||||
if (context == null || android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
|
if (context == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||||
return false; //No good way to know it
|
return false; //No good way to know it
|
||||||
}
|
}
|
||||||
boolean mobile = false;
|
try {
|
||||||
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
boolean mobile = false;
|
||||||
Network[] networks = connMgr.getAllNetworks();
|
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
for (Network network : networks) {
|
Network[] networks = connMgr.getAllNetworks();
|
||||||
NetworkInfo info = connMgr.getNetworkInfo(network);
|
for (Network network : networks) {
|
||||||
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
|
NetworkInfo info = connMgr.getNetworkInfo(network);
|
||||||
mobile = info.isConnected();
|
if (info == null) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
|
||||||
|
mobile = info.isConnected();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//Log.e(info.getTypeName(),""+info.isAvailable());
|
||||||
|
if (info.isAvailable()) return false; //We are connected to at least one non-mobile network
|
||||||
}
|
}
|
||||||
Log.e(info.getTypeName(),""+info.isAvailable());
|
if (mobile) { //We suspect we are on a mobile net
|
||||||
if (info.isAvailable()) return false; //We are connected to at least one non-mobile network
|
try {
|
||||||
|
//Check the number of network neighbours, on data it should be 0
|
||||||
|
LineNumberReader is = new LineNumberReader(new FileReader("/proc/net/arp"));
|
||||||
|
is.skip(Long.MAX_VALUE);
|
||||||
|
//Log.e("NetworkHelper", "procnetarp has " + is.getLineNumber() + " lines");
|
||||||
|
if (is.getLineNumber() > 1) { //The first line are the headers
|
||||||
|
return false; //I have neighbours, so this doesn't look like a mobile network
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("NetworkHelper", "Exception reading procnetarp");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Log.d("isOnMobileNetwork", "Something went wrong, but this is non-critical.");
|
||||||
}
|
}
|
||||||
return mobile;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -40,7 +40,7 @@ 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;
|
||||||
|
|
||||||
private NetworkPackage lastInfo = null;
|
private NetworkPackage batteryInfo = new NetworkPackage(PACKAGE_TYPE_BATTERY);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
@@ -56,18 +56,18 @@ public class BatteryPlugin extends Plugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent batteryIntent) {
|
public void onReceive(Context context, Intent batteryIntent) {
|
||||||
|
|
||||||
Intent batteryChargeIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||||
int level = batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
|
||||||
int scale = batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
|
int plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||||
int currentCharge = level*100 / scale;
|
|
||||||
boolean isCharging = (0 != batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
|
int currentCharge = (level == -1)? batteryInfo.getInt("currentCharge") : level*100 / scale;
|
||||||
|
boolean isCharging = (plugged == -1)? batteryInfo.getBoolean("isCharging") : (0 != plugged);
|
||||||
boolean lowBattery = Intent.ACTION_BATTERY_LOW.equals(batteryIntent.getAction());
|
boolean lowBattery = Intent.ACTION_BATTERY_LOW.equals(batteryIntent.getAction());
|
||||||
int thresholdEvent = lowBattery? THRESHOLD_EVENT_BATTERY_LOW : THRESHOLD_EVENT_NONE;
|
int thresholdEvent = lowBattery? THRESHOLD_EVENT_BATTERY_LOW : THRESHOLD_EVENT_NONE;
|
||||||
|
|
||||||
if (lastInfo != null
|
if (isCharging == batteryInfo.getBoolean("isCharging")
|
||||||
&& isCharging == lastInfo.getBoolean("isCharging")
|
&& currentCharge == batteryInfo.getInt("currentCharge")
|
||||||
&& currentCharge == lastInfo.getInt("currentCharge")
|
&& thresholdEvent == batteryInfo.getInt("thresholdEvent")
|
||||||
&& thresholdEvent == lastInfo.getInt("thresholdEvent")
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
//Do not send again if nothing has changed
|
//Do not send again if nothing has changed
|
||||||
@@ -75,12 +75,10 @@ public class BatteryPlugin extends Plugin {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_BATTERY);
|
batteryInfo.set("currentCharge", currentCharge);
|
||||||
np.set("currentCharge", currentCharge);
|
batteryInfo.set("isCharging", isCharging);
|
||||||
np.set("isCharging", isCharging);
|
batteryInfo.set("thresholdEvent", thresholdEvent);
|
||||||
np.set("thresholdEvent", thresholdEvent);
|
device.sendPackage(batteryInfo);
|
||||||
device.sendPackage(np);
|
|
||||||
lastInfo = np;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,8 +87,10 @@ public class BatteryPlugin extends Plugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
IntentFilter intentFilter = new IntentFilter();
|
||||||
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_LOW));
|
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
||||||
|
context.registerReceiver(receiver, intentFilter);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,9 +104,7 @@ public class BatteryPlugin extends Plugin {
|
|||||||
public boolean onPackageReceived(NetworkPackage np) {
|
public boolean onPackageReceived(NetworkPackage np) {
|
||||||
|
|
||||||
if (np.getBoolean("request")) {
|
if (np.getBoolean("request")) {
|
||||||
if (lastInfo != null) {
|
device.sendPackage(batteryInfo);
|
||||||
device.sendPackage(lastInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -138,6 +138,10 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
|
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
|
||||||
|
if (statusBarNotification == null) {
|
||||||
|
Log.w("onNotificationRemoved", "notification is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
String id = getNotificationKeyCompat(statusBarNotification);
|
String id = getNotificationKeyCompat(statusBarNotification);
|
||||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
|
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
|
||||||
np.set("id", id);
|
np.set("id", id);
|
||||||
|
@@ -125,7 +125,7 @@ class SimpleSftpServer {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
try {
|
try {
|
||||||
started = false;
|
started = false;
|
||||||
sshd.stop();
|
sshd.stop(true);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -144,6 +144,17 @@ class SimpleSftpServer {
|
|||||||
try {
|
try {
|
||||||
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
|
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
|
||||||
NetworkInterface intf = en.nextElement();
|
NetworkInterface intf = en.nextElement();
|
||||||
|
|
||||||
|
// Anything with rmnet is related to cellular connections or USB
|
||||||
|
// tethering mechanisms. See:
|
||||||
|
//
|
||||||
|
// https://android.googlesource.com/kernel/msm/+/android-msm-flo-3.4-kitkat-mr1/Documentation/usb/gadget_rmnet.txt
|
||||||
|
//
|
||||||
|
// If we run across an interface that has this, we can safely
|
||||||
|
// ignore it. In fact, it's much safer to do. If we don't, we
|
||||||
|
// might get invalid IP adddresses out of it.
|
||||||
|
if(intf.getDisplayName().contains("rmnet")) continue;
|
||||||
|
|
||||||
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
|
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
|
||||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||||
if (!inetAddress.isLoopbackAddress()) {
|
if (!inetAddress.isLoopbackAddress()) {
|
||||||
|
@@ -27,6 +27,8 @@ import android.support.v4.content.ContextCompat;
|
|||||||
import android.telephony.SmsManager;
|
import android.telephony.SmsManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.kde.kdeconnect.NetworkPackage;
|
import org.kde.kdeconnect.NetworkPackage;
|
||||||
import org.kde.kdeconnect.Plugins.Plugin;
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
import org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin;
|
import org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin;
|
||||||
@@ -70,10 +72,17 @@ public class TelepathyPlugin extends Plugin {
|
|||||||
String phoneNo = np.getString("phoneNumber");
|
String phoneNo = np.getString("phoneNumber");
|
||||||
String sms = np.getString("messageBody");
|
String sms = np.getString("messageBody");
|
||||||
try {
|
try {
|
||||||
SmsManager smsManager = SmsManager.getDefault();
|
if(permissionCheck == PackageManager.PERMISSION_GRANTED) {
|
||||||
smsManager.sendTextMessage(phoneNo, null, sms, null, null);
|
SmsManager smsManager = SmsManager.getDefault();
|
||||||
Log.d("TelepathyPlugin", "SMS sent");
|
|
||||||
|
|
||||||
|
ArrayList<String> parts = smsManager.divideMessage(sms);
|
||||||
|
|
||||||
|
// If this message turns out to fit in a single SMS, sendMultpartTextMessage
|
||||||
|
// properly handles that case
|
||||||
|
smsManager.sendMultipartTextMessage(phoneNo, null, parts, null, null);
|
||||||
|
} else if(permissionCheck == PackageManager.PERMISSION_DENIED){
|
||||||
|
// TODO Request Permission SEND_SMS
|
||||||
|
}
|
||||||
//TODO: Notify other end
|
//TODO: Notify other end
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//TODO: Notify other end
|
//TODO: Notify other end
|
||||||
|
@@ -37,8 +37,10 @@ import android.util.Log;
|
|||||||
import org.kde.kdeconnect.Helpers.ContactsHelper;
|
import org.kde.kdeconnect.Helpers.ContactsHelper;
|
||||||
import org.kde.kdeconnect.NetworkPackage;
|
import org.kde.kdeconnect.NetworkPackage;
|
||||||
import org.kde.kdeconnect.Plugins.Plugin;
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
|
import org.kde.kdeconnect_tp.BuildConfig;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
@@ -78,11 +80,19 @@ public class TelephonyPlugin extends Plugin {
|
|||||||
final Bundle bundle = intent.getExtras();
|
final Bundle bundle = intent.getExtras();
|
||||||
if (bundle == null) return;
|
if (bundle == null) return;
|
||||||
final Object[] pdus = (Object[]) bundle.get("pdus");
|
final Object[] pdus = (Object[]) bundle.get("pdus");
|
||||||
|
ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
|
||||||
|
|
||||||
for (Object pdu : pdus) {
|
for (Object pdu : pdus) {
|
||||||
SmsMessage message = SmsMessage.createFromPdu((byte[])pdu);
|
// I hope, but am not sure, that the pdus array is in the order that the parts
|
||||||
smsBroadcastReceived(message);
|
// of the SMS message should be
|
||||||
|
// If it is not, I belive the pdu contains the information necessary to put it
|
||||||
|
// in order, but in my testing the order seems to be correct, so I won't worry
|
||||||
|
// about it now.
|
||||||
|
messages.add(SmsMessage.createFromPdu((byte[])pdu));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smsBroadcastReceived(messages);
|
||||||
|
|
||||||
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
|
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
|
||||||
|
|
||||||
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
|
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
|
||||||
@@ -208,7 +218,14 @@ public class TelephonyPlugin extends Plugin {
|
|||||||
lastState = state;
|
lastState = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void smsBroadcastReceived(SmsMessage message) {
|
private void smsBroadcastReceived(ArrayList<SmsMessage> messages) {
|
||||||
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
if (!(messages.size() > 0))
|
||||||
|
{
|
||||||
|
throw new AssertionError("This method requires at least one message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Log.e("SmsBroadcastReceived", message.toString());
|
//Log.e("SmsBroadcastReceived", message.toString());
|
||||||
|
|
||||||
@@ -216,12 +233,18 @@ public class TelephonyPlugin extends Plugin {
|
|||||||
|
|
||||||
np.set("event","sms");
|
np.set("event","sms");
|
||||||
|
|
||||||
String messageBody = message.getMessageBody();
|
String messageBody = new String();
|
||||||
|
|
||||||
|
for (int index = 0; index < messages.size(); index ++)
|
||||||
|
{
|
||||||
|
messageBody += messages.get(index).getMessageBody();
|
||||||
|
}
|
||||||
|
|
||||||
if (messageBody != null) {
|
if (messageBody != null) {
|
||||||
np.set("messageBody",messageBody);
|
np.set("messageBody",messageBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
String phoneNumber = message.getOriginatingAddress();
|
String phoneNumber = messages.get(0).getOriginatingAddress();
|
||||||
|
|
||||||
int permissionCheck = ContextCompat.checkSelfPermission(context,
|
int permissionCheck = ContextCompat.checkSelfPermission(context,
|
||||||
Manifest.permission.READ_CONTACTS);
|
Manifest.permission.READ_CONTACTS);
|
||||||
|
@@ -446,6 +446,10 @@ public class DeviceFragment extends Fragment {
|
|||||||
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
||||||
public void onServiceStart(BackgroundService service) {
|
public void onServiceStart(BackgroundService service) {
|
||||||
Device dev = service.getDevice(devId);
|
Device dev = service.getDevice(devId);
|
||||||
|
if (dev == null) {
|
||||||
|
Log.w("rejectPairing", "Device no longer exists: "+devId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
activity.getSupportActionBar().setTitle(dev.getName());
|
activity.getSupportActionBar().setTitle(dev.getName());
|
||||||
|
|
||||||
dev.addPairingCallback(frag.pairingCallback);
|
dev.addPairingCallback(frag.pairingCallback);
|
||||||
@@ -465,6 +469,10 @@ public class DeviceFragment extends Fragment {
|
|||||||
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
||||||
public void onServiceStart(BackgroundService service) {
|
public void onServiceStart(BackgroundService service) {
|
||||||
Device dev = service.getDevice(devId);
|
Device dev = service.getDevice(devId);
|
||||||
|
if (dev == null) {
|
||||||
|
Log.w("rejectPairing", "Device no longer exists: "+devId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
activity.getSupportActionBar().setTitle(dev.getName());
|
activity.getSupportActionBar().setTitle(dev.getName());
|
||||||
|
|
||||||
dev.addPairingCallback(frag.pairingCallback);
|
dev.addPairingCallback(frag.pairingCallback);
|
||||||
|
@@ -132,6 +132,11 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
|
if (!isAdded()) {
|
||||||
|
//Fragment is not attached to an activity. We will crash if we try to do anything here.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (listRefreshCalledThisFrame) {
|
if (listRefreshCalledThisFrame) {
|
||||||
// This makes sure we don't try to call list.getFirstVisiblePosition()
|
// This makes sure we don't try to call list.getFirstVisiblePosition()
|
||||||
// twice per frame, because the second time the list hasn't been drawn
|
// twice per frame, because the second time the list hasn't been drawn
|
||||||
|
Reference in New Issue
Block a user