profile trigger

This commit is contained in:
jens 2022-01-04 17:51:27 +01:00
parent 8c6331237d
commit 5653a9c70e
10 changed files with 313 additions and 28 deletions

View File

@ -147,6 +147,7 @@
<activity android:name=".ActivityDisplayLongMessage" />
<activity android:name=".ActivityManageActionSendTextMessage" />
<activity android:name=".ActivityManageActionPlaySound" />
<activity android:name=".ActivityManageTriggerProfile" />
<activity android:name=".ActivityManageTriggerTimeFrame" />
<activity android:name=".ActivityMaintenance" />
<activity android:name=".ActivityManageTriggerPhoneCall" />

View File

@ -16,6 +16,7 @@ import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Rule implements Comparable<Rule>
@ -23,9 +24,9 @@ public class Rule implements Comparable<Rule>
private static ArrayList<Rule> ruleCollection = new ArrayList<Rule>();
public static boolean isAnyRuleActive = false;
private static ArrayList<Rule> ruleRunHistory = new ArrayList<Rule>();
private static List<Rule> ruleRunHistory = new ArrayList<Rule>();
public static ArrayList<Rule> getRuleRunHistory()
public static List<Rule> getRuleRunHistory()
{
return ruleRunHistory;
}

View File

@ -3,7 +3,6 @@ package com.jens.automation2;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@ -14,6 +13,7 @@ import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.text.util.Linkify;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
@ -50,6 +50,7 @@ public class ActivityManageRule extends Activity
{
final static String activityDetectionClassPath = "com.jens.automation2.receivers.ActivityDetectionReceiver";
public final static String intentNameTriggerParameter1 = "triggerParameter1";
public final static String intentNameTriggerParameter2 = "triggerParameter2";
public final static String intentNameActionParameter1 = "actionParameter1";
public final static String intentNameActionParameter2 = "actionParameter2";
@ -106,6 +107,8 @@ public class ActivityManageRule extends Activity
final static int requestCodeActionPlaySoundEdit = 502;
final static int requestCodeTriggerPhoneCallAdd = 601;
final static int requestCodeTriggerPhoneCallEdit = 602;
final static int requestCodeTriggerProfileAdd = 603;
final static int requestCodeTriggerProfileEdit = 604;
final static int requestCodeTriggerWifiAdd = 723;
final static int requestCodeTriggerWifiEdit = 724;
final static int requestCodeActionSendTextMessageAdd = 5001;
@ -271,6 +274,12 @@ public class ActivityManageRule extends Activity
phoneCallEditor.putExtra("edit", true);
startActivityForResult(phoneCallEditor, requestCodeTriggerPhoneCallEdit);
break;
case profileActive:
Intent profileActiveEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerProfile.class);
profileActiveEditor.putExtra(ActivityManageRule.intentNameTriggerParameter1, selectedTrigger.getTriggerParameter());
profileActiveEditor.putExtra(ActivityManageRule.intentNameTriggerParameter2, selectedTrigger.getTriggerParameter2());
startActivityForResult(profileActiveEditor, requestCodeTriggerProfileEdit);
break;
case wifiConnection:
Intent wifiEditor = new Intent(ActivityManageRule.this, ActivityManageTriggerWifi.class);
wifiEditor.putExtra("edit", true);
@ -496,6 +505,8 @@ public class ActivityManageRule extends Activity
items.add(new Item(typesLong[i].toString(), R.drawable.notification));
else if(types[i].toString().equals(Trigger_Enum.deviceOrientation.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.smartphone));
else if(types[i].toString().equals(Trigger_Enum.profileActive.toString()))
items.add(new Item(typesLong[i].toString(), R.drawable.sound));
else
items.add(new Item(typesLong[i].toString(), R.drawable.placeholder));
}
@ -568,7 +579,6 @@ public class ActivityManageRule extends Activity
Intent wifiTriggerEditor = new Intent(myContext, ActivityManageTriggerWifi.class);
startActivityForResult(wifiTriggerEditor, requestCodeTriggerWifiAdd);
return;
// booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
}
else if(triggerType == Trigger_Enum.deviceOrientation)
{
@ -576,10 +586,7 @@ public class ActivityManageRule extends Activity
Intent devicePositionTriggerEditor = new Intent(myContext, ActivityManageTriggerDeviceOrientation.class);
startActivityForResult(devicePositionTriggerEditor, requestCodeTriggerDeviceOrientationAdd);
return;
// booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
}
// else if(triggerType == Trigger_Enum.wifiConnection)
// booleanChoices = new String[]{getResources().getString(R.string.connected), getResources().getString(R.string.disconnected)};
else if(triggerType == Trigger_Enum.process_started_stopped)
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
else if(triggerType == Trigger_Enum.notification)
@ -599,7 +606,13 @@ public class ActivityManageRule extends Activity
Intent phoneTriggerEditor = new Intent(myContext, ActivityManageTriggerPhoneCall.class);
startActivityForResult(phoneTriggerEditor, requestCodeTriggerPhoneCallAdd);
return;
// booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
}
else if(triggerType == Trigger_Enum.profileActive)
{
newTrigger.setTriggerType(Trigger_Enum.profileActive);
Intent profileTriggerEditor = new Intent(myContext, ActivityManageTriggerProfile.class);
startActivityForResult(profileTriggerEditor, requestCodeTriggerProfileAdd);
return;
}
else if(triggerType == Trigger_Enum.activityDetection)
{
@ -622,7 +635,7 @@ public class ActivityManageRule extends Activity
}
catch (IllegalAccessException | InvocationTargetException e)
{
e.printStackTrace();
Miscellaneous.logEvent("w", "ActivityDetection", "Either play services are not available or the ActivityDetection classes are not. " + Log.getStackTraceString(e), 4);
}
return;
}
@ -1428,6 +1441,30 @@ public class ActivityManageRule extends Activity
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerProfileAdd)
{
if(resultCode == RESULT_OK)
{
newTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
newTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
newTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().add(newTrigger);
this.refreshTriggerList();
}
}
else if(requestCode == requestCodeTriggerProfileEdit)
{
if(resultCode == RESULT_OK)
{
Trigger editedTrigger = new Trigger();
editedTrigger.setTriggerType(Trigger_Enum.profileActive);
editedTrigger.setTriggerParameter(data.getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true));
editedTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageRule.intentNameTriggerParameter2));
editedTrigger.setParentRule(ruleToEdit);
ruleToEdit.getTriggerSet().set(editIndex, editedTrigger);
this.refreshTriggerList();
}
}
}
protected AlertDialog getActionTypeDialog()

View File

@ -0,0 +1,116 @@
package com.jens.automation2;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.Nullable;
import java.util.List;
public class ActivityManageTriggerProfile extends Activity
{
public static final String profileFieldName = "profileName";
boolean editMode = false;
Button bSaveTriggerProfile;
Spinner spinnerProfiles;
CheckBox chkProfileActive, chkProfileCheckSettings;
ArrayAdapter<Profile> profileSpinnerAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_trigger_profile);
bSaveTriggerProfile = (Button)findViewById(R.id.bSaveTriggerProfile);
spinnerProfiles = (Spinner)findViewById(R.id.spinnerProfiles);
chkProfileActive = (CheckBox)findViewById(R.id.chkProfileActive);
chkProfileCheckSettings = (CheckBox)findViewById(R.id.chkProfileCheckSettings);
try
{
profileSpinnerAdapter = new ArrayAdapter<Profile>(this, R.layout.text_view_for_poi_listview_mediumtextsize, Profile.getProfileCollection());
loadProfileItems();
}
catch (Exception e)
{
Miscellaneous.logEvent("w", "ActivityManageTriggerProfile", Log.getStackTraceString(e), 1);
}
if(getIntent().hasExtra(ActivityManageRule.intentNameTriggerParameter2))
{
editMode = true;
try
{
String values[] = getIntent().getStringExtra(ActivityManageRule.intentNameTriggerParameter2).split(Trigger.triggerParameter2Split);
if(values.length >= 2)
{
boolean active = getIntent().getBooleanExtra(ActivityManageRule.intentNameTriggerParameter1, true);
chkProfileActive.setChecked(active);
boolean checkSettings = Boolean.parseBoolean(values[0]);
chkProfileCheckSettings.setChecked(checkSettings);
String profileName = values[1];
List<Profile> profileList = Profile.getProfileCollection();
for(int i = 0; i < profileList.size(); i++)
{
if(profileList.get(i).getName().equals(profileName))
{
spinnerProfiles.setSelection(i);
break;
}
}
}
}
catch(Exception e)
{
Toast.makeText(ActivityManageTriggerProfile.this, getResources().getString(R.string.triggerWrong), Toast.LENGTH_SHORT).show();
Miscellaneous.logEvent("e", "ActivityManageTriggerProfile", "There\'s something wrong with parameters. Content: " + getIntent().getStringExtra(ActivityManageRule.intentNameActionParameter2) + ", " + Log.getStackTraceString(e), 1);
}
}
bSaveTriggerProfile.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent returnData = new Intent();
returnData.putExtra(ActivityManageRule.intentNameTriggerParameter1, chkProfileActive.isChecked());
returnData.putExtra(ActivityManageRule.intentNameTriggerParameter2,
spinnerProfiles.getSelectedItem().toString() + Trigger.triggerParameter2Split +
chkProfileCheckSettings.isChecked());
setResult(RESULT_OK, returnData);
finish();
}
});
}
private void loadProfileItems()
{
try
{
if(spinnerProfiles.getAdapter() == null)
spinnerProfiles.setAdapter(profileSpinnerAdapter);
profileSpinnerAdapter.notifyDataSetChanged();
}
catch(NullPointerException e)
{
e.printStackTrace();
}
}
}

View File

@ -1065,6 +1065,23 @@ public class Miscellaneous extends Service
return "";
}
public static String explode(String glue, String[] inputArray)
{
if(inputArray != null)
{
StringBuilder builder = new StringBuilder();
for (String s : inputArray)
builder.append(s + glue);
if (builder.length() > 0)
builder.delete(builder.length() - glue.length(), builder.length());
return builder.toString();
}
else
return "";
}
public static boolean isGooglePlayInstalled(Context context)
{
// return false;

View File

@ -14,10 +14,12 @@ import com.jens.automation2.Action.Action_Enum;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Profile implements Comparable<Profile>
{
protected static ArrayList<Profile> profileCollection = new ArrayList<Profile>();
protected static List<Profile> profileCollection = new ArrayList<Profile>();
protected static List<Profile> profileActivationHistory = new ArrayList<>();
protected String name;
protected String oldName;
@ -267,7 +269,7 @@ public class Profile implements Comparable<Profile>
return hapticFeedback;
}
public static ArrayList<Profile> getProfileCollection()
public static List<Profile> getProfileCollection()
{
return profileCollection;
}
@ -395,6 +397,18 @@ public class Profile implements Comparable<Profile>
{
for(Rule oneRule : rulesThatReferenceMe)
{
for(Trigger oneTrigger : oneRule.getTriggerSet())
{
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.profileActive)
{
String[] parts = oneTrigger.getTriggerParameter2().split(Trigger.triggerParameter2Split);
parts[1] = this.name;
oneTrigger.setTriggerParameter2(Miscellaneous.explode(Trigger.triggerParameter2Split, parts));
// We don't need to save the file. This will happen anyway in PointOfInterest.writePoisToFile() below.
}
}
for(Action oneAction : oneRule.getActionSet())
{
if(oneAction.getAction() == Action_Enum.changeSoundProfile)
@ -463,6 +477,8 @@ public class Profile implements Comparable<Profile>
{
Miscellaneous.logEvent("i", "Profile " + this.getName(), String.format(context.getResources().getString(R.string.profileActivate), this.getName()), 3);
profileActivationHistory.add(this);
AutomationService.getInstance().checkLockSoundChangesTimeElapsed();
if(AutomationService.getInstance().getLockSoundChangesEnd() == null)

View File

@ -117,6 +117,10 @@ public class Trigger
if(!getParentRule().checkActivityDetection(this))
result = false;
break;
case profileActive:
if(!checkProfileActive())
result = false;
break;
default:
break;
}
@ -273,6 +277,34 @@ public class Trigger
return true;
}
boolean checkProfileActive()
{
try
{
String demandedProfileName = getTriggerParameter2().split(Trigger.triggerParameter2Split)[0];
Profile lastProfile = null;
if(Profile.profileActivationHistory.size() > 0)
{
lastProfile = Profile.profileActivationHistory.get(Profile.profileActivationHistory.size() - 1);
if (getTriggerParameter())
return demandedProfileName.equals(lastProfile.getName());
else
return !demandedProfileName.equals(lastProfile.getName());
}
else
return !getTriggerParameter();
}
catch(Exception e)
{
Miscellaneous.logEvent("w", "Trigger", "Error checking profile trigger.", 4);
}
return false;
}
boolean checkDeviceOrientation()
{
String deviceOrientationPieces[] = getTriggerParameter2().split(Trigger.triggerParameter2Split);
@ -986,7 +1018,7 @@ public class Trigger
*/
public enum Trigger_Enum {
pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped, airplaneMode, roaming, nfcTag, activityDetection, bluetoothConnection, headsetPlugged, notification, deviceOrientation, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
pointOfInterest, timeFrame, charging, batteryLevel, usb_host_connection, speed, noiseLevel, wifiConnection, process_started_stopped, airplaneMode, roaming, nfcTag, activityDetection, bluetoothConnection, headsetPlugged, notification, deviceOrientation, profileActive, phoneCall; //phoneCall always needs to be at the very end because of Google's shitty so called privacy
public String getFullName(Context context)
{
@ -1028,6 +1060,8 @@ public class Trigger
return context.getResources().getString(R.string.notification);
case deviceOrientation:
return context.getResources().getString(R.string.deviceOrientation);
case profileActive:
return context.getResources().getString(R.string.profile);
default:
return "Unknown";
}
@ -1373,21 +1407,7 @@ public class Trigger
if (ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), "com.google.android.gms.permission.ACTIVITY_RECOGNITION"))
{
// This type doesn't have an activate/deactivate equivalent, at least not yet.
// try
// {
returnString.append(Miscellaneous.runMethodReflective(ActivityManageRule.activityDetectionClassPath, "getDescription", new Object[]{getActivityDetectionType()}));
// for(Method method : activityDetection.getMethods())
// {
// if(method.getName().equalsIgnoreCase("getDescription"))
// returnString.append(method.invoke());
//// returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivity) + " " + activityDetection.getDescription(getActivityDetectionType()));
// }
// }
// catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException e)
// {
// e.printStackTrace();
// }
}
else
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.featureNotInFdroidVersion));
@ -1500,6 +1520,12 @@ public class Trigger
case deviceOrientation:
returnString.append(Miscellaneous.getAnyContext().getString(R.string.deviceIsInCertainOrientation));
break;
case profileActive:
if(triggerParameter)
returnString.append(String.format(Miscellaneous.getAnyContext().getString(R.string.profileActive), getTriggerParameter2().split(Trigger.triggerParameter2Split)[0]));
else
returnString.append(String.format(Miscellaneous.getAnyContext().getString(R.string.profileNotActive), getTriggerParameter2().split(Trigger.triggerParameter2Split)[0]));
break;
default:
returnString.append("error");
break;

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/default_margin"
android:orientation="vertical">
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1" >
<TableRow>
<TextView
android:text="@string/profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/spinnerProfiles"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
<TableRow>
<TextView
android:text="@string/needsToBeActive"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/chkProfileActive"
android:checked="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
<TableRow>
<TextView
android:text="@string/checkSettings"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/chkProfileCheckSettings"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
</TableLayout>
<Button
android:id="@+id/bSaveTriggerProfile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/default_margin"
android:text="@string/save" />
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -738,4 +738,8 @@
<string name="smsDialogNotice">If you have not used a send-sms action in this program before, Android may show an additional confirmation dialog, asking you to allow sending messages. You need to select the \"always allow\" checkbox and confirm if you want this action to work in the background. It\'s advised to run this rule manually once to provoke this confirmation dialog.</string>
<string name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS">Exclude from battery optimization</string>
<string name="recommendedForBetterReliability">Recommended for better reliability</string>
<string name="needsToBeActive">Needs to be active</string>
<string name="checkSettings">Check settings</string>
<string name="profileActive">profile %1$s is active</string>
<string name="profileNotActive">profile %1$s is not active</string>
</resources>

View File

@ -1 +1,2 @@
* Exclusion from battery optimization
* Profiles can be used as trigger