Initial commit

This commit is contained in:
jens 2021-02-16 20:24:12 +01:00
parent a8950597d0
commit 8690dec2e2
20 changed files with 4680 additions and 46 deletions

View File

@ -7,7 +7,7 @@ android {
defaultConfig { defaultConfig {
applicationId "com.jens.automation2" applicationId "com.jens.automation2"
minSdkVersion 14 minSdkVersion 16
compileSdkVersion 29 compileSdkVersion 29
buildToolsVersion '29.0.2' buildToolsVersion '29.0.2'
useLibrary 'org.apache.http.legacy' useLibrary 'org.apache.http.legacy'
@ -64,16 +64,16 @@ android {
} }
dependencies { dependencies {
googlePlayFlavorImplementation 'com.google.firebase:firebase-appindexing:16.0.1' googlePlayFlavorImplementation 'com.google.firebase:firebase-appindexing:19.2.0'
googlePlayFlavorImplementation 'com.google.android.gms:play-services-location:15.0.1' googlePlayFlavorImplementation 'com.google.android.gms:play-services-location:17.1.0'
apkFlavorImplementation 'com.google.firebase:firebase-appindexing:16.0.1' apkFlavorImplementation 'com.google.firebase:firebase-appindexing:19.2.0'
apkFlavorImplementation 'com.google.android.gms:play-services-location:15.0.1' apkFlavorImplementation 'com.google.android.gms:play-services-location:17.1.0'
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.1.0' implementation 'com.google.android.material:material:1.3.0'
testImplementation 'junit:junit:4.+' testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
} }

View File

@ -0,0 +1,16 @@
package com.jens.automation2;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
public class MiscellaneousWithGoogleServices
{
public static boolean isPlayServiceAvailable()
{
GoogleApiAvailability aa = new GoogleApiAvailability();
if(aa.isGooglePlayServicesAvailable(Miscellaneous.getAnyContext()) == ConnectionResult.SUCCESS)
return true;
else
return false;
}
}

View File

@ -0,0 +1,391 @@
package com.jens.automation2.receivers;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.ActivityRecognition;
import com.google.android.gms.location.ActivityRecognitionApi;
import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;
import com.jens.automation2.ActivityPermissions;
import com.jens.automation2.AutomationService;
import com.jens.automation2.Miscellaneous;
import com.jens.automation2.R;
import com.jens.automation2.Rule;
import com.jens.automation2.Settings;
import com.jens.automation2.Trigger.Trigger_Enum;
import java.util.ArrayList;
import java.util.Date;
// See also: http://developer.android.com/reference/com/google/android/gms/location/ActivityRecognitionClient.html
// https://www.sitepoint.com/google-play-services-location-activity-recognition/
public class ActivityDetectionReceiver extends IntentService implements AutomationListenerInterface, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
{
protected static ActivityRecognitionApi activityRecognitionClient = null;
protected static boolean connected = false;
protected static enum LastRequestEnum { start, stop, restart };
protected static LastRequestEnum lastRequest = null;
protected static GoogleApiClient googleApiClient = null;
protected static ActivityRecognitionResult activityDetectionLastResult = null;
protected static long lastUpdate = 0;
protected static Date currentTime;
protected static ActivityDetectionReceiver instance = null;
protected static ActivityDetectionReceiver getInstance()
{
if(instance == null)
instance = new ActivityDetectionReceiver();
return instance;
}
protected static boolean activityDetectionReceiverRunning = false;
protected static ActivityDetectionReceiver activityDetectionReceiverInstance = null;
public static boolean isActivityDetectionReceiverRunning()
{
return activityDetectionReceiverRunning;
}
public static ActivityRecognitionResult getActivityDetectionLastResult()
{
return activityDetectionLastResult;
}
public static GoogleApiClient getApiClient()
{
if(googleApiClient == null)
{
googleApiClient = new GoogleApiClient.Builder(AutomationService.getInstance())
.addConnectionCallbacks(getInstance())
.addOnConnectionFailedListener(getInstance())
.addApi(ActivityRecognition.API)
.build();
}
return googleApiClient;
}
private static void requestUpdates()
{
long frequency = Settings.activityDetectionFrequency * 1000;
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Requesting ActivityDetection updates with frequency " + String.valueOf(frequency) + " milliseconds.", 4);
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(getApiClient(), 1000, getInstance().getActivityDetectionPendingIntent());
}
private void reloadUpdates()
{
long frequency = Settings.activityDetectionFrequency * 1000;
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Re-requesting ActivityDetection updates with frequency " + String.valueOf(frequency) + " milliseconds.", 4);
activityRecognitionClient.removeActivityUpdates(getApiClient(), getInstance().getActivityDetectionPendingIntent());
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Error reloading updates for ActivityDetectionReceiver: " + Log.getStackTraceString(e), 5);
}
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(getApiClient(), frequency, getInstance().getActivityDetectionPendingIntent());
}
private static void stopUpdates()
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Unsubscribing from ActivityDetection-updates.", 4);
ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(getApiClient(), getInstance().getActivityDetectionPendingIntent());
// activityRecognitionClient.removeActivityUpdates(getApiClient(), getInstance().getActivityDetectionPendingIntent());
// activityRecognitionClient.disconnect();
}
public static void startActivityDetectionReceiver()
{
try
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Starting ActivityDetectionReceiver", 3);
if(activityDetectionReceiverInstance == null)
activityDetectionReceiverInstance = new ActivityDetectionReceiver();
if(!activityDetectionReceiverRunning && Rule.isAnyRuleUsing(Trigger_Enum.activityDetection))
{
if(isPlayServiceAvailable())
{
/*if(activityRecognitionClient == null)
activityRecognitionClient = new ActivityRecognitionClient(Miscellaneous.getAnyContext(), activityDetectionReceiverInstance, activityDetectionReceiverInstance);*/
lastRequest = LastRequestEnum.start;
if(!connected)
getApiClient().connect();
else
requestUpdates();
activityDetectionReceiverRunning = true;
}
}
}
catch(Exception ex)
{
Miscellaneous.logEvent("e", "ActivityDetectionReceiver", "Error starting ActivityDetectionReceiver: " + Log.getStackTraceString(ex), 3);
}
}
public static void restartActivityDetectionReceiver()
{
try
{
if(!activityDetectionReceiverRunning && Rule.isAnyRuleUsing(Trigger_Enum.activityDetection))
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Restarting ActivityDetectionReceiver", 3);
if(activityDetectionReceiverInstance == null)
activityDetectionReceiverInstance = new ActivityDetectionReceiver();
if(isPlayServiceAvailable())
{
// if(activityRecognitionClient == null)
// activityRecognitionClient = new ActivityRecognitionClient(Miscellaneous.getAnyContext(), activityDetectionReceiverInstance, activityDetectionReceiverInstance);
lastRequest = LastRequestEnum.restart;
if(!connected)
getApiClient().connect();
else
requestUpdates();
}
}
}
catch(Exception ex)
{
Miscellaneous.logEvent("e", "ActivityDetectionReceiver", "Error starting ActivityDetectionReceiver: " + Log.getStackTraceString(ex), 3);
}
}
public static void stopActivityDetectionReceiver()
{
try
{
if(activityDetectionReceiverRunning)
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Stopping ActivityDetectionReceiver", 3);
if(isPlayServiceAvailable())
{
lastRequest = LastRequestEnum.stop;
if(!connected)
getApiClient().connect();
else
stopUpdates();
activityDetectionReceiverRunning = false;
}
}
}
catch(Exception ex)
{
Miscellaneous.logEvent("e", "ActivityDetectionReceiver", "Error stopping ActivityDetectionReceiver: " + Log.getStackTraceString(ex), 3);
}
@Override
public void onConnectionFailed(ConnectionResult arg0)
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Connection to Play Services failed.", 4);
if(connected && getApiClient().isConnected())
{
connected = false;
}
}
@Override
public void onConnected(Bundle arg0)
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Connected to Play Services.", 4);
connected = true;
if(lastRequest == null)
{
Miscellaneous.logEvent("w", "ActivityDetectionReceiver", "Request type not specified. Start or stop listening to activity detection updates?", 4);
return;
}
if(lastRequest.equals(LastRequestEnum.start))
requestUpdates();
else if(lastRequest.equals(LastRequestEnum.stop))
stopUpdates();
else //reload, e.g. to set a new update time
reloadUpdates();
}
@Override
public void onConnectionSuspended(int arg0)
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Connection to Play Services suspended.", 4);
// activityRecognitionClient.disconnect();
connected = false;
}
public ActivityDetectionReceiver()
{
super("ActivityDetectionIntentService");
if(instance == null)
instance = this;
}
@Override
protected void onHandleIntent(Intent intent)
{
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "onHandleIntent(): Received some status.", 5);
try
{
if(isActivityDetectionReceiverRunning())
{
currentTime = new Date();
if(lastUpdate == 0 | currentTime.getTime() >= lastUpdate + Settings.activityDetectionFrequency * 1000 - 1000) // -1000 to include updates only marginaly below the threshold
{
lastUpdate = currentTime.getTime();
if(ActivityRecognitionResult.hasResult(intent))
{
activityDetectionLastResult = ActivityRecognitionResult.extractResult(intent);
for(DetectedActivity activity : activityDetectionLastResult.getProbableActivities())
{
int loglevel = 3;
if(activity.getConfidence() < Settings.activityDetectionRequiredProbability)
loglevel = 4;
Miscellaneous.logEvent("i", "ActivityDetectionReceiver", "Detected activity (probability " + String.valueOf(activity.getConfidence()) + "%): " + getDescription(activity.getType()), loglevel);
}
/*
* Returns the list of activities that where detected with the confidence value associated with each activity.
* The activities are sorted by most probable activity first.
* The sum of the confidences of all detected activities this method returns does not have to be <= 100
* since some activities are not mutually exclusive (for example, you can be walking while in a bus)
* and some activities are hierarchical (ON_FOOT is a generalization of WALKING and RUNNING).
*/
ArrayList<Rule> allRulesWithActivityDetection = Rule.findRuleCandidatesByActivityDetection();
for(int i=0; i<allRulesWithActivityDetection.size(); i++)
{
if(allRulesWithActivityDetection.get(i).applies(Miscellaneous.getAnyContext()))
allRulesWithActivityDetection.get(i).activate(AutomationService.getInstance(), false);
}
}
}
else
Miscellaneous.logEvent("w", "ActivityDetectionReceiver", String.format(getResources().getString(R.string.ignoringActivityDetectionUpdateTooSoon), String.valueOf(Settings.activityDetectionFrequency)), 5);
}
else
Miscellaneous.logEvent("w", "ActivityDetectionReceiver", "I am not running. I shouldn't be getting updates. Ignoring it.", 5);
}
catch(Exception e)
{
// some error, don't care.
Miscellaneous.logEvent("e", "ActivityDetectionReceiver", "onHandleIntent(): Error while receiving status: " + Log.getStackTraceString(e), 4);
}
}
public static int[] getAllTypes()
{
return new int[] {
DetectedActivity.IN_VEHICLE,
DetectedActivity.ON_BICYCLE,
DetectedActivity.ON_FOOT,
DetectedActivity.STILL,
DetectedActivity.TILTING,
DetectedActivity.WALKING,
DetectedActivity.RUNNING,
DetectedActivity.UNKNOWN
};
}
public static String getDescription(int type)
{
switch(type)
{
case(DetectedActivity.IN_VEHICLE):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityInVehicle);
case(DetectedActivity.ON_BICYCLE):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityOnBicycle);
case(DetectedActivity.ON_FOOT):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityOnFoot);
case(DetectedActivity.STILL):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityStill);
case(DetectedActivity.TILTING):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityTilting);
case(DetectedActivity.WALKING):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityWalking);
case(DetectedActivity.RUNNING):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityRunning);
case(DetectedActivity.UNKNOWN):
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityUnknown);
default:
return Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivityInvalidStatus);
}
}
public static String[] getAllDescriptions()
{
ArrayList<String> types = new ArrayList<String>();
for(int type : getAllTypes())
types.add(getDescription(type));
return types.toArray(new String[types.size()]);
}
@Override
public void startListener(AutomationService automationService)
{
ActivityDetectionReceiver.startActivityDetectionReceiver();
}
@Override
public void stopListener(AutomationService automationService)
{
ActivityDetectionReceiver.stopActivityDetectionReceiver();
}
public static boolean haveAllPermission()
{
return ActivityPermissions.havePermission("com.google.android.gms.permission.ACTIVITY_RECOGNITION", Miscellaneous.getAnyContext());
}
@Override
public boolean isListenerRunning()
{
return ActivityDetectionReceiver.isActivityDetectionReceiverRunning();
}
@Override
public Trigger_Enum[] getMonitoredTrigger()
{
return new Trigger_Enum[] { Trigger_Enum.activityDetection };
}
private PendingIntent getActivityDetectionPendingIntent()
{
Intent intent = new Intent(AutomationService.getInstance(), ActivityDetectionReceiver.class);
PendingIntent returnValue = PendingIntent.getService(AutomationService.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return returnValue;
}
}

View File

@ -0,0 +1,557 @@
package com.jens.automation2;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.jens.automation2.AutomationService.serviceCommands;
import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.LocationProvider;
import java.util.Calendar;
@SuppressLint("NewApi")
public class ActivityMainScreen extends ActivityGeneric
{
private static boolean guiChangeInProgress = false;
private static ActivityMainScreen activityMainScreenInstance = null;
private ToggleButton toggleService, tbLockSound;
private Button bShowHelp, bPrivacy, bSettingsErase, bSettingsSetToDefault, bVolumeTest, bAddSoundLockTIme;
private TextView tvActivePoi, tvClosestPoi, tvLastRule, tvMainScreenNote, tvlockSoundDuration;
private ListView lvRuleHistory;
private ArrayAdapter<Rule> ruleHistoryListViewAdapter;
private static boolean uiUpdateRunning = false;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_overview_layout);
activityMainScreenInstance = this;
if(ActivityPermissions.needMorePermissions(ActivityMainScreen.this))
{
Intent permissionsIntent = new Intent(ActivityMainScreen.this, ActivityPermissions.class);
startActivityForResult(permissionsIntent, 7000);
}
Settings.readFromPersistentStorage(this);
guiChangeInProgress = true;
tvActivePoi = (TextView) findViewById(R.id.tvActivePoi);
tvClosestPoi = (TextView) findViewById(R.id.tvClosestPoi);
lvRuleHistory = (ListView) findViewById(R.id.lvRuleHistory);
tvLastRule = (TextView) findViewById(R.id.tvTimeFrameHelpText);
tvMainScreenNote = (TextView) findViewById(R.id.tvMainScreenNote);
tvlockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration);
tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound);
toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener);
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
toggleService.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if (!ActivityMainScreen.this.uiUpdateRunning)
{
if (toggleService.isChecked())
{
startAutomationService(getBaseContext(), false);
} else
{
stopAutomationService();
}
}
}
});
tvMainScreenNote.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(ActivityMainScreen.this, ActivityPermissions.class);
startActivityForResult(intent, ActivityPermissions.requestCodeForPermissions);
}
});
tbLockSound.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
Settings.lockSoundChanges = isChecked;
if(!isChecked)
{
AutomationService.getInstance().nullLockSoundChangesEnd();
updateMainScreen();
}
if (!guiChangeInProgress)
Settings.writeSettings(ActivityMainScreen.this);
}
});
Button bSettings = (Button) findViewById(R.id.bSettings);
bSettings.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent myIntent = new Intent(ActivityMainScreen.this, ActivitySettings.class);
startActivityForResult(myIntent, 6000);
}
});
Button bVolumeTest = (Button) findViewById(R.id.bVolumeTest);
bVolumeTest.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(ActivityMainScreen.this, ActivityVolumeTest.class);
startActivity(intent);
}
});
bShowHelp = (Button) findViewById(R.id.bShowHelp);
bShowHelp.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent showHelpIntent = new Intent(ActivityMainScreen.this, ActivityHelp.class);
startActivity(showHelpIntent);
}
});
bPrivacy = (Button) findViewById(R.id.bPrivacy);
bPrivacy.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ActivityMainScreen.this);
builder.setMessage(getResources().getString(R.string.privacyConfirmationText));
builder.setPositiveButton(getResources().getString(R.string.yes), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
openPrivacyPolicy();
}
});
builder.setNegativeButton(getResources().getString(R.string.no), null);
builder.create().show();
}
});
/*bSettingsErase = (Button)findViewById(R.id.bSettingsErase);
bSettingsErase.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
getEraseSettingsDialog(ActivityMainScreen.this).show();
}
});*/
bSettingsSetToDefault = (Button) findViewById(R.id.bSettingsSetToDefault);
bSettingsSetToDefault.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
getDefaultSettingsDialog(ActivityMainScreen.this).show();
}
});
lvRuleHistory.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
bAddSoundLockTIme = (Button)findViewById(R.id.bAddSoundLockTIme);
bAddSoundLockTIme.setText("+" + Settings.lockSoundChangesInterval + " min");
bAddSoundLockTIme.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
if(AutomationService.isMyServiceRunning(ActivityMainScreen.this))
{
AutomationService.getInstance().lockSoundChangesEndAddTime();
ActivityMainScreen.updateMainScreen();
}
else
Toast.makeText(ActivityMainScreen.this, getResources().getString(R.string.serviceNotRunning), Toast.LENGTH_LONG).show();
}
});
ruleHistoryListViewAdapter = new ArrayAdapter<Rule>(this, R.layout.text_view_for_poi_listview_mediumtextsize, Rule.getRuleRunHistory());
if (PointOfInterest.getPointOfInterestCollection() == null | PointOfInterest.getPointOfInterestCollection().size() == 0)
PointOfInterest.loadPoisFromFile();
if (Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0)
Rule.readFromFile();
ActivityMainScreen.updateMainScreen();
this.storeServiceReferenceInVariable();
guiChangeInProgress = false;
}
private static AlertDialog getEraseSettingsDialog(final Context context)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(context.getResources().getString(R.string.areYouSure));
alertDialogBuilder.setPositiveButton(context.getResources().getString(R.string.yes), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
if (Settings.eraseSettings(context))
Toast.makeText(context, context.getResources().getString(R.string.settingsErased), Toast.LENGTH_LONG).show();
}
});
alertDialogBuilder.setNegativeButton(context.getResources().getString(R.string.no), null);
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
private static AlertDialog getDefaultSettingsDialog(final Context context)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(context.getResources().getString(R.string.areYouSure));
alertDialogBuilder.setPositiveButton(context.getResources().getString(R.string.yes), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
if (Settings.initializeSettings(context, true))
Toast.makeText(context, context.getResources().getString(R.string.settingsSetToDefault), Toast.LENGTH_LONG).show();
}
});
alertDialogBuilder.setNegativeButton(context.getResources().getString(R.string.no), null);
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
public static ActivityMainScreen getActivityMainScreenInstance()
{
return activityMainScreenInstance;
}
public static void updateMainScreen()
{
Miscellaneous.logEvent("i", "MainScreen", "Request to update notification.", 5);
if (activityMainScreenInstance != null)
{
if(ActivityPermissions.needMorePermissions(activityMainScreenInstance))
{
activityMainScreenInstance.tvMainScreenNote.setText(R.string.mainScreenPermissionNote);
activityMainScreenInstance.tvMainScreenNote.setVisibility(View.VISIBLE);
}
else
{
activityMainScreenInstance.tvMainScreenNote.setText("");
activityMainScreenInstance.tvMainScreenNote.setVisibility(View.GONE);
}
if (AutomationService.isMyServiceRunning(activityMainScreenInstance))
{
Miscellaneous.logEvent("i", "MainScreen", "Service is running. Updating mainscreen with this info.", 5);
uiUpdateRunning = true;
activityMainScreenInstance.toggleService.setChecked(true);
uiUpdateRunning = false;
// if(activityMainScreenInstance.hasWindowFocus())
// {
try
{
PointOfInterest activePoi = PointOfInterest.getActivePoi();
if (activePoi == null)
{
PointOfInterest closestPoi = PointOfInterest.getClosestPOI(LocationProvider.getInstance().getCurrentLocation());
activityMainScreenInstance.tvActivePoi.setText("none");
activityMainScreenInstance.tvClosestPoi.setText(closestPoi.getName());
}
else
{
activityMainScreenInstance.tvActivePoi.setText(activePoi.getName());
activityMainScreenInstance.tvClosestPoi.setText("n./a.");
}
}
catch (NullPointerException e)
{
if (PointOfInterest.getPointOfInterestCollection().size() > 0)
{
if(
Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest)
&&
ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationCoarse, AutomationService.getInstance())
&&
ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationFine, AutomationService.getInstance())
)
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.stillGettingPosition));
else
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.locationEngineNotActive));
activityMainScreenInstance.tvClosestPoi.setText("n./a.");
}
else
{
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.noPoisDefinedShort));
activityMainScreenInstance.tvClosestPoi.setText("n./a.");
}
}
try
{
activityMainScreenInstance.tvLastRule.setText(Rule.getLastActivatedRule().getName() + " " + activityMainScreenInstance.getResources().getString(R.string.at) + " " + Rule.getLastActivatedRuleActivationTime().toLocaleString());
activityMainScreenInstance.updateListView();
}
catch (Exception e)
{
activityMainScreenInstance.tvLastRule.setText("n./a.");
}
}
else
{
Miscellaneous.logEvent("i", "MainScreen", "Service not running. Updating mainscreen with this info.", 5);
activityMainScreenInstance.toggleService.setChecked(false);
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.serviceNotRunning));
activityMainScreenInstance.tvClosestPoi.setText("");
activityMainScreenInstance.tvLastRule.setText("");
}
// uiUpdateRunning = true;
if(AutomationService.isMyServiceRunning(ActivityMainScreen.getActivityMainScreenInstance()) && AutomationService.getInstance() != null)
{
AutomationService.getInstance().checkLockSoundChangesTimeElapsed();
Calendar end = AutomationService.getInstance().getLockSoundChangesEnd();
activityMainScreenInstance.tbLockSound.setChecked(end != null);
activityMainScreenInstance.tbLockSound.setEnabled(end != null);
if(end != null)
{
Calendar now = Calendar.getInstance();
long millis = end.getTimeInMillis() - now.getTimeInMillis();
long minutes = millis/1000/60;
if(minutes < 60)
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(minutes + " min..."));
else
{
double hours = (double)minutes / 60.0;
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(Math.round(hours * 100.0) / 100.0) + " h...");
}
}
else
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(""));
}
else
{
activityMainScreenInstance.tbLockSound.setChecked(false);
activityMainScreenInstance.tbLockSound.setEnabled(false);
activityMainScreenInstance.tvlockSoundDuration.setText("");
}
Settings.writeSettings(activityMainScreenInstance);
// uiUpdateRunning = false;
// }
// else
// Miscellaneous.logEvent("i", "ActivityMainScreen", "Window doesn't have focus. We're not updating anything.", 5);
}
else
Miscellaneous.logEvent("i", "ActivityMainScreen", "Activity not running. No need to update.", 5);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// Miscellaneous.logEvent("i", "ListView", "Notifying ListViewAdapter", 4);
if (AutomationService.isMyServiceRunning(this))
bindToService();
switch (requestCode)
{
case ActivityPermissions.requestCodeForPermissions:
updateMainScreen();
break;
case 6000: //settings
Settings.readFromPersistentStorage(this);
if (boundToService && AutomationService.isMyServiceRunning(this))
myAutomationService.serviceInterface(serviceCommands.reloadSettings);
if(AutomationService.isMyServiceRunning(ActivityMainScreen.this))
Toast.makeText(this, getResources().getString(R.string.settingsWillTakeTime), Toast.LENGTH_LONG).show();
break;
}
if (AutomationService.isMyServiceRunning(this))
{
// Let service reload via binding interface.
if (boundToService)
{
myAutomationService.serviceInterface(serviceCommands.updateNotification); //in case names got changed.
unBindFromService();
}
}
else
{
// Let service reload classically.
AutomationService service = AutomationService.getInstance();
if (service != null)
service.applySettingsAndRules();
}
}
public static void startAutomationService(Context context, boolean startAtBoot)
{
try
{
if (Rule.getRuleCollection().size() > 0)
{
if (!AutomationService.isMyServiceRunning(context))
{
// if(myServiceIntent == null) //do we need that line?????
myServiceIntent = new Intent(context, AutomationService.class);
myServiceIntent.putExtra("startAtBoot", startAtBoot);
context.startService(myServiceIntent);
} else
Miscellaneous.logEvent("w", "Service", context.getResources().getString(R.string.logServiceAlreadyRunning), 3);
} else
{
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
}
}
catch (NullPointerException ne)
{
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
}
catch (Exception e)
{
Toast.makeText(context, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
}
}
private void stopAutomationService()
{
if (myServiceIntent == null)
myServiceIntent = new Intent(this, AutomationService.class);
stopService(myServiceIntent);
}
@Override
protected void onRestart()
{
super.onRestart();
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
ActivityMainScreen.updateMainScreen();
}
@Override
protected void onStart()
{
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
ActivityMainScreen.updateMainScreen();
super.onStart();
}
@Override
protected void onResume()
{
super.onResume();
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
ActivityMainScreen.updateMainScreen();
if(Build.VERSION.SDK_INT >= 28 && !Settings.noticeAndroid9MicrophoneShown && Rule.isAnyRuleUsing(Trigger_Enum.noiseLevel))
{
Settings.noticeAndroid9MicrophoneShown = true;
Settings.writeSettings(ActivityMainScreen.this);
Miscellaneous.messageBox(getResources().getString(R.string.app_name), getResources().getString(R.string.android9RecordAudioNotice) + " " + getResources().getString(R.string.messageNotShownAgain), ActivityMainScreen.this).show();
}
if(Build.VERSION.SDK_INT >= 29 && !Settings.noticeAndroid10WifiShown && Rule.isAnyRuleUsing(Action.Action_Enum.setWifi))
{
Settings.noticeAndroid10WifiShown = true;
Settings.writeSettings(ActivityMainScreen.this);
Miscellaneous.messageBox(getResources().getString(R.string.app_name), getResources().getString(R.string.android10WifiToggleNotice) + " " + getResources().getString(R.string.messageNotShownAgain), ActivityMainScreen.this).show();
}
}
@Override
protected void onDestroy()
{
super.onDestroy();
activityMainScreenInstance = null;
}
private void openPrivacyPolicy()
{
String privacyPolicyUrl = "http://server47.de/automation/privacy.html";
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(privacyPolicyUrl));
startActivity(browserIntent);
}
private void updateListView()
{
Miscellaneous.logEvent("i", "ListView", "Attempting to update lvRuleHistory", 4);
try
{
if (lvRuleHistory.getAdapter() == null)
lvRuleHistory.setAdapter(ruleHistoryListViewAdapter);
ruleHistoryListViewAdapter.notifyDataSetChanged();
}
catch (NullPointerException e)
{
}
}
public static void showMessageBox(String title, String text)
{
Miscellaneous.messageBox(title, text, ActivityMainScreen.getActivityMainScreenInstance());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,597 @@
package com.jens.automation2;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;
import com.jens.automation2.AutomationService.serviceCommands;
import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.location.LocationProvider;
import java.util.Calendar;
@SuppressLint("NewApi")
public class ActivityMainScreen extends ActivityGeneric
{
private static boolean guiChangeInProgress = false;
private static ActivityMainScreen activityMainScreenInstance = null;
private ToggleButton toggleService, tbLockSound;
private Button bShowHelp, bPrivacy, bSettingsErase, bSettingsSetToDefault, bVolumeTest, bAddSoundLockTIme;
private TextView tvActivePoi, tvClosestPoi, tvLastRule, tvMainScreenNote, tvlockSoundDuration;
private ListView lvRuleHistory;
private ArrayAdapter<Rule> ruleHistoryListViewAdapter;
private static boolean uiUpdateRunning = false;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_overview_layout);
activityMainScreenInstance = this;
if(ActivityPermissions.needMorePermissions(ActivityMainScreen.this))
{
Intent permissionsIntent = new Intent(ActivityMainScreen.this, ActivityPermissions.class);
startActivityForResult(permissionsIntent, 7000);
}
Settings.readFromPersistentStorage(this);
guiChangeInProgress = true;
tvActivePoi = (TextView) findViewById(R.id.tvActivePoi);
tvClosestPoi = (TextView) findViewById(R.id.tvClosestPoi);
lvRuleHistory = (ListView) findViewById(R.id.lvRuleHistory);
tvLastRule = (TextView) findViewById(R.id.tvTimeFrameHelpText);
tvMainScreenNote = (TextView) findViewById(R.id.tvMainScreenNote);
tvlockSoundDuration = (TextView)findViewById(R.id.tvlockSoundDuration);
tbLockSound = (ToggleButton) findViewById(R.id.tbLockSound);
toggleService = (ToggleButton) findViewById(R.id.tbArmMastListener);
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
toggleService.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if (!ActivityMainScreen.this.uiUpdateRunning)
{
if (toggleService.isChecked())
{
startAutomationService(getBaseContext(), false);
} else
{
stopAutomationService();
}
}
}
});
tvMainScreenNote.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(ActivityMainScreen.this, ActivityPermissions.class);
startActivityForResult(intent, ActivityPermissions.requestCodeForPermissions);
}
});
tbLockSound.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
Settings.lockSoundChanges = isChecked;
if(!isChecked)
{
AutomationService.getInstance().nullLockSoundChangesEnd();
updateMainScreen();
}
if (!guiChangeInProgress)
Settings.writeSettings(ActivityMainScreen.this);
}
});
Button bSettings = (Button) findViewById(R.id.bSettings);
bSettings.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent myIntent = new Intent(ActivityMainScreen.this, ActivitySettings.class);
startActivityForResult(myIntent, 6000);
}
});
Button bVolumeTest = (Button) findViewById(R.id.bVolumeTest);
bVolumeTest.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(ActivityMainScreen.this, ActivityVolumeTest.class);
startActivity(intent);
}
});
bShowHelp = (Button) findViewById(R.id.bShowHelp);
bShowHelp.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent showHelpIntent = new Intent(ActivityMainScreen.this, ActivityHelp.class);
startActivity(showHelpIntent);
}
});
bPrivacy = (Button) findViewById(R.id.bPrivacy);
bPrivacy.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ActivityMainScreen.this);
builder.setMessage(getResources().getString(R.string.privacyConfirmationText));
builder.setPositiveButton(getResources().getString(R.string.yes), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
openPrivacyPolicy();
}
});
builder.setNegativeButton(getResources().getString(R.string.no), null);
builder.create().show();
}
});
/*bSettingsErase = (Button)findViewById(R.id.bSettingsErase);
bSettingsErase.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
getEraseSettingsDialog(ActivityMainScreen.this).show();
}
});*/
bSettingsSetToDefault = (Button) findViewById(R.id.bSettingsSetToDefault);
bSettingsSetToDefault.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
getDefaultSettingsDialog(ActivityMainScreen.this).show();
}
});
lvRuleHistory.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
bAddSoundLockTIme = (Button)findViewById(R.id.bAddSoundLockTIme);
bAddSoundLockTIme.setText("+" + Settings.lockSoundChangesInterval + " min");
bAddSoundLockTIme.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
if(AutomationService.isMyServiceRunning(ActivityMainScreen.this))
{
AutomationService.getInstance().lockSoundChangesEndAddTime();
ActivityMainScreen.updateMainScreen();
}
else
Toast.makeText(ActivityMainScreen.this, getResources().getString(R.string.serviceNotRunning), Toast.LENGTH_LONG).show();
}
});
ruleHistoryListViewAdapter = new ArrayAdapter<Rule>(this, R.layout.text_view_for_poi_listview_mediumtextsize, Rule.getRuleRunHistory());
if (PointOfInterest.getPointOfInterestCollection() == null | PointOfInterest.getPointOfInterestCollection().size() == 0)
PointOfInterest.loadPoisFromFile();
if (Rule.getRuleCollection() == null | Rule.getRuleCollection().size() == 0)
Rule.readFromFile();
ActivityMainScreen.updateMainScreen();
this.storeServiceReferenceInVariable();
guiChangeInProgress = false;
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
private static AlertDialog getEraseSettingsDialog(final Context context)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(context.getResources().getString(R.string.areYouSure));
alertDialogBuilder.setPositiveButton(context.getResources().getString(R.string.yes), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
if (Settings.eraseSettings(context))
Toast.makeText(context, context.getResources().getString(R.string.settingsErased), Toast.LENGTH_LONG).show();
}
});
alertDialogBuilder.setNegativeButton(context.getResources().getString(R.string.no), null);
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
private static AlertDialog getDefaultSettingsDialog(final Context context)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(context.getResources().getString(R.string.areYouSure));
alertDialogBuilder.setPositiveButton(context.getResources().getString(R.string.yes), new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
if (Settings.initializeSettings(context, true))
Toast.makeText(context, context.getResources().getString(R.string.settingsSetToDefault), Toast.LENGTH_LONG).show();
}
});
alertDialogBuilder.setNegativeButton(context.getResources().getString(R.string.no), null);
AlertDialog alertDialog = alertDialogBuilder.create();
return alertDialog;
}
public static ActivityMainScreen getActivityMainScreenInstance()
{
return activityMainScreenInstance;
}
public static void updateMainScreen()
{
Miscellaneous.logEvent("i", "MainScreen", "Request to update notification.", 5);
if (activityMainScreenInstance != null)
{
if(ActivityPermissions.needMorePermissions(activityMainScreenInstance))
{
activityMainScreenInstance.tvMainScreenNote.setText(R.string.mainScreenPermissionNote);
activityMainScreenInstance.tvMainScreenNote.setVisibility(View.VISIBLE);
}
else
{
activityMainScreenInstance.tvMainScreenNote.setText("");
activityMainScreenInstance.tvMainScreenNote.setVisibility(View.GONE);
}
if (AutomationService.isMyServiceRunning(activityMainScreenInstance))
{
Miscellaneous.logEvent("i", "MainScreen", "Service is running. Updating mainscreen with this info.", 5);
uiUpdateRunning = true;
activityMainScreenInstance.toggleService.setChecked(true);
uiUpdateRunning = false;
// if(activityMainScreenInstance.hasWindowFocus())
// {
try
{
PointOfInterest activePoi = PointOfInterest.getActivePoi();
if (activePoi == null)
{
PointOfInterest closestPoi = PointOfInterest.getClosestPOI(LocationProvider.getInstance().getCurrentLocation());
activityMainScreenInstance.tvActivePoi.setText("none");
activityMainScreenInstance.tvClosestPoi.setText(closestPoi.getName());
}
else
{
activityMainScreenInstance.tvActivePoi.setText(activePoi.getName());
activityMainScreenInstance.tvClosestPoi.setText("n./a.");
}
}
catch (NullPointerException e)
{
if (PointOfInterest.getPointOfInterestCollection().size() > 0)
{
if(
Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest)
&&
ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationCoarse, AutomationService.getInstance())
&&
ActivityPermissions.havePermission(ActivityPermissions.permissionNameLocationFine, AutomationService.getInstance())
)
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.stillGettingPosition));
else
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.locationEngineNotActive));
activityMainScreenInstance.tvClosestPoi.setText("n./a.");
}
else
{
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.noPoisDefinedShort));
activityMainScreenInstance.tvClosestPoi.setText("n./a.");
}
}
try
{
activityMainScreenInstance.tvLastRule.setText(Rule.getLastActivatedRule().getName() + " " + activityMainScreenInstance.getResources().getString(R.string.at) + " " + Rule.getLastActivatedRuleActivationTime().toLocaleString());
activityMainScreenInstance.updateListView();
}
catch (Exception e)
{
activityMainScreenInstance.tvLastRule.setText("n./a.");
}
}
else
{
Miscellaneous.logEvent("i", "MainScreen", "Service not running. Updating mainscreen with this info.", 5);
activityMainScreenInstance.toggleService.setChecked(false);
activityMainScreenInstance.tvActivePoi.setText(activityMainScreenInstance.getResources().getString(R.string.serviceNotRunning));
activityMainScreenInstance.tvClosestPoi.setText("");
activityMainScreenInstance.tvLastRule.setText("");
}
// uiUpdateRunning = true;
if(AutomationService.isMyServiceRunning(ActivityMainScreen.getActivityMainScreenInstance()) && AutomationService.getInstance() != null)
{
AutomationService.getInstance().checkLockSoundChangesTimeElapsed();
Calendar end = AutomationService.getInstance().getLockSoundChangesEnd();
activityMainScreenInstance.tbLockSound.setChecked(end != null);
activityMainScreenInstance.tbLockSound.setEnabled(end != null);
if(end != null)
{
Calendar now = Calendar.getInstance();
long millis = end.getTimeInMillis() - now.getTimeInMillis();
long minutes = millis/1000/60;
if(minutes < 60)
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(minutes + " min..."));
else
{
double hours = (double)minutes / 60.0;
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(Math.round(hours * 100.0) / 100.0) + " h...");
}
}
else
activityMainScreenInstance.tvlockSoundDuration.setText(String.valueOf(""));
}
else
{
activityMainScreenInstance.tbLockSound.setChecked(false);
activityMainScreenInstance.tbLockSound.setEnabled(false);
activityMainScreenInstance.tvlockSoundDuration.setText("");
}
Settings.writeSettings(activityMainScreenInstance);
// uiUpdateRunning = false;
// }
// else
// Miscellaneous.logEvent("i", "ActivityMainScreen", "Window doesn't have focus. We're not updating anything.", 5);
}
else
Miscellaneous.logEvent("i", "ActivityMainScreen", "Activity not running. No need to update.", 5);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// Miscellaneous.logEvent("i", "ListView", "Notifying ListViewAdapter", 4);
if (AutomationService.isMyServiceRunning(this))
bindToService();
switch (requestCode)
{
case ActivityPermissions.requestCodeForPermissions:
updateMainScreen();
break;
case 6000: //settings
Settings.readFromPersistentStorage(this);
if (boundToService && AutomationService.isMyServiceRunning(this))
myAutomationService.serviceInterface(serviceCommands.reloadSettings);
if(AutomationService.isMyServiceRunning(ActivityMainScreen.this))
Toast.makeText(this, getResources().getString(R.string.settingsWillTakeTime), Toast.LENGTH_LONG).show();
break;
}
if (AutomationService.isMyServiceRunning(this))
{
// Let service reload via binding interface.
if (boundToService)
{
myAutomationService.serviceInterface(serviceCommands.updateNotification); //in case names got changed.
unBindFromService();
}
}
else
{
// Let service reload classically.
AutomationService service = AutomationService.getInstance();
if (service != null)
service.applySettingsAndRules();
}
}
public static void startAutomationService(Context context, boolean startAtBoot)
{
try
{
if (Rule.getRuleCollection().size() > 0)
{
if (!AutomationService.isMyServiceRunning(context))
{
// if(myServiceIntent == null) //do we need that line?????
myServiceIntent = new Intent(context, AutomationService.class);
myServiceIntent.putExtra("startAtBoot", startAtBoot);
context.startService(myServiceIntent);
} else
Miscellaneous.logEvent("w", "Service", context.getResources().getString(R.string.logServiceAlreadyRunning), 3);
} else
{
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
}
}
catch (NullPointerException ne)
{
Toast.makeText(context, context.getResources().getString(R.string.serviceWontStart), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
}
catch (Exception e)
{
Toast.makeText(context, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
activityMainScreenInstance.toggleService.setChecked(false);
}
}
private void stopAutomationService()
{
if (myServiceIntent == null)
myServiceIntent = new Intent(this, AutomationService.class);
stopService(myServiceIntent);
}
@Override
protected void onRestart()
{
super.onRestart();
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
ActivityMainScreen.updateMainScreen();
}
@Override
protected void onStart()
{
super.onStart();
client.connect();
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
ActivityMainScreen.updateMainScreen();
AppIndex.AppIndexApi.start(client, getIndexApiAction());
}
@Override
protected void onResume()
{
super.onResume();
toggleService.setChecked(AutomationService.isMyServiceRunning(this));
ActivityMainScreen.updateMainScreen();
if(Build.VERSION.SDK_INT >= 28 && !Settings.noticeAndroid9MicrophoneShown && Rule.isAnyRuleUsing(Trigger_Enum.noiseLevel))
{
Settings.noticeAndroid9MicrophoneShown = true;
Settings.writeSettings(ActivityMainScreen.this);
Miscellaneous.messageBox(getResources().getString(R.string.app_name), getResources().getString(R.string.android9RecordAudioNotice) + " " + getResources().getString(R.string.messageNotShownAgain), ActivityMainScreen.this).show();
}
if(Build.VERSION.SDK_INT >= 29 && !Settings.noticeAndroid10WifiShown && Rule.isAnyRuleUsing(Action.Action_Enum.setWifi))
{
Settings.noticeAndroid10WifiShown = true;
Settings.writeSettings(ActivityMainScreen.this);
Miscellaneous.messageBox(getResources().getString(R.string.app_name), getResources().getString(R.string.android10WifiToggleNotice) + " " + getResources().getString(R.string.messageNotShownAgain), ActivityMainScreen.this).show();
}
}
@Override
protected void onDestroy()
{
super.onDestroy();
activityMainScreenInstance = null;
}
private void openPrivacyPolicy()
{
String privacyPolicyUrl = "http://server47.de/automation/privacy.html";
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(privacyPolicyUrl));
startActivity(browserIntent);
}
private void updateListView()
{
Miscellaneous.logEvent("i", "ListView", "Attempting to update lvRuleHistory", 4);
try
{
if (lvRuleHistory.getAdapter() == null)
lvRuleHistory.setAdapter(ruleHistoryListViewAdapter);
ruleHistoryListViewAdapter.notifyDataSetChanged();
} catch (NullPointerException e)
{
}
}
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
public com.google.android.gms.appindexing.Action getIndexApiAction()
{
Thing object = new Thing.Builder()
.setName("ActivityMainScreen Page") // TODO: Define a title for the content shown.
// TODO: Make sure this auto-generated URL is correct.
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
.build();
return new com.google.android.gms.appindexing.Action.Builder(com.google.android.gms.appindexing.Action.TYPE_VIEW)
.setObject(object)
.setActionStatus(com.google.android.gms.appindexing.Action.STATUS_TYPE_COMPLETED)
.build();
}
@Override
public void onStop()
{
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
AppIndex.AppIndexApi.end(client, getIndexApiAction());
client.disconnect();
}
public static void showMessageBox(String title, String text)
{
Miscellaneous.messageBox(title, text, ActivityMainScreen.getActivityMainScreenInstance());
}
}

View File

@ -0,0 +1,16 @@
package com.jens.automation2;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
public class MiscellaneousWithGoogleServices
{
public static boolean isPlayServiceAvailable()
{
GoogleApiAvailability aa = new GoogleApiAvailability();
if(aa.isGooglePlayServicesAvailable(Miscellaneous.getAnyContext()) == ConnectionResult.SUCCESS)
return true;
else
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
package com.jens.automation2.location;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingEvent;
import com.jens.automation2.Miscellaneous;
import java.util.List;
import static eu.chainfire.libsuperuser.Debug.TAG;
public class GeofenceBroadcastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError())
{
// Miscellaneous.logEvent("i", "Geofence", geofenceTransitionDetails, 2);
// String errorMessage = GeofenceStatusCodes.getErrorString(geofencingEvent.getErrorCode());
Log.e(TAG, "Geofence error");
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT)
{
// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = "something happened";//getGeofenceTransitionDetails(this, geofenceTransition, triggeringGeofences);
// Send notification and log the transition details.
Miscellaneous.logEvent("i", "Geofence", geofenceTransitionDetails, 2);
Log.i(TAG, geofenceTransitionDetails);
}
else
{
// Log the error.
// Log.e(TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition));
Log.e("Geofence", String.valueOf(geofenceTransition));
}
}
}

View File

@ -0,0 +1,109 @@
package com.jens.automation2.location;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import androidx.annotation.Nullable;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.GeofencingClient;
import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.LocationServices;
import com.jens.automation2.PointOfInterest;
import java.util.ArrayList;
import java.util.List;
public class GeofenceIntentService extends IntentService
{
private GeofencingClient mGeofencingClient;
protected static GoogleApiClient googleApiClient = null;
PendingIntent geofencePendingIntent;
static GeofenceIntentService instance;
List<com.google.android.gms.location.Geofence> geoFenceList = new ArrayList<>();
public static GeofenceIntentService getInstance()
{
if (instance == null)
instance = new GeofenceIntentService("Automation");
return instance;
}
public GeofenceIntentService(String name)
{
super(name);
}
@Override
protected void onHandleIntent(@Nullable Intent intent)
{
}
@Override
public void onCreate()
{
mGeofencingClient = LocationServices.getGeofencingClient(this);
}
public void addFence(PointOfInterest poi)
{
com.google.android.gms.location.Geofence geofence = new com.google.android.gms.location.Geofence.Builder()
.setRequestId(poi.getName()) // Geofence ID
.setCircularRegion(poi.getLocation().getLatitude(), poi.getLocation().getLongitude(), (float) poi.getRadius()) // defining fence region
.setExpirationDuration(com.google.android.gms.location.Geofence.NEVER_EXPIRE) // expiring date
// Transition types that it should look for
.setTransitionTypes(com.google.android.gms.location.Geofence.GEOFENCE_TRANSITION_ENTER | com.google.android.gms.location.Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
geoFenceList.add(geofence);
GeofencingRequest request = new GeofencingRequest.Builder()
// Notification to trigger when the Geofence is created
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofence(geofence) // add a Geofence
.build();
mGeofencingClient.removeGeofences(getGeofencePendingIntent());
}
public static void startService()
{
for (PointOfInterest poi : PointOfInterest.getPointOfInterestCollection())
getInstance().addFence(poi);
}
public static void stopService()
{
for (PointOfInterest poi : PointOfInterest.getPointOfInterestCollection())
getInstance().addFence(poi);
}
/**
* Gets a PendingIntent to send with the request to add or remove Geofences. Location Services
* issues the Intent inside this PendingIntent whenever a geofence transition occurs for the
* current list of geofences.
*
* @return A PendingIntent for the IntentService that handles geofence transitions.
*/
private PendingIntent getGeofencePendingIntent()
{
// Reuse the PendingIntent if we already have it.
if (geofencePendingIntent != null)
{
return geofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return geofencePendingIntent;
}
}

View File

@ -9,7 +9,6 @@ import android.util.Log;
import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.ActivityRecognition; import com.google.android.gms.location.ActivityRecognition;
import com.google.android.gms.location.ActivityRecognitionApi; import com.google.android.gms.location.ActivityRecognitionApi;
import com.google.android.gms.location.ActivityRecognitionResult; import com.google.android.gms.location.ActivityRecognitionResult;

View File

@ -34,11 +34,14 @@ import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.RequiresApi;
import com.jens.automation2.Action.Action_Enum; import com.jens.automation2.Action.Action_Enum;
import com.jens.automation2.Trigger.Trigger_Enum; import com.jens.automation2.Trigger.Trigger_Enum;
import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.NfcReceiver; import com.jens.automation2.receivers.NfcReceiver;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -489,7 +492,8 @@ public class ActivityManageSpecificRule extends Activity
.setTitle(getResources().getString(R.string.selectTypeOfTrigger)) .setTitle(getResources().getString(R.string.selectTypeOfTrigger))
.setAdapter(adapter, new DialogInterface.OnClickListener() .setAdapter(adapter, new DialogInterface.OnClickListener()
{ {
public void onClick(DialogInterface dialog, int which) @RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void onClick(DialogInterface dialog, int which)
{ {
triggerType = Trigger_Enum.values()[which]; triggerType = Trigger_Enum.values()[which];
@ -530,13 +534,25 @@ public class ActivityManageSpecificRule extends Activity
booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)}; booleanChoices = new String[]{getResources().getString(R.string.started), getResources().getString(R.string.stopped)};
else if(triggerType == Trigger_Enum.activityDetection) else if(triggerType == Trigger_Enum.activityDetection)
{ {
if(ActivityDetectionReceiver.isPlayServiceAvailable()) try
{ {
newTrigger.setTriggerType(Trigger_Enum.activityDetection); Method m = Miscellaneous.getClassMethodReflective("ActivityDetectionReceiver", "isPlayServiceAvailable");
getTriggerActivityDetectionDialog().show(); if(m != null)
{
boolean available = (Boolean)m.invoke(null);
if(available)
{
newTrigger.setTriggerType(Trigger_Enum.activityDetection);
getTriggerActivityDetectionDialog().show();
}
else
Toast.makeText(myContext, getResources().getString(R.string.triggerOnlyAvailableIfPlayServicesInstalled), Toast.LENGTH_LONG).show();
}
}
catch (IllegalAccessException | InvocationTargetException e)
{
e.printStackTrace();
} }
else
Toast.makeText(myContext, getResources().getString(R.string.triggerOnlyAvailableIfPlayServicesInstalled), Toast.LENGTH_LONG).show();
return; return;
} }
else if(triggerType == Trigger_Enum.nfcTag) else if(triggerType == Trigger_Enum.nfcTag)
@ -898,25 +914,52 @@ public class ActivityManageSpecificRule extends Activity
return alertDialog; return alertDialog;
} }
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private AlertDialog getTriggerActivityDetectionDialog() private AlertDialog getTriggerActivityDetectionDialog()
{ {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this); AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle(Miscellaneous.getAnyContext().getResources().getString(R.string.selectTypeOfActivity)); alertDialog.setTitle(Miscellaneous.getAnyContext().getResources().getString(R.string.selectTypeOfActivity));
String[] choices = ActivityDetectionReceiver.getAllDescriptions();
alertDialog.setItems(choices, new DialogInterface.OnClickListener() Method m = Miscellaneous.getClassMethodReflective("ActivityDetectionReceiver", "getAllDescriptions");
{ if(m != null)
@Override {
public void onClick(DialogInterface dialog, int which) String[] choices = new String[0];
try
{ {
newTrigger.setActivityDetectionType(ActivityDetectionReceiver.getAllTypes()[which]); choices = (String[])m.invoke(null);
ruleToEdit.getTriggerSet().add(newTrigger); alertDialog.setItems(choices, new DialogInterface.OnClickListener()
refreshTriggerList(); {
@Override
public void onClick(DialogInterface dialog, int which)
{
Method m = Miscellaneous.getClassMethodReflective("ActivityDetectionReceiver", "getAllTypes");
if(m != null)
{
try
{
Integer[] choices = (Integer[])m.invoke(null);
newTrigger.setActivityDetectionType(choices[which]);
ruleToEdit.getTriggerSet().add(newTrigger);
refreshTriggerList();
}
catch (IllegalAccessException | InvocationTargetException e)
{
e.printStackTrace();
}
}
}
});
} }
}); catch (IllegalAccessException | InvocationTargetException e)
{
e.printStackTrace();
}
}
return alertDialog.create(); return alertDialog.create();
} }
private static class GenerateApplicationSelectionsDialogTask extends AsyncTask<ActivityManageSpecificRule, Void, String[]> private static class GenerateApplicationSelectionsDialogTask extends AsyncTask<ActivityManageSpecificRule, Void, String[]>
{ {

View File

@ -48,6 +48,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.Thread.UncaughtExceptionHandler; import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Method;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
@ -72,12 +73,9 @@ import javax.net.ssl.X509TrustManager;
import static com.jens.automation2.AutomationService.NOTIFICATION_CHANNEL_ID; import static com.jens.automation2.AutomationService.NOTIFICATION_CHANNEL_ID;
import static com.jens.automation2.AutomationService.channelName; import static com.jens.automation2.AutomationService.channelName;
//import android.R.string;
//import android.util.Log;
public class Miscellaneous extends Service public class Miscellaneous extends Service
{ {
private static String writeableFolderStringCache = null; protected static String writeableFolderStringCache = null;
public static final String lineSeparator = System.getProperty("line.separator"); public static final String lineSeparator = System.getProperty("line.separator");
public static String downloadURL(String url, String username, String password) public static String downloadURL(String url, String username, String password)
@ -884,4 +882,26 @@ public class Miscellaneous extends Service
} }
} }
} }
public static Method getClassMethodReflective(String className, String methodName)
{
Class atRecClass = null;
try
{
atRecClass = Class.forName("ActivityDetectionReceiver");
for(Method m : atRecClass.getMethods())
{
if(m.getName().equalsIgnoreCase("isPlayServiceAvailable"))
{
return m;
}
}
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
return null;
}
} }

View File

@ -4,7 +4,6 @@ import android.util.Log;
import com.jens.automation2.location.CellLocationChangedReceiver; import com.jens.automation2.location.CellLocationChangedReceiver;
import com.jens.automation2.location.WifiBroadcastReceiver; import com.jens.automation2.location.WifiBroadcastReceiver;
import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.AlarmListener; import com.jens.automation2.receivers.AlarmListener;
import com.jens.automation2.receivers.AutomationListenerInterface; import com.jens.automation2.receivers.AutomationListenerInterface;
import com.jens.automation2.receivers.BatteryReceiver; import com.jens.automation2.receivers.BatteryReceiver;

View File

@ -2,10 +2,14 @@ package com.jens.automation2;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.content.Context; import android.content.Context;
import android.os.Build;
import androidx.annotation.RequiresApi;
import com.jens.automation2.receivers.ActivityDetectionReceiver;
import com.jens.automation2.receivers.BluetoothReceiver; import com.jens.automation2.receivers.BluetoothReceiver;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
@ -215,22 +219,13 @@ public class Trigger
} }
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Override @Override
public String toString() public String toString()
{ {
StringBuilder returnString = new StringBuilder(); StringBuilder returnString = new StringBuilder();
/*
* public enum TriggerType_Enum { pointOfInterest, timeFrame, event };
public enum Event_Enum { charging_started, charging_stopped, usb_connected, usb_disconnected };
private TriggerType_Enum triggerType;
private PointOfInterest pointOfInterest;
private Event_Enum event;
private TimeFrame timeFrame;
*/
switch(this.getTriggerType()) switch(this.getTriggerType())
{ {
case charging: case charging:
@ -358,8 +353,27 @@ public class Trigger
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.closeTo) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.nfcTag) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.withLabel) + " " + this.getNfcTagId()); returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.closeTo) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.nfcTag) + " " + Miscellaneous.getAnyContext().getResources().getString(R.string.withLabel) + " " + this.getNfcTagId());
break; break;
case activityDetection: case activityDetection:
// This type doesn't have an activate/deactivate equivalent, at least not yet. if(ActivityPermissions.isPermissionDeclaratedInManifest(Miscellaneous.getAnyContext(), "com.google.android.gms.permission.ACTIVITY_RECOGNITION"))
returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivity) + " " + ActivityDetectionReceiver.getDescription(getActivityDetectionType())); {
// This type doesn't have an activate/deactivate equivalent, at least not yet.
try
{
Class activityDetection = Class.forName("com.jens.automation2.receivers.ActivityDetectionReceiver");
for(Method method : activityDetection.getMethods())
{
if(method.getName().equalsIgnoreCase("getDescription"))
returnString.append(method.invoke(getActivityDetectionType()));
// returnString.append(Miscellaneous.getAnyContext().getResources().getString(R.string.detectedActivity) + " " + activityDetection.getDescription(getActivityDetectionType()));
}
}
catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException e)
{
e.printStackTrace();
}
}
else
returnString.append("Invalid trigger. This application version cannot handle ActivityDetection.");
break; break;
case bluetoothConnection: case bluetoothConnection:
String device = Miscellaneous.getAnyContext().getResources().getString(R.string.anyDevice); String device = Miscellaneous.getAnyContext().getResources().getString(R.string.anyDevice);

View File

@ -237,8 +237,8 @@ public class LocationProvider
} }
else else
{ {
if(Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest)) // if(Rule.isAnyRuleUsing(Trigger_Enum.pointOfInterest))
GeofenceIntentService.startService(); // GeofenceIntentService.startService();
} }
} }