tethering detection

This commit is contained in:
jens 2022-06-04 02:44:26 +02:00
parent b35208b7aa
commit bb1b3b0149
15 changed files with 356 additions and 36 deletions

View File

@ -168,6 +168,7 @@
<activity android:name=".ActivityManageActionSendBroadcast" />
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@ -166,6 +166,7 @@
<activity android:name=".ActivityManageActionSendBroadcast" />
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@ -153,6 +153,7 @@
<activity android:name=".ActivityManageActionSendBroadcast" />
<activity android:name=".ActivityManageActionRunExecutable" />
<activity android:name=".ActivityManageActionWifi" />
<activity android:name=".ActivityManageTriggerTethering" />
<activity
android:name=".ActivityMainTabLayout"
android:launchMode="singleTask">

View File

@ -77,17 +77,6 @@ public class ActivityMainScreen extends ActivityGeneric
tvLockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration);
tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound);
toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener);
Button bTether = (Button)findViewById(R.id.bTethering);
bTether.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
Toast.makeText(ActivityMainScreen.this, "Tethering active: " + String.valueOf(Actions.isTetheringActive1(ActivityMainScreen.this)), Toast.LENGTH_LONG).show();
}
});
bDonate = (Button)findViewById(R.id.bDonate);
if(!BuildConfig.FLAVOR.equalsIgnoreCase(AutomationService.flavor_name_googleplay))

View File

@ -127,6 +127,8 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionRunExecutableEdit = 814;
final static int requestCodeActionSetWifiAdd = 815;
final static int requestCodeActionSetWifiEdit = 816;
final static int requestCodeTriggerTetheringAdd = 817;
final static int requestCodeTriggerTetheringEdit = 818;
public static ActivityManageRule getInstance()
{
@ -312,6 +314,11 @@ public class ActivityManageRule extends Activity
broadcastEditor.putExtra(intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(broadcastEditor, requestCodeTriggerBroadcastReceivedEdit);
break;
case tethering:
Intent tetheringEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerTethering.class);
tetheringEditor.putExtra(intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
startActivityForResult(tetheringEditor, requestCodeTriggerTetheringEdit);
break;
default:
break;
}
@ -568,6 +575,8 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.alarm));
else if(types[i].toString().equals(Trigger_Enum.serviceStarts.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.alarm));
else if(types[i].toString().equals(Trigger_Enum.tethering.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.router));
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@ -767,6 +776,13 @@ public class ActivityManageRule extends Activity
startActivityForResult(broadcastTriggerEditor, requestCodeTriggerBroadcastReceivedAdd);
return;
}
else if(triggerType == Trigger_Enum.tethering)
{
newTrigger.setTriggerType(Trigger_Enum.tethering);
Intent tetheringTriggerEditor = new Intent(myContext, ActivityManageTriggerTethering.class);
startActivityForResult(tetheringTriggerEditor, requestCodeTriggerTetheringAdd);
return;
}
else
getTriggerParameterDialog(context, booleanChoices).show();
@ -1782,6 +1798,28 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerTetheringAdd)
{
if(resultCode == RESULT_OK)
{
newTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerTetheringEdit)
{
if(resultCode == RESULT_OK)
{
Trigger editedTrigger = new Trigger();
editedTrigger.setTriggerType(Trigger_Enum.tethering);
editedTrigger.setTriggerParameter(data.getBooleanExtra(intentNameTriggerParameter1, true));
editedTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, editedTrigger);
this.refreshTriggerList();
}
}
}
protected AlertDialog getActionTypeDialog()

View File

@ -0,0 +1,46 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.TextView;
import androidx.annotation.Nullable;
public class ActivityManageTriggerTethering extends Activity
{
RadioButton rbTetheringOn, rTetheringOff;
Button bTriggerTetheringSave;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_trigger_tethering);
rbTetheringOn = (RadioButton) findViewById(R.id.rbTetheringOn);
rTetheringOff = (RadioButton)findViewById(R.id.rTetheringOff);
bTriggerTetheringSave = (Button) findViewById(R.id.bTriggerTetheringSave);
Intent input = getIntent();
if(input.hasExtra(ActivityManageRule.intentNameTriggerParameter1))
rbTetheringOn.setChecked(input.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
bTriggerTetheringSave.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent response = new Intent();
response.putExtra(ActivityManageRule.intentNameTriggerParameter1, rbTetheringOn.isChecked());
setResult(RESULT_OK, response);
finish();
}
});
}
}

View File

@ -18,6 +18,7 @@ import com.jens.automation2.receivers.NoiseListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import com.jens.automation2.receivers.ProcessListener;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.TetheringReceiver;
import com.jens.automation2.receivers.TimeZoneListener;
import androidx.annotation.RequiresApi;
@ -59,7 +60,8 @@ public class ReceiverCoordinator
ProcessListener.class,
MediaPlayerListener.class,
ScreenStateReceiver.class,
TimeZoneListener.class
TimeZoneListener.class,
TetheringReceiver.class
};
}
catch (ClassNotFoundException e)
@ -77,7 +79,8 @@ public class ReceiverCoordinator
PhoneStatusListener.class,
ProcessListener.class,
ScreenStateReceiver.class,
TimeZoneListener.class
TimeZoneListener.class,
TetheringReceiver.class
};
}
}
@ -176,6 +179,9 @@ public class ReceiverCoordinator
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.deviceOrientation))
DeviceOrientationListener.getInstance().startListener(AutomationService.getInstance());
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.tethering))
TetheringReceiver.getInstance().startListener(AutomationService.getInstance());
try
{
Class testClass = Class.forName(ActivityManageRule.activityDetectionClassPath);
@ -216,6 +222,7 @@ public class ReceiverCoordinator
ProcessListener.stopProcessListener(AutomationService.getInstance());
MediaPlayerListener.getInstance().stopListener(AutomationService.getInstance());
DeviceOrientationListener.getInstance().stopListener(AutomationService.getInstance());
TetheringReceiver.getInstance().stopListener(AutomationService.getInstance());
try
{
@ -415,6 +422,24 @@ public class ReceiverCoordinator
}
}
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.tethering))
{
if(!TetheringReceiver.getInstance().isListenerRunning())
{
Miscellaneous.logEvent("i", "TetheringReceiver", "Starting TetheringReceiver because used in a new/changed rule.", 4);
// if(DevicePositionListener.getInstance().haveAllPermission())
TetheringReceiver.getInstance().startListener(AutomationService.getInstance());
}
}
else
{
if(TetheringReceiver.getInstance().isListenerRunning())
{
Miscellaneous.logEvent("i", "TetheringReceiver", "Shutting down TetheringReceiver because not used in any rule.", 4);
TetheringReceiver.getInstance().stopListener(AutomationService.getInstance());
}
}
AutomationService.updateNotification();
}
}

View File

@ -24,10 +24,10 @@ import com.jens.automation2.receivers.NotificationListener;
import com.jens.automation2.receivers.PhoneStatusListener;
import com.jens.automation2.receivers.ProcessListener;
import com.jens.automation2.receivers.ScreenStateReceiver;
import com.jens.automation2.receivers.TetheringReceiver;
import org.apache.commons.lang3.StringUtils;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@ -59,6 +59,7 @@ public class Trigger
deviceStarts,
serviceStarts,
broadcastReceived,
tethering,
phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
@ -113,6 +114,8 @@ public class Trigger
return context.getResources().getString(R.string.serviceStarts);
case broadcastReceived:
return context.getResources().getString(R.string.broadcastReceivedTitle);
case tethering:
return context.getResources().getString(R.string.tetheringState);
default:
return "Unknown";
}
@ -228,6 +231,10 @@ public class Trigger
if(!checkBroadcastReceived())
result = false;
break;
case tethering:
if(!checkTetheringActive())
result = false;
break;
default:
break;
}
@ -919,6 +926,11 @@ public class Trigger
return true;
}
boolean checkTetheringActive()
{
return TetheringReceiver.isTetheringActive() == triggerParameter;
}
public boolean checkDateTime(Object triggeringObject, boolean checkifStateChangedSinceLastRuleExecution)
{
/*
@ -1636,6 +1648,12 @@ public class Trigger
returnString.append(": " + triggerParameter2);
break;
case tethering:
if(triggerParameter)
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.tetheringActive));
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.tetheringNotActive));
break;
default:
returnString.append("error");
break;

View File

@ -6,6 +6,7 @@ import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
@ -54,22 +55,6 @@ public class BroadcastListener extends android.content.BroadcastReceiver impleme
for(String key : intent.getExtras().keySet())
{
Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
Object ob = intent.getExtras().get(key);
String target = null;
if(Build.VERSION.SDK_INT >= 26)
target = "tetherArray";
else
target = "activeArray";
if(key.equals(target) && ob instanceof ArrayList)
{
if(((ArrayList<String>)ob).size() > 0)
;
}
Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
}
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.broadcastReceived);

View File

@ -0,0 +1,130 @@
package com.jens.automation2.receivers;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.util.Log;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.Rule;
import com.jens.automation2.Trigger;
import java.util.ArrayList;
public class TetheringReceiver extends android.content.BroadcastReceiver implements AutomationListenerInterface
{
public static AutomationService automationServiceRef = null;
private static boolean receiverActive = false;
private static TetheringReceiver receiverInstance = null;
private static IntentFilter intentFilter = null;
private static boolean tetheringActive = false;
public static TetheringReceiver getInstance()
{
if(receiverInstance == null)
receiverInstance = new TetheringReceiver();
return receiverInstance;
}
public static boolean isTetheringActive()
{
return tetheringActive;
}
@Override
public void onReceive(Context context, Intent intent)
{
for(String key : intent.getExtras().keySet())
{
// Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
Object ob = intent.getExtras().get(key);
String target = null;
if(Build.VERSION.SDK_INT >= 26)
target = "tetherArray";
else
target = "activeArray";
if(key.equals(target) && ob instanceof ArrayList)
{
if(((ArrayList<String>)ob).size() > 0)
tetheringActive = true;
else
tetheringActive = false;
}
// Miscellaneous.logEvent("i", "Broadcast extra", "Broadcast " + intent.getAction() + " has extra " + key + " and type " + intent.getExtras().get(key).getClass().getName(), 4);
}
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.tethering);
for(int i=0; i<ruleCandidates.size(); i++)
{
if(ruleCandidates.get(i).getsGreenLight(context))
ruleCandidates.get(i).activate(automationServiceRef, false);
}
}
@Override
public void startListener(AutomationService automationService)
{
if(!receiverActive)
{
TetheringReceiver.automationServiceRef = automationService;
if(receiverInstance == null)
receiverInstance = new TetheringReceiver();
if(intentFilter == null)
{
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.TETHER_STATE_CHANGED");
}
try
{
automationServiceRef.registerReceiver(receiverInstance, intentFilter);
receiverActive = true;
}
catch(Exception e)
{
/*
We might be confronted with permission issues here.
*/
Miscellaneous.logEvent("e", "TetheringReceiver", Log.getStackTraceString(e), 1);
receiverActive = false;
}
}
}
@Override
public void stopListener(AutomationService automationService)
{
if(receiverActive)
{
if(receiverInstance != null)
{
automationServiceRef.unregisterReceiver(receiverInstance);
receiverInstance = null;
}
receiverActive = false;
}
}
@Override
public boolean isListenerRunning()
{
return receiverActive;
}
@Override
public Trigger.Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger.Trigger_Enum[] { Trigger.Trigger_Enum.tethering};
}
}

View File

@ -58,11 +58,14 @@
android:layout_marginTop="@dimen/default_margin">
<TextView
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/state" />
<RadioGroup
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="@dimen/default_margin" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginBottom="@dimen/default_margin"
android:text="@string/tetheringState"/>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:stretchColumns="1"
android:shrinkColumns="1" >
<TableRow
android:layout_marginTop="@dimen/default_margin">
<TextView
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:text="@string/state" />
<RadioGroup
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<RadioButton
android:id="@+id/rbTetheringOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/on" />
<RadioButton
android:id="@+id/rTetheringOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/off" />
</RadioGroup>
</TableRow>
</TableLayout>
<Button
android:id="@+id/bTriggerTetheringSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/save" />
</LinearLayout>
</ScrollView>

View File

@ -339,12 +339,6 @@
android:layout_marginTop="30dp"
android:gravity="center_horizontal" >
<Button
android:id="@+id/bTethering"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/test" />
<Button
android:id="@+id/bShowHelp"
android:layout_gravity="center_vertical"

View File

@ -723,4 +723,18 @@
<string name="explanationBroadcastTrigger">La mayoría de los eventos en su teléfono se \"publicado\" transmitiéndolos a través del sistema operativo.\nPor ejemplo, activar / desactivar el modo avión activará dicha transmisión. Esas transmisiones no son automáticamente visibles / audibles, pero si una aplicación (como Automatización) está interesada, puede conectarse a ellas. Cuando ocurran, se le notificará y podrá reaccionar.\n\nPuede definir aquí un evento de difusión para el que la aplicación esperará. Puede ingresarlo manualmente, copiarlo y pegarlo desde algún lugar o elegir uno de la lista de sugerencias. Como este desencadenante está destinado a ser y seguir siendo muy flexible, no puedo proporcionarle explicaciones para los elementos.\n\nLa lista de sugerencias no pretende estar completa. Visite la siguiente URL para echar un vistazo a la documentación de Android.\nTambién cualquier aplicación puede enviar eventos personalizados que no aparecerán en la documentación de Android, por supuesto.\n\nMuchas transmisiones requieren permisos específicos para funcionar. Intento solicitar permisos donde sé que serán necesarios. Si cree que se requiere un permiso para la acción que ingresó, hágamelo saber.\n\nNo recibido significa que no ha habido tal transmisión desde que se inició el servicio. Responder a ciertos parámetros está en desarrollo.</string>
<string name="logsExplanation">Um eine unnötige Abnutzung Ihres Speichers zu vermeiden, werden Protokolle standardmäßig nicht gespeichert. Wenn Sie also ein Problem haben, aktivieren Sie bitte zuerst die Anmeldeeinstellungen und setzen Sie den Protokollpegel auf 5. Reproduzieren Sie dann das Problem. Erst dann können Protokolle angehängt werden.</string>
<string name="directionStringDoesNotContain">enthält nicht</string>
<string name="path">Pfad</string>
<string name="runExecutable">Programm/Script ausführen</string>
<string name="parameters">Parameter</string>
<string name="chooseExecutable">Datei auswählen</string>
<string name="runAsRoot">Als root ausführen</string>
<string name="selectValidExecutable">Wählen Sie eine gültige ausführbare Datei aus.</string>
<string name="fileNotExecutable">Diese Datei ist nicht ausführbar.</string>
<string name="usingRoot">als root</string>
<string name="tetheringActive">Tethering ist aktiv</string>
<string name="tetheringNotActive">Tethering ist nicht aktiv</string>
<string name="tetheringState">Tethering Status</string>
<string name="wifiExplanation2">Während der Flugmodus aktiv ist, kann WLAN nur von Anwendungen ein- oder ausgeschaltet werden, wenn root-Rechte dafür verwendet werden.</string>
<string name="wifiExplanation1">Anwendungen, die auf Android Q oder höher ausgerichtet sind, können WLAN nicht mehr ein- oder ausschalten. Daran ist Google schuld, nicht ich.\n\nSie können diese Einschränkung umgehen, indem Sie Ihr Gerät rooten und die Checkbox unten aktivieren. Alternativ laden Sie sich diese Anwendung von F-Droid oder meiner Webseite herunter. In diesen Versionen bin ich nicht gezwungen, die Anwendungen auf die neuesten API Level zu unterstützen.</string>
<string name="runExecutableExplanation">Sie können ein Script oder eine andere ausführbare Datei auswählen, die dann als Aktion ausgeführt wird.\n\nAllerdings gibt es ein paar Voraussetzungen, um die Sie sich selbst kümmern müssen. Google hat es sehr schwer gemacht, irgendetwas außer normalen Android Anwendungen auszuführen.\n\n1.\nDie Datei muß im Dateisystem als ausführbar markiert sein. Auf einem normalen Android-System (ohne Root) ist das in der Tat der schwierigste Teil.\n\n2.\nDas bedeutet auch, daß auch Automation in der Lage sein muß, die Datei auszuführen, nicht nur der Besitzer oder die Gruppe.\n\n3.\nWenn es ein Script ist, muß eine gültige Shell im Header des Scripts definiert sein.</string>
</resources>

View File

@ -831,4 +831,7 @@
<string name="wifiExplanation2">While airplane mode is activated, wifi can only be toggled from applications when using root permissions for that.</string>
<string name="usingRoot">using root</string>
<string name="runExecutableExplanation">You can select a script or an executable file here that will be executed as an action.\n\nBut there are some prerequisites which you have to deal with on your own. Google has made it very hard to run anything other than regular Android applications.\n\n1.\nThe file must be marked as executable in the file system. On a regular Android system (without root) this is actually the hard part.\n\n2.\nThat also means Automation must be able to execute the file, not just the owner or the group.\n\n3.\nIf it is a script, a valid shell be specified in the script\'s header.</string>
<string name="tetheringActive">tethering is active</string>
<string name="tetheringNotActive">tethering is not active</string>
<string name="tetheringState">Tethering state</string>
</resources>