forked from jens/Automation
Initial commit
This commit is contained in:
@ -0,0 +1,400 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPlayServiceAvailable()
|
||||
{
|
||||
if(GooglePlayServicesUtil.isGooglePlayServicesAvailable(Miscellaneous.getAnyContext()) == ConnectionResult.SUCCESS)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
@ -0,0 +1,301 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.Rule;
|
||||
import com.jens.automation2.Trigger;
|
||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
public class AlarmListener extends BroadcastReceiver implements AutomationListenerInterface
|
||||
{
|
||||
private static AutomationService automationServiceRef;
|
||||
private static AlarmManager centralAlarmManagerInstance;
|
||||
// private static Intent alarmIntent;
|
||||
// private static PendingIntent alarmPendingIntent;
|
||||
private static boolean alarmListenerActive=false;
|
||||
private static ArrayList<Long> alarmCandidates = new ArrayList<Long>();
|
||||
|
||||
private static ArrayList<Integer> requestCodeList = new ArrayList<Integer>();
|
||||
|
||||
public static void startAlarmListener(final AutomationService automationServiceRef)
|
||||
{
|
||||
AlarmListener.startAlarmListenerInternal(automationServiceRef);
|
||||
}
|
||||
public static void stopAlarmListener(Context context)
|
||||
{
|
||||
AlarmListener.stopAlarmListenerInternal();
|
||||
}
|
||||
|
||||
public static boolean isAlarmListenerActive()
|
||||
{
|
||||
return alarmListenerActive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "AlarmListener", "Alarm received", 2);
|
||||
Date now = new Date();
|
||||
String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds());
|
||||
Time passTime = Time.valueOf(timeString);
|
||||
|
||||
ArrayList<Rule> allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime);
|
||||
for(int i=0; i<allRulesWithNowInTimeFrame.size(); i++)
|
||||
{
|
||||
if(allRulesWithNowInTimeFrame.get(i).applies(context))
|
||||
allRulesWithNowInTimeFrame.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
|
||||
setAlarms();
|
||||
}
|
||||
|
||||
public static void setAlarms()
|
||||
{
|
||||
alarmCandidates.clear();
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
||||
|
||||
clearAlarms();
|
||||
|
||||
int i=0;
|
||||
|
||||
// // get a Calendar object with current time
|
||||
// Calendar cal = Calendar.getInstance();
|
||||
// // add 5 minutes to the calendar object
|
||||
// cal.add(Calendar.SECOND, 10);
|
||||
// String calSetWorkingCopyString2 = null;
|
||||
// SimpleDateFormat sdf2 = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
||||
// if (cal != null)
|
||||
// {
|
||||
// calSetWorkingCopyString2 = sdf2.format(cal.getTime());
|
||||
// }
|
||||
// Miscellaneous.logEvent("i", "AlarmManager", "Setting repeating alarm because of hardcoded test: beginning at " + calSetWorkingCopyString2);
|
||||
// Intent alarmIntent2 = new Intent(automationServiceRef, AlarmListener.class);
|
||||
// PendingIntent alarmPendingIntent2 = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent2, 0);
|
||||
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, alarmPendingIntent2);
|
||||
// requestCodeList.add(0);
|
||||
|
||||
ArrayList<Rule> allRulesWithTimeFrames = new ArrayList<Rule>();
|
||||
allRulesWithTimeFrames = Rule.findRuleCandidatesByTimeFrame();
|
||||
for(Rule oneRule : allRulesWithTimeFrames)
|
||||
{
|
||||
for(Trigger oneTrigger : oneRule.getTriggerSet())
|
||||
{
|
||||
if(oneTrigger.getTriggerType() == Trigger_Enum.timeFrame)
|
||||
{
|
||||
Calendar calNow, calSet;
|
||||
Time setTime;
|
||||
|
||||
if(oneTrigger.getTriggerParameter())
|
||||
setTime = oneTrigger.getTimeFrame().getTriggerTimeStart();
|
||||
else
|
||||
setTime = oneTrigger.getTimeFrame().getTriggerTimeStop();
|
||||
|
||||
calNow = Calendar.getInstance();
|
||||
calSet = (Calendar) calNow.clone();
|
||||
calSet.set(Calendar.HOUR_OF_DAY, setTime.getHours());
|
||||
calSet.set(Calendar.MINUTE, setTime.getMinutes());
|
||||
calSet.set(Calendar.SECOND, 0);
|
||||
calSet.set(Calendar.MILLISECOND, 0);
|
||||
// At this point calSet would be a scheduling candidate. It's just the day the might not be right, yet.
|
||||
|
||||
long milliSecondsInAWeek = 1000 * 60 * 60 * 24 * 7;
|
||||
|
||||
for(int dayOfWeek : oneTrigger.getTimeFrame().getDayList())
|
||||
{
|
||||
Calendar calSetWorkingCopy = (Calendar) calSet.clone();
|
||||
|
||||
// calSetWorkingCopy.set(Calendar.HOUR_OF_DAY, setTime.getHours());
|
||||
// calSetWorkingCopy.set(Calendar.MINUTE, setTime.getMinutes());
|
||||
// calSetWorkingCopy.set(Calendar.SECOND, 0);
|
||||
// calSetWorkingCopy.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
int diff = dayOfWeek - calNow.get(Calendar.DAY_OF_WEEK);
|
||||
// Log.i("AlarmManager", "Today: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + " / Sched.Day: " + String.valueOf(dayOfWeek) + " Difference to target day is: " + String.valueOf(diff));
|
||||
if(diff == 0) //if we're talking about the current day, is the time still in the future?
|
||||
{
|
||||
if(calSetWorkingCopy.getTime().getHours() < calNow.getTime().getHours())
|
||||
{
|
||||
// Log.i("AlarmManager", "calSetWorkingCopy.getTime().getHours(" + String.valueOf(calSetWorkingCopy.getTime().getHours()) + ") < calNow.getTime().getHours(" + String.valueOf(calNow.getTime().getHours()) + ")");
|
||||
calSetWorkingCopy.add(Calendar.DAY_OF_MONTH, 7); //add a week
|
||||
}
|
||||
else if(calSetWorkingCopy.getTime().getHours() == calNow.getTime().getHours())
|
||||
{
|
||||
// Log.i("AlarmManager", "calSetWorkingCopy.getTime().getHours() == calNow.getTime().getHours()");
|
||||
if(calSetWorkingCopy.getTime().getMinutes() <= calNow.getTime().getMinutes())
|
||||
{
|
||||
// Log.i("AlarmManager", "calSetWorkingCopy.getTime().getMinutes() < calNow.getTime().getMinutes()");
|
||||
calSetWorkingCopy.add(Calendar.DAY_OF_MONTH, 7); //add a week
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(diff < 0)
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "AlarmManager", "Adding " + String.valueOf(diff+7) + " on top of " + String.valueOf(calSetWorkingCopy.get(Calendar.DAY_OF_WEEK)));
|
||||
calSetWorkingCopy.add(Calendar.DAY_OF_WEEK, diff+7); // it's a past weekday, schedule for next week
|
||||
}
|
||||
else
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "AlarmManager", "Adding " + String.valueOf(diff) + " on top of " + String.valueOf(calSetWorkingCopy.get(Calendar.DAY_OF_WEEK)));
|
||||
calSetWorkingCopy.add(Calendar.DAY_OF_WEEK, diff); // it's a future weekday, schedule for that day
|
||||
}
|
||||
|
||||
i++;
|
||||
i=(int)System.currentTimeMillis();
|
||||
String calSetWorkingCopyString = sdf.format(calSetWorkingCopy.getTime()) + " RequestCode: " + String.valueOf(i);
|
||||
// Miscellaneous.logEvent("i", "AlarmManager", "Setting repeating alarm because of rule: " + oneRule.getName() + " beginning at " + calSetWorkingCopyString);
|
||||
|
||||
alarmCandidates.add(calSetWorkingCopy.getTimeInMillis());
|
||||
// Intent alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
||||
// alarmIntent.setData(Uri.parse("myalarms://" + i));
|
||||
// PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, i, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, calSetWorkingCopy.getTimeInMillis(), milliSecondsInAWeek, alarmPendingIntent);
|
||||
// requestCodeList.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // get a Calendar object with current time
|
||||
// Calendar cal = Calendar.getInstance();
|
||||
// cal.add(Calendar.SECOND, 10);
|
||||
// String calSetWorkingCopyString2 = sdf.format(cal.getTime());
|
||||
// Miscellaneous.logEvent("i", "AlarmManager", "Setting repeating alarm because of hardcoded test: beginning at " + calSetWorkingCopyString2);
|
||||
// Intent alarmIntent2 = new Intent(automationServiceRef, AlarmListener.class);
|
||||
// PendingIntent alarmPendingIntent2 = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent2, 0);
|
||||
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, alarmPendingIntent2);
|
||||
// requestCodeList.add(0);
|
||||
|
||||
scheduleNextAlarm();
|
||||
}
|
||||
|
||||
private static void scheduleNextAlarm()
|
||||
{
|
||||
Long currentTime = System.currentTimeMillis();
|
||||
Long scheduleCandidate = null;
|
||||
|
||||
if(alarmCandidates.size() == 0)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "AlarmManager", "No alarms to be scheduled.", 3);
|
||||
return;
|
||||
}
|
||||
else if(alarmCandidates.size() == 1)
|
||||
{
|
||||
// only one alarm, schedule that
|
||||
scheduleCandidate = alarmCandidates.get(0);
|
||||
}
|
||||
else if(alarmCandidates.size() > 1)
|
||||
{
|
||||
scheduleCandidate = alarmCandidates.get(0);
|
||||
|
||||
for(long alarmCandidate : alarmCandidates)
|
||||
{
|
||||
if(Math.abs(currentTime - alarmCandidate) < Math.abs(currentTime - scheduleCandidate))
|
||||
scheduleCandidate = alarmCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
Intent alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
||||
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
centralAlarmManagerInstance.set(AlarmManager.RTC_WAKEUP, scheduleCandidate, alarmPendingIntent);
|
||||
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("E dd.MM.yyyy HH:mm");
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(scheduleCandidate);
|
||||
Miscellaneous.logEvent("i", "AlarmManager", "Chose " + sdf.format(calendar.getTime()) + " as next scheduled alarm.", 4);
|
||||
|
||||
}
|
||||
|
||||
public static void clearAlarms()
|
||||
{
|
||||
Miscellaneous.logEvent("i", "AlarmManager", "Clearing possibly standing alarms.", 4);
|
||||
for(int requestCode : requestCodeList)
|
||||
{
|
||||
Intent alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
||||
PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, requestCode, alarmIntent, 0);
|
||||
// Miscellaneous.logEvent("i", "AlarmManager", "Clearing alarm with request code: " + String.valueOf(requestCode));
|
||||
centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
||||
}
|
||||
requestCodeList.clear();
|
||||
}
|
||||
|
||||
private static void startAlarmListenerInternal(AutomationService givenAutomationServiceRef)
|
||||
{
|
||||
if(!alarmListenerActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "AlarmListener", "Starting alarm listener.", 4);
|
||||
AlarmListener.automationServiceRef = givenAutomationServiceRef;
|
||||
centralAlarmManagerInstance = (AlarmManager)automationServiceRef.getSystemService(automationServiceRef.ALARM_SERVICE);
|
||||
// alarmIntent = new Intent(automationServiceRef, AlarmListener.class);
|
||||
// alarmPendingIntent = PendingIntent.getBroadcast(automationServiceRef, 0, alarmIntent, 0);
|
||||
alarmListenerActive = true;
|
||||
Miscellaneous.logEvent("i", "AlarmListener", "Alarm listener started.", 4);
|
||||
AlarmListener.setAlarms();
|
||||
|
||||
// // get a Calendar object with current time
|
||||
// Calendar cal = Calendar.getInstance();
|
||||
// // add 5 minutes to the calendar object
|
||||
// cal.add(Calendar.SECOND, 10);
|
||||
// centralAlarmManagerInstance.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, alarmPendingIntent);
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", "AlarmListener", "Request to start AlarmListener. But it's already active.", 5);
|
||||
}
|
||||
|
||||
private static void stopAlarmListenerInternal()
|
||||
{
|
||||
if(alarmListenerActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "AlarmListener", "Stopping alarm listener.", 4);
|
||||
clearAlarms();
|
||||
// centralAlarmManagerInstance.cancel(alarmPendingIntent);
|
||||
alarmListenerActive = false;
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", "AlarmListener", "Request to stop AlarmListener. But it's not running.", 5);
|
||||
}
|
||||
public static void reloadAlarms()
|
||||
{
|
||||
AlarmListener.setAlarms();
|
||||
}
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
AlarmListener.startAlarmListener(automationService);
|
||||
}
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
AlarmListener.stopAlarmListener(automationService);
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return isAlarmListenerActive();
|
||||
}
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return new Trigger_Enum[] { Trigger_Enum.timeFrame };
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||
|
||||
public interface AutomationListenerInterface
|
||||
{
|
||||
public void startListener(AutomationService automationService);
|
||||
public void stopListener(AutomationService automationService);
|
||||
public boolean isListenerRunning();
|
||||
public Trigger_Enum[] getMonitoredTrigger();
|
||||
}
|
@ -0,0 +1,314 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.jens.automation2.ActivityPermissions;
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.Rule;
|
||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BatteryReceiver extends BroadcastReceiver implements AutomationListenerInterface
|
||||
{
|
||||
private static int batteryLevel=-1; // initialize with a better value than this
|
||||
public static AutomationService automationServiceRef = null;
|
||||
private static boolean usbHostConnected = false;
|
||||
|
||||
private static boolean batteryReceiverActive = false;
|
||||
private static IntentFilter batteryIntentFilter = null;
|
||||
private static Intent batteryStatus = null;
|
||||
private static BroadcastReceiver batteryInfoReceiverInstance = null;
|
||||
public static void startBatteryReceiver(final AutomationService automationServiceRef)
|
||||
{
|
||||
if(!batteryReceiverActive)
|
||||
{
|
||||
BatteryReceiver.automationServiceRef = automationServiceRef;
|
||||
|
||||
if(batteryInfoReceiverInstance == null)
|
||||
batteryInfoReceiverInstance = new BatteryReceiver();
|
||||
|
||||
if(batteryIntentFilter == null)
|
||||
{
|
||||
batteryIntentFilter = new IntentFilter();
|
||||
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
batteryIntentFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
||||
// batteryIntentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
|
||||
// batteryIntentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
|
||||
}
|
||||
|
||||
batteryStatus = automationServiceRef.registerReceiver(batteryInfoReceiverInstance, batteryIntentFilter);
|
||||
|
||||
batteryReceiverActive = true;
|
||||
}
|
||||
}
|
||||
public static void stopBatteryReceiver()
|
||||
{
|
||||
if(batteryReceiverActive)
|
||||
{
|
||||
if(batteryInfoReceiverInstance != null)
|
||||
{
|
||||
automationServiceRef.unregisterReceiver(batteryInfoReceiverInstance);
|
||||
batteryInfoReceiverInstance = null;
|
||||
}
|
||||
|
||||
batteryReceiverActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBatteryReceiverActive()
|
||||
{
|
||||
return batteryReceiverActive;
|
||||
}
|
||||
|
||||
public static boolean isUsbHostConnected()
|
||||
{
|
||||
return usbHostConnected;
|
||||
}
|
||||
|
||||
public static int getBatteryLevel()
|
||||
{
|
||||
return batteryLevel;
|
||||
}
|
||||
|
||||
private static int deviceIsCharging = 0; //0=unknown, 1=no, 2=yes
|
||||
|
||||
public static int getDeviceIsCharging()
|
||||
{
|
||||
return deviceIsCharging;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
// Log.i("Battery", "Some battery event");
|
||||
|
||||
if (intent == null)
|
||||
return;
|
||||
if (context == null)
|
||||
return;
|
||||
|
||||
if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW))
|
||||
{
|
||||
Log.i("Battery", "Low battery event");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "BatteryReceiver", "Received battery event.");
|
||||
// if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED))
|
||||
// {
|
||||
batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||
// int scale = -1;
|
||||
// int voltage = -1;
|
||||
// int temp = -1;
|
||||
// scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
|
||||
// temp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
|
||||
// voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
|
||||
Log.i("Battery", "Level: " + String.valueOf(batteryLevel));
|
||||
this.actionBatteryLevel(context);
|
||||
|
||||
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
||||
int statusPlugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
// Miscellaneous.logEvent("i", "BatteryReceiver", "Status: " + String.valueOf(statusPlugged));
|
||||
|
||||
switch(statusPlugged)
|
||||
{
|
||||
case BatteryManager.BATTERY_PLUGGED_AC:
|
||||
// Toast.makeText(context, "Regular charging", Toast.LENGTH_LONG).show();
|
||||
// Miscellaneous.logEvent("i", "BatteryReceiver", "Regular charging.");
|
||||
this.actionCharging(context);
|
||||
break;
|
||||
case BatteryManager.BATTERY_PLUGGED_USB:
|
||||
this.actionUsbConnected(context);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(status)
|
||||
{
|
||||
// case BatteryManager.BATTERY_STATUS_CHARGING:
|
||||
// break;
|
||||
case BatteryManager.BATTERY_STATUS_FULL:
|
||||
// Toast.makeText(context, "Regular charging full", Toast.LENGTH_LONG).show();
|
||||
// Miscellaneous.logEvent("i", "BatteryReceiver", "Device has been fully charged.");
|
||||
this.actionCharging(context);
|
||||
break;
|
||||
case BatteryManager.BATTERY_STATUS_DISCHARGING:
|
||||
this.actionDischarging(context);
|
||||
break;
|
||||
}
|
||||
// }
|
||||
// else if(intent.getAction().equals(Intent.ACTION_POWER_CONNECTED))
|
||||
// {
|
||||
//// Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is charging or full.");
|
||||
// deviceIsCharging = 2;
|
||||
// //activate rule(s)
|
||||
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(true);
|
||||
// for(int i=0; i<ruleCandidates.size(); i++)
|
||||
// {
|
||||
// if(ruleCandidates.get(i).applies(context))
|
||||
// ruleCandidates.get(i).activate(locationProviderRef.getParentService());
|
||||
// }
|
||||
// }
|
||||
// else if(intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED))
|
||||
// {
|
||||
//// Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is discharging.");
|
||||
// deviceIsCharging = 1;
|
||||
// //activate rule(s)
|
||||
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(false);
|
||||
// for(int i=0; i<ruleCandidates.size(); i++)
|
||||
// {
|
||||
// if(ruleCandidates.get(i).applies(context))
|
||||
// ruleCandidates.get(i).activate(locationProviderRef.getParentService());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "BatteryReceiver", "Error receiving battery status: " + e.getMessage(), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int isDeviceCharging(Context context)
|
||||
{
|
||||
switch(deviceIsCharging)
|
||||
{
|
||||
case 0:
|
||||
Miscellaneous.logEvent("w", "ChargingInfo", "Status of device charging was requested. Information isn't available, yet.", 4);
|
||||
break;
|
||||
case 1:
|
||||
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is discharging.", 3);
|
||||
break;
|
||||
case 2:
|
||||
Miscellaneous.logEvent("i", "ChargingInfo", "Status of device charging was requested. Device is charging.", 3);
|
||||
break;
|
||||
}
|
||||
|
||||
return deviceIsCharging;
|
||||
}
|
||||
|
||||
private void actionCharging(Context context)
|
||||
{
|
||||
if(deviceIsCharging != 2) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
|
||||
{
|
||||
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is charging or full.", 3);
|
||||
deviceIsCharging = 2;
|
||||
//activate rule(s)
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(true);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void actionBatteryLevel(Context context)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery level has changed.", 3);
|
||||
//activate rule(s)
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByBatteryLevel();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void actionDischarging(Context context)
|
||||
{
|
||||
if(deviceIsCharging != 1) // Avoid flooding the log. This event will occur on a regular basis even though charging state wasn't changed.
|
||||
{
|
||||
Miscellaneous.logEvent("i", "BatteryReceiver", "Battery is discharging.", 3);
|
||||
deviceIsCharging = 1;
|
||||
//activate rule(s)
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByCharging(false);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
|
||||
this.actionUsbDisconnected(context);
|
||||
}
|
||||
}
|
||||
|
||||
private void actionUsbConnected(Context context)
|
||||
{
|
||||
// Event usbConnected
|
||||
|
||||
// Miscellaneous.logEvent("i", "BatteryReceiver", "BATTERY_PLUGGED_USB");
|
||||
|
||||
if(!usbHostConnected)
|
||||
{
|
||||
usbHostConnected = true;
|
||||
Miscellaneous.logEvent("i", "BatteryReceiver", "Connected to computer.", 3);
|
||||
Toast.makeText(context, "Connected to computer.", Toast.LENGTH_LONG).show();
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(true);
|
||||
for(Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if(oneRule.applies(context))
|
||||
oneRule.activate(automationServiceRef, false);
|
||||
}
|
||||
|
||||
this.actionCharging(context);
|
||||
}
|
||||
}
|
||||
|
||||
private void actionUsbDisconnected(Context context)
|
||||
{
|
||||
// Event usbDisConnected
|
||||
|
||||
if(usbHostConnected)
|
||||
{
|
||||
usbHostConnected = false;
|
||||
Miscellaneous.logEvent("i", "BatteryReceiver", "Disconnected from computer.", 3);
|
||||
Toast.makeText(context, "Disconnected from computer.", Toast.LENGTH_LONG).show();
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByUsbHost(false);
|
||||
for(Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if(oneRule.applies(context))
|
||||
oneRule.activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
BatteryReceiver.startBatteryReceiver(automationService);
|
||||
}
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
BatteryReceiver.stopBatteryReceiver();
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return ActivityPermissions.havePermission("android.permission.READ_PHONE_STATE", Miscellaneous.getAnyContext()) &&
|
||||
ActivityPermissions.havePermission("android.permission.BATTERY_STATS", Miscellaneous.getAnyContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return BatteryReceiver.isBatteryReceiverActive();
|
||||
}
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
// actually monitores several
|
||||
return new Trigger_Enum[] { Trigger_Enum.batteryLevel, Trigger_Enum.charging, Trigger_Enum.usb_host_connection };
|
||||
}
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.util.Log;
|
||||
|
||||
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.Trigger.Trigger_Enum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Set;
|
||||
|
||||
public class BluetoothReceiver extends BroadcastReceiver implements AutomationListenerInterface
|
||||
{
|
||||
protected static ArrayList<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
|
||||
protected static ArrayList<BluetoothDevice> devicesInRange = new ArrayList<BluetoothDevice>();
|
||||
|
||||
protected static BluetoothDevice lastAffectedDevice = null;
|
||||
protected static String lastAction = null;
|
||||
|
||||
protected static IntentFilter bluetoothReceiverIntentFilter = null;
|
||||
protected static boolean bluetoothReceiverActive = false;
|
||||
protected static BluetoothReceiver bluetoothReceiverInstance = null;
|
||||
|
||||
public static boolean isBluetoothReceiverActive()
|
||||
{
|
||||
return bluetoothReceiverActive;
|
||||
}
|
||||
|
||||
public static void startBluetoothReceiver()
|
||||
{
|
||||
if(bluetoothReceiverInstance == null)
|
||||
bluetoothReceiverInstance = new BluetoothReceiver();
|
||||
|
||||
if(bluetoothReceiverIntentFilter == null)
|
||||
{
|
||||
bluetoothReceiverIntentFilter = new IntentFilter();
|
||||
bluetoothReceiverIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
|
||||
bluetoothReceiverIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
|
||||
bluetoothReceiverIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(!bluetoothReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "BluetoothReceiver", "Starting BluetoothReceiver", 4);
|
||||
bluetoothReceiverActive = true;
|
||||
AutomationService.getInstance().registerReceiver(bluetoothReceiverInstance, bluetoothReceiverIntentFilter);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "BluetoothReceiver", "Error starting BluetoothReceiver: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
public static void stopBluetoothReceiver()
|
||||
{
|
||||
try
|
||||
{
|
||||
if(bluetoothReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "BluetoothReceiver", "Stopping BluetoothReceiver", 4);
|
||||
bluetoothReceiverActive = false;
|
||||
AutomationService.getInstance().unregisterReceiver(bluetoothReceiverInstance);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "BluetoothReceiver", "Error stopping BluetoothReceiver: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public static BluetoothDevice getLastAffectedDevice()
|
||||
{
|
||||
return lastAffectedDevice;
|
||||
}
|
||||
|
||||
public static String getLastAction()
|
||||
{
|
||||
return lastAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "BluetoothReceiver", "Bluetooth event.", 4);
|
||||
|
||||
String action = intent.getAction();
|
||||
BluetoothDevice bluetoothDevice = null;
|
||||
|
||||
if(action.equals(BluetoothDevice.ACTION_ACL_CONNECTED) | action.equals("android.bluetooth.device.action.ACL_CONNECTED"))
|
||||
{
|
||||
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
lastAffectedDevice = bluetoothDevice;
|
||||
lastAction = action;
|
||||
connectedDevices.add(bluetoothDevice);
|
||||
Miscellaneous.logEvent("i", "BluetoothReceiver", String.format(context.getResources().getString(R.string.bluetoothConnectionTo), bluetoothDevice.getName()), 3);
|
||||
}
|
||||
else if(action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED) | action.equals(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED) | action.equals("android.bluetooth.device.ACTION_ACL_DISCONNECTED") | action.equals("android.bluetooth.device.ACTION_ACL_DISCONNECT_REQUESTED"))
|
||||
{
|
||||
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
lastAffectedDevice = bluetoothDevice;
|
||||
lastAction = action;
|
||||
connectedDevices.remove(bluetoothDevice);
|
||||
Miscellaneous.logEvent("i", "BluetoothReceiver", String.format(context.getResources().getString(R.string.bluetoothDisconnectFrom), bluetoothDevice.getName()), 3);
|
||||
}
|
||||
else if(action.equals(BluetoothDevice.ACTION_FOUND) | action.equals("android.bluetooth.device.ACTION_FOUND"))
|
||||
{
|
||||
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
lastAffectedDevice = bluetoothDevice;
|
||||
lastAction = action;
|
||||
devicesInRange.add(bluetoothDevice);
|
||||
Miscellaneous.logEvent("i", "BluetoothReceiver", String.format(context.getResources().getString(R.string.bluetoothDeviceInRange), bluetoothDevice.getName()), 3);
|
||||
}
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByBluetoothConnection();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(AutomationService.getInstance()))
|
||||
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public static BluetoothDevice[] getAllPairedBluetoothDevices()
|
||||
{
|
||||
BluetoothDevice[] returnArray;
|
||||
|
||||
try
|
||||
{
|
||||
Set<BluetoothDevice> deviceList = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
|
||||
returnArray = deviceList.toArray(new BluetoothDevice[deviceList.size()]);
|
||||
|
||||
Arrays.sort(returnArray, new Comparator<BluetoothDevice>()
|
||||
{
|
||||
@Override
|
||||
public int compare(BluetoothDevice lhs, BluetoothDevice rhs)
|
||||
{
|
||||
return lhs.getName().compareTo(rhs.getName());
|
||||
}
|
||||
|
||||
;
|
||||
});
|
||||
}
|
||||
catch(NullPointerException e)
|
||||
{
|
||||
// There are no paired bluetooth devices.
|
||||
|
||||
returnArray = new BluetoothDevice[] {};
|
||||
}
|
||||
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public static String[] getAllPairedBluetoothDevicesStrings()
|
||||
{
|
||||
ArrayList<String> names = new ArrayList<String>();
|
||||
for(BluetoothDevice device : getAllPairedBluetoothDevices())
|
||||
names.add(device.getName() + " (" + device.getAddress() + ")");
|
||||
|
||||
return names.toArray(new String[names.size()]);
|
||||
}
|
||||
|
||||
public static BluetoothDevice getDeviceByName(String name)
|
||||
{
|
||||
for(BluetoothDevice device : getAllPairedBluetoothDevices())
|
||||
{
|
||||
if(device.getName().equals(name))
|
||||
return device;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BluetoothDevice getDeviceByAddress(String address)
|
||||
{
|
||||
for(BluetoothDevice device : getAllPairedBluetoothDevices())
|
||||
{
|
||||
if(device.getAddress().equals(address))
|
||||
return device;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getDevicePositionByAddress(String address)
|
||||
{
|
||||
BluetoothDevice[] allDevices = getAllPairedBluetoothDevices();
|
||||
for(int i=0; i<allDevices.length; i++)
|
||||
{
|
||||
if(allDevices[i].getAddress().equals(address))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static boolean isDeviceCurrentlyConnected(BluetoothDevice searchDevice)
|
||||
{
|
||||
for(BluetoothDevice device : connectedDevices)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (device.getAddress().equals(searchDevice.getAddress()))
|
||||
return true;
|
||||
}
|
||||
catch(NullPointerException e)
|
||||
{
|
||||
/*
|
||||
Just proceed with the next loop.
|
||||
|
||||
This may happen if devices have been unpaired since
|
||||
they have been added for usage in a rule.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAnyDeviceConnected()
|
||||
{
|
||||
if(connectedDevices.size() > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAnyDeviceInRange()
|
||||
{
|
||||
if(devicesInRange.size() > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isDeviceInRange(BluetoothDevice searchDevice)
|
||||
{
|
||||
for(BluetoothDevice device : devicesInRange)
|
||||
if(device.getAddress().equals(searchDevice.getAddress()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void discovery()
|
||||
{
|
||||
BluetoothAdapter.getDefaultAdapter().startDiscovery();
|
||||
BroadcastReceiver discoveryReceiver = new BroadcastReceiver()
|
||||
{
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
String action = intent.getAction();
|
||||
//ACTION_DISCOVERY_STARTED and ACTION_DISCOVERY_FINISHED
|
||||
if(action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
|
||||
{
|
||||
// This would be a good point to look for devices that are not in range anymore.
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
BluetoothReceiver.startBluetoothReceiver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
BluetoothReceiver.stopBluetoothReceiver();
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return ActivityPermissions.havePermission("android.permission.BLUETOOTH_ADMIN", Miscellaneous.getAnyContext()) &&
|
||||
ActivityPermissions.havePermission("android.permission.BLUETOOTH", Miscellaneous.getAnyContext()) &&
|
||||
ActivityPermissions.havePermission("android.permission.ACCESS_NETWORK_STATE", Miscellaneous.getAnyContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return BluetoothReceiver.isBluetoothReceiverActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return new Trigger_Enum[] { Trigger_Enum.bluetoothConnection };
|
||||
}
|
||||
}
|
@ -0,0 +1,263 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jens.automation2.ActivityPermissions;
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.Rule;
|
||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||
import com.jens.automation2.location.WifiBroadcastReceiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ConnectivityReceiver extends BroadcastReceiver implements AutomationListenerInterface
|
||||
{
|
||||
protected static boolean connectivityReceiverActive = false;
|
||||
private static ConnectivityReceiver connectivityReceiverInstance = null;
|
||||
private static IntentFilter connectivityIntentFilter = null;
|
||||
private static AutomationService automationServiceRef = null;
|
||||
protected static boolean dataConnectionLastState = false;
|
||||
protected static boolean roamingLastState = false;
|
||||
|
||||
public static boolean isConnectivityReceiverActive()
|
||||
{
|
||||
return connectivityReceiverActive;
|
||||
}
|
||||
|
||||
public static void startConnectivityReceiver(AutomationService ref)
|
||||
{
|
||||
automationServiceRef = ref;
|
||||
|
||||
if(connectivityReceiverInstance == null)
|
||||
connectivityReceiverInstance = new ConnectivityReceiver();
|
||||
|
||||
|
||||
if(connectivityIntentFilter == null)
|
||||
{
|
||||
connectivityIntentFilter = new IntentFilter();
|
||||
connectivityIntentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
connectivityIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(!connectivityReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Wifi Listener", "Starting connectivityReceiver", 4);
|
||||
connectivityReceiverActive = true;
|
||||
automationServiceRef.registerReceiver(connectivityReceiverInstance, connectivityIntentFilter);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "Wifi Listener", "Error starting connectivityReceiver: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void stopConnectivityReceiver()
|
||||
{
|
||||
try
|
||||
{
|
||||
if(connectivityReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Wifi Listener", "Stopping connectivityReceiver", 4);
|
||||
connectivityReceiverActive = false;
|
||||
automationServiceRef.unregisterReceiver(connectivityReceiverInstance);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "Wifi Listener", "Error stopping connectivityReceiver: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
// Get roaming state from telephony manager
|
||||
public static Boolean isRoaming(Context context)
|
||||
{
|
||||
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
return telephonyManager.isNetworkRoaming();
|
||||
}
|
||||
|
||||
public static void setDataConnectionLastState(boolean newState)
|
||||
{
|
||||
if(dataConnectionLastState != newState)
|
||||
{
|
||||
dataConnectionLastState = newState;
|
||||
|
||||
// Run rules if I decide to create such a trigger
|
||||
// automationServiceRef.getLocationProvider().handleDataConnectionChange(newState);
|
||||
}
|
||||
}
|
||||
public static Boolean isDataConnectionAvailable(Context context)
|
||||
{
|
||||
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo ni = connManager.getActiveNetworkInfo();
|
||||
return ni != null && ni.isConnected();
|
||||
}
|
||||
|
||||
// Get airplane mode state from system settings
|
||||
@SuppressLint("NewApi")
|
||||
public static boolean isAirplaneMode(Context context)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
{
|
||||
int value = android.provider.Settings.System.getInt(context.getContentResolver(), android.provider.Settings.System.AIRPLANE_MODE_ON, 0);
|
||||
return value != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return android.provider.Settings.Global.getInt(context.getContentResolver(), android.provider.Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (context == null)
|
||||
return;
|
||||
|
||||
if(intent.getAction().equals(Intent.ACTION_AIRPLANE_MODE_CHANGED))
|
||||
{
|
||||
// Airplane mode status has changed.
|
||||
Miscellaneous.logEvent("i", "Connectivity", "Airplane mode changed.", 2);
|
||||
boolean isAirplaneMode = isAirplaneMode(context);
|
||||
automationServiceRef.getLocationProvider().handleAirplaneMode(isAirplaneMode);
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByAirplaneMode(isAirplaneMode);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(automationServiceRef))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
else if(intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION))
|
||||
{
|
||||
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
// NetworkInfo ni = connManager.getActiveNetworkInfo();
|
||||
NetworkInfo ni = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
|
||||
if(ni != null)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Connectivity", "Change of network with type " + ni.getType() + " noticed.", 4);
|
||||
|
||||
switch(ni.getType())
|
||||
{
|
||||
case ConnectivityManager.TYPE_WIFI:
|
||||
WifiBroadcastReceiver.lastConnectedState = ni.isConnected();
|
||||
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
||||
WifiBroadcastReceiver.setLastWifiSsid(wifiInfo.getSSID());
|
||||
WifiBroadcastReceiver.findRules(automationServiceRef.getLocationProvider());
|
||||
break;
|
||||
case ConnectivityManager.TYPE_MOBILE:
|
||||
boolean isRoaming = isRoaming(context);
|
||||
if(isRoaming != roamingLastState)
|
||||
{
|
||||
roamingLastState = isRoaming;
|
||||
|
||||
automationServiceRef.getLocationProvider().handleRoaming(isRoaming);
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByRoaming(isRoaming);
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(automationServiceRef))
|
||||
ruleCandidates.get(i).activate(automationServiceRef, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// case ConnectivityManager.TYPE_BLUETOOTH:
|
||||
|
||||
|
||||
/*
|
||||
* BluetoothAdapter.ACTION_STATE_CHANGED ("android.bluetooth.adapter.action.STATE_CHANGED")
|
||||
|
||||
Broadcast Action: The state of the local Bluetooth adapter has been changed. For example, Bluetooth has been turned on or off.
|
||||
|
||||
and for Ringer mode changes:
|
||||
|
||||
AudioManager.RINGER_MODE_CHANGED_ACTION ("android.media.RINGER_MODE_CHANGED")
|
||||
|
||||
Sticky broadcast intent action indicating that the ringer mode has changed. Includes the new ringer mode.
|
||||
|
||||
Not a ringer mode change, but this can be good to have also AudioManager.VIBRATE_SETTING_CHANGED_ACTION ("android.media.VIBRATE_SETTING_CHANGED")
|
||||
|
||||
Broadcast intent action indicating that the vibrate setting has changed. Includes the vibrate type and its new setting.
|
||||
*/
|
||||
// BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
// if(bluetoothDevice.getBondState()
|
||||
// if(BluetoothDevice.)
|
||||
// ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByRoaming(isRoaming);
|
||||
// for(int i=0; i<ruleCandidates.size(); i++)
|
||||
// {
|
||||
// if(ruleCandidates.get(i).applies(parentLocationProvider.getParentService()))
|
||||
// ruleCandidates.get(i).activate(parentLocationProvider.getParentService());
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
Miscellaneous.logEvent("i", "Connectivity", "Type of changed network not specified. Doing nothing.", 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkInfo wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||
if(!wifiInfo.isAvailable() && WifiBroadcastReceiver.lastConnectedState)
|
||||
{
|
||||
// This will serve as a disconnected event. Happens if wifi is connected, then module deactivated.
|
||||
Miscellaneous.logEvent("i", "Connectivity", "Wifi deactivated while having been connected before.", 4);
|
||||
WifiBroadcastReceiver.lastConnectedState = false;
|
||||
WifiBroadcastReceiver.findRules(automationServiceRef.getLocationProvider());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "Connectivity", "Error in ConnectivityReceiver->onReceive(): " + Log.getStackTraceString(e), 3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
ConnectivityReceiver.startConnectivityReceiver(automationService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
ConnectivityReceiver.stopConnectivityReceiver();
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return ActivityPermissions.havePermission("android.permission.ACCESS_NETWORK_STATE", Miscellaneous.getAnyContext()) &&
|
||||
ActivityPermissions.havePermission("android.permission.ACCESS_WIFI_STATE", Miscellaneous.getAnyContext()) &&
|
||||
ActivityPermissions.havePermission("android.permission.ACCESS_NETWORK_STATE", Miscellaneous.getAnyContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return ConnectivityReceiver.isConnectivityReceiverActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return new Trigger_Enum[] { Trigger_Enum.airplaneMode, Trigger_Enum.roaming, Trigger_Enum.wifiConnection };
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jens.automation2.ActivityPermissions;
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.Rule;
|
||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class HeadphoneJackListener extends BroadcastReceiver implements AutomationListenerInterface
|
||||
{
|
||||
private static boolean headsetConnected = false;
|
||||
private static int headphoneType = -1;
|
||||
|
||||
protected static boolean headphoneJackListenerActive=false;
|
||||
protected static IntentFilter headphoneJackListenerIntentFilter = null;
|
||||
protected static HeadphoneJackListener instance;
|
||||
|
||||
public static HeadphoneJackListener getInstance()
|
||||
{
|
||||
if(instance == null)
|
||||
instance = new HeadphoneJackListener();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean isHeadphoneJackListenerActive()
|
||||
{
|
||||
return headphoneJackListenerActive;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isHeadsetConnected()
|
||||
{
|
||||
return headsetConnected;
|
||||
}
|
||||
|
||||
public static int getHeadphoneType()
|
||||
{
|
||||
return headphoneType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
try
|
||||
{
|
||||
/*Broadcast Action: Wired Headset plugged in or unplugged.
|
||||
The intent will have the following extra values:
|
||||
|
||||
state - 0 for unplugged, 1 for plugged.
|
||||
name - Headset type, human readable string
|
||||
microphone - 1 if headset has a microphone, 0 otherwise*/
|
||||
|
||||
int state = intent.getExtras().getInt("state");
|
||||
String name = intent.getExtras().getString("name");
|
||||
headphoneType = intent.getExtras().getInt("microphone");
|
||||
|
||||
if(state == 0)
|
||||
{
|
||||
headsetConnected = false;
|
||||
Miscellaneous.logEvent("i", "HeadphoneJackListener", "Headset " + name + " unplugged.", 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
headsetConnected = true;
|
||||
Miscellaneous.logEvent("i", "HeadphoneJackListener", "Headset " + name + " plugged in.", 4);
|
||||
}
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByHeadphoneJack(isHeadsetConnected());
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(context))
|
||||
ruleCandidates.get(i).activate(AutomationService.getInstance(), false);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
if(headphoneJackListenerIntentFilter == null)
|
||||
{
|
||||
headphoneJackListenerIntentFilter = new IntentFilter();
|
||||
headphoneJackListenerIntentFilter.addAction(Intent.ACTION_HEADSET_PLUG);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(!headphoneJackListenerActive && Rule.isAnyRuleUsing(Trigger_Enum.headsetPlugged))
|
||||
{
|
||||
Miscellaneous.logEvent("i", "HeadsetJackListener", "Starting HeadsetJackListener", 4);
|
||||
headphoneJackListenerActive = true;
|
||||
// getInstance().startHeadphoneJackListener(AutomationService.getInstance(), headphoneJackListenerIntentFilter);
|
||||
automationService.registerReceiver(this, headphoneJackListenerIntentFilter);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "ActivityDetectionReceiver", "Error starting HeadsetJackListener: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(headphoneJackListenerActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "HeadsetJackListener", "Stopping HeadsetJackListener", 4);
|
||||
// getInstance().stopHeadphoneJackListener(AutomationService.getInstance());
|
||||
automationService.unregisterReceiver(this);
|
||||
headphoneJackListenerActive = false;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "ActivityDetectionReceiver", "Error stopping HeadsetJackListener: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return ActivityPermissions.havePermission("android.permission.READ_PHONE_STATE", Miscellaneous.getAnyContext());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return HeadphoneJackListener.isHeadphoneJackListenerActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return new Trigger_Enum[] { Trigger_Enum.headsetPlugged };
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,344 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.Tag;
|
||||
import android.nfc.tech.Ndef;
|
||||
import android.nfc.tech.NdefFormatable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.R;
|
||||
import com.jens.automation2.Rule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public class NfcReceiver
|
||||
{
|
||||
public static final String MIME_TEXT_PLAIN = "text/plain";
|
||||
public static String lastReadLabel = null;
|
||||
|
||||
private static NfcAdapter nfcAdapter = null;
|
||||
public static NfcAdapter getNfcAdapter(Context context)
|
||||
{
|
||||
if(nfcAdapter == null)
|
||||
{
|
||||
if(Build.VERSION.SDK_INT <= 10)
|
||||
{
|
||||
// NFC not supported until after Gingerbread.
|
||||
Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.nfcNotSupportedInThisAndroidVersionYet), 3);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
nfcAdapter = NfcAdapter.getDefaultAdapter(context);
|
||||
}
|
||||
}
|
||||
return nfcAdapter;
|
||||
}
|
||||
|
||||
public static void setNfcAdapter(NfcAdapter nfcAdapter)
|
||||
{
|
||||
NfcReceiver.nfcAdapter = nfcAdapter;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public static void checkIntentForNFC(Context context, Intent intent)
|
||||
{
|
||||
if(!NfcReceiver.checkNfcRequirements(context, false))
|
||||
return;
|
||||
|
||||
String action = intent.getAction();
|
||||
if(action == null)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "NFC", "action=null", 5);
|
||||
return;
|
||||
}
|
||||
|
||||
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
|
||||
{
|
||||
Miscellaneous.logEvent("i", "NFC", "ACTION_NDEF_DISCOVERED", 4);
|
||||
|
||||
getNfcAdapter(context);
|
||||
|
||||
if(nfcAdapter == null) // if it's still null the device doesn't support NFC
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String mimeType = intent.getType();
|
||||
if(mimeType.equals(MIME_TEXT_PLAIN))
|
||||
{
|
||||
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
|
||||
|
||||
// if(NfcReceiver.discoveredTag == null)
|
||||
// NfcReceiver.discoveredTag = tag;
|
||||
|
||||
new NdefReaderTask().execute(tag);
|
||||
}
|
||||
}
|
||||
// else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action))
|
||||
// {
|
||||
//
|
||||
// // In case we would still use the Tech Discovered Intent
|
||||
// Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
|
||||
// String[] techList = tag.getTechList();
|
||||
// String searchedTech = Ndef.class.getName();
|
||||
//
|
||||
// for (String tech : techList)
|
||||
// {
|
||||
// if (searchedTech.equals(tech))
|
||||
// {
|
||||
// new NdefReaderTask().execute(tag);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // No NFC NDEF intent
|
||||
// Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.nfcNoNdefIntentBut) + " " + action + ".", 5);
|
||||
// }
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public static class NdefReaderTask extends AsyncTask<Tag, Void, String>
|
||||
{
|
||||
@Override
|
||||
protected String doInBackground(Tag... params)
|
||||
{
|
||||
Tag tag = params[0];
|
||||
|
||||
Ndef ndef = Ndef.get(tag);
|
||||
if (ndef == null)
|
||||
{
|
||||
// NDEF is not supported by this Tag.
|
||||
return null;
|
||||
}
|
||||
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
|
||||
NdefRecord[] records = ndefMessage.getRecords();
|
||||
for (NdefRecord ndefRecord : records)
|
||||
{
|
||||
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT))
|
||||
{
|
||||
try
|
||||
{
|
||||
return readText(ndefRecord);
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "NFC", Miscellaneous.getAnyContext().getString(R.string.nfcUnsupportedEncoding) + " " + Log.getStackTraceString(e), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
// return readTag(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result)
|
||||
{
|
||||
if (result != null && result.length() > 0)
|
||||
{
|
||||
// Text of tag is now stored in variable "result"
|
||||
lastReadLabel = result;
|
||||
Miscellaneous.logEvent("i", "NFC", Miscellaneous.getAnyContext().getResources().getString(R.string.nfcTagFoundWithText) + " " + result, 3);
|
||||
Toast.makeText(Miscellaneous.getAnyContext(), Miscellaneous.getAnyContext().getResources().getString(R.string.nfcTagFoundWithText) + " " + result, Toast.LENGTH_LONG).show();
|
||||
|
||||
AutomationService asInstance = AutomationService.getInstance();
|
||||
if(asInstance == null)
|
||||
{
|
||||
Context context = Miscellaneous.getAnyContext();
|
||||
if(context != null)
|
||||
{
|
||||
Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.serviceNotRunning) + " " + context.getResources().getString(R.string.cantRunRule), 4);
|
||||
Toast.makeText(context, context.getResources().getString(R.string.serviceNotRunning) + " " + context.getResources().getString(R.string.cantRunRule), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayList<Rule> allRulesWithNfcTags = Rule.findRuleCandidatesByNfc();
|
||||
for(int i=0; i<allRulesWithNfcTags.size(); i++)
|
||||
{
|
||||
if(allRulesWithNfcTags.get(i).applies(asInstance))
|
||||
allRulesWithNfcTags.get(i).activate(asInstance, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class NdefWriterTask extends AsyncTask<Object, Void, Boolean>
|
||||
{
|
||||
@Override
|
||||
protected Boolean doInBackground(Object... params)
|
||||
{
|
||||
String textToWrite = (String)params[0];
|
||||
Tag tagToWrite = (Tag)params[1];
|
||||
return writeTag(textToWrite, tagToWrite);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected void onPostExecute(Boolean result)
|
||||
// {
|
||||
// return result;
|
||||
// }
|
||||
}
|
||||
|
||||
public static String readTag(Tag tag)
|
||||
{
|
||||
// if(tag == null)
|
||||
// {
|
||||
// Toast.makeText(Miscellaneous.getAnyContext(), Miscellaneous.getAnyContext().getResources().getString(R.string.nfcNoTag), Toast.LENGTH_LONG).show();
|
||||
// return null;
|
||||
// }
|
||||
|
||||
Ndef ndef = Ndef.get(tag);
|
||||
if (ndef == null)
|
||||
{
|
||||
// NDEF is not supported by this Tag.
|
||||
return null;
|
||||
}
|
||||
|
||||
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
|
||||
|
||||
NdefRecord[] records = ndefMessage.getRecords();
|
||||
for (NdefRecord ndefRecord : records)
|
||||
{
|
||||
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT))
|
||||
{
|
||||
try
|
||||
{
|
||||
return readText(ndefRecord);
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
Miscellaneous.logEvent("w", "NFC", "Unsupported Encoding: " + Log.getStackTraceString(e), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String readText(NdefRecord record) throws UnsupportedEncodingException
|
||||
{
|
||||
/*
|
||||
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
|
||||
*
|
||||
* http://www.nfc-forum.org/specs/
|
||||
*
|
||||
* bit_7 defines encoding
|
||||
* bit_6 reserved for future use, must be 0
|
||||
* bit_5..0 length of IANA language code
|
||||
*/
|
||||
|
||||
byte[] payload = record.getPayload();
|
||||
|
||||
// Get the Text Encoding
|
||||
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
|
||||
|
||||
// Get the Language Code
|
||||
int languageCodeLength = payload[0] & 0063;
|
||||
|
||||
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
|
||||
// e.g. "en"
|
||||
|
||||
// Get the Text
|
||||
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
|
||||
}
|
||||
|
||||
public static boolean writeTag(String textToWrite, Tag tag)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "NFC", "Attempting to write tag...", 2);
|
||||
|
||||
String packageName = Miscellaneous.getAnyContext().getPackageName();
|
||||
NdefRecord appRecord = NdefRecord.createApplicationRecord(packageName);
|
||||
// Record with actual data we care about
|
||||
byte[] textBytes = textToWrite.getBytes();
|
||||
byte[] textPayload = new byte[textBytes.length + 3];
|
||||
textPayload[0] = 0x02; // 0x02 = UTF8
|
||||
textPayload[1] = 'e'; // Language = en
|
||||
textPayload[2] = 'n';
|
||||
System.arraycopy(textBytes, 0, textPayload, 3, textBytes.length);
|
||||
NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], textPayload);
|
||||
|
||||
// Complete NDEF message with both records
|
||||
NdefMessage completeMessageToWrite = new NdefMessage(new NdefRecord[] {textRecord, appRecord});
|
||||
|
||||
int size = completeMessageToWrite.toByteArray().length;
|
||||
try
|
||||
{
|
||||
Ndef ndef = Ndef.get(tag);
|
||||
if (ndef != null)
|
||||
{
|
||||
ndef.connect();
|
||||
if (ndef.isWritable() && ndef.getMaxSize() > size)
|
||||
{
|
||||
ndef.writeNdefMessage(completeMessageToWrite);
|
||||
Miscellaneous.logEvent("i", "NFC", "Done writing tag.", 2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NdefFormatable format = NdefFormatable.get(tag);
|
||||
if (format != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
format.connect();
|
||||
format.format(completeMessageToWrite);
|
||||
Miscellaneous.logEvent("i", "NFC", "Done writing tag.", 2);
|
||||
return true;
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "NFC", "Error writing tag: " + Log.getStackTraceString(e), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "NFC", "Error writing tag: " + Log.getStackTraceString(e), 2);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean checkNfcRequirements(Context context, boolean showErrorMessage)
|
||||
{
|
||||
if(!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC))
|
||||
{
|
||||
if(showErrorMessage)
|
||||
Toast.makeText(context, context.getResources().getString(R.string.deviceDoesNotHaveNfc), Toast.LENGTH_LONG).show();
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(Build.VERSION.SDK_INT <= 10)
|
||||
{
|
||||
// NFC not supported until after Gingerbread.
|
||||
if(showErrorMessage)
|
||||
Toast.makeText(context, context.getResources().getString(R.string.nfcNotSupportedInThisAndroidVersionYet), Toast.LENGTH_LONG).show();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.media.MediaRecorder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import com.jens.automation2.ActivityPermissions;
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.Rule;
|
||||
import com.jens.automation2.Settings;
|
||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class NoiseListener implements AutomationListenerInterface
|
||||
{
|
||||
private static AutomationService automationService;
|
||||
private static boolean isMeasuringActive = false;
|
||||
private static boolean isTimerActive = false;
|
||||
private static long noiseLevelDb;
|
||||
private static Handler workHandler = new Handler()
|
||||
{
|
||||
@Override
|
||||
public void handleMessage(Message msg)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Noise level", "Message received stating measurement is complete.", 5);
|
||||
// This will take care of results delivered by the actual measuring instance
|
||||
noiseLevelDb = msg.getData().getLong("noiseLevelDb");
|
||||
|
||||
// execute matching rules containing noise
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByNoiseLevel();
|
||||
for(Rule oneRule : ruleCandidates)
|
||||
{
|
||||
if(oneRule.applies(automationService))
|
||||
oneRule.activate(automationService, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
private static NoiseListenerMeasuring listener;
|
||||
|
||||
private static boolean stopRequested = false;
|
||||
private static Handler schedulingHandler = new Handler()
|
||||
{
|
||||
@Override
|
||||
public void handleMessage(Message msg)
|
||||
{
|
||||
if(msg.arg1 == 1)
|
||||
{
|
||||
if(!stopRequested)
|
||||
{
|
||||
if(listener == null)
|
||||
listener = new NoiseListenerMeasuring();
|
||||
listener.doMeasuring();
|
||||
Miscellaneous.logEvent("i", "Noise level", "Rearming noise level message.", 5);
|
||||
Message message = new Message();
|
||||
message.arg1 = 1;
|
||||
schedulingHandler.sendMessageDelayed(message, Settings.timeBetweenNoiseLevelMeasurements * 1000);
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", "Noise level", "Not rearming noise level message, stop requested.", 5);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private static class NoiseListenerMeasuring
|
||||
{
|
||||
Thread measuringThread;
|
||||
|
||||
public void doMeasuring()
|
||||
{
|
||||
measuringThread = new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isMeasuringActive)
|
||||
{
|
||||
isMeasuringActive = true;
|
||||
|
||||
Miscellaneous.logEvent("i", "Noise level", "Periodic noise level measurement started.", 5);
|
||||
|
||||
// Start recording but don't store data
|
||||
MediaRecorder mediaRecorder = new MediaRecorder();
|
||||
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
|
||||
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
|
||||
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
|
||||
mediaRecorder.setOutputFile("/dev/null");
|
||||
// Date myDate = new Date();
|
||||
// mediaRecorder.setOutputFile("/sdcard/temp/" + String.valueOf(myDate.getTime()) + ".3gpp");
|
||||
try
|
||||
{
|
||||
mediaRecorder.prepare();
|
||||
mediaRecorder.getMaxAmplitude();
|
||||
mediaRecorder.start();
|
||||
mediaRecorder.getMaxAmplitude();
|
||||
|
||||
long noiseLevel;
|
||||
|
||||
try
|
||||
{
|
||||
sleep(Settings.lengthOfNoiseLevelMeasurements * 1000);
|
||||
// Obtain maximum amplitude since last call of getMaxAmplitude()
|
||||
noiseLevel = mediaRecorder.getMaxAmplitude();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
noiseLevel = -1;
|
||||
Miscellaneous.logEvent("e", "Noise level", "Error getting sound level: " + e.getMessage(), 2);
|
||||
}
|
||||
|
||||
double db = 20 * Math.log(noiseLevel / Settings.referenceValueForNoiseLevelMeasurements);
|
||||
noiseLevelDb = Math.round(db);
|
||||
|
||||
Message answer = new Message();
|
||||
Bundle answerBundle = new Bundle();
|
||||
answerBundle.putLong("noiseLevelDb", noiseLevelDb);
|
||||
answer.setData(answerBundle);
|
||||
workHandler.sendMessage(answer);
|
||||
|
||||
Miscellaneous.logEvent("i", "Noise level", "Measured noise level: " + String.valueOf(noiseLevel) + " / converted to db: " + String.valueOf(db), 3);
|
||||
|
||||
// Don't forget to release
|
||||
mediaRecorder.reset();
|
||||
mediaRecorder.release();
|
||||
}
|
||||
catch(Exception e)
|
||||
{}
|
||||
|
||||
isMeasuringActive = false;
|
||||
|
||||
Miscellaneous.logEvent("i", "Noise level", "Periodic noise level measurement stopped.", 5);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
measuringThread.start();
|
||||
}
|
||||
|
||||
public void interrupt()
|
||||
{
|
||||
measuringThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public static void startNoiseListener(AutomationService newAutomationService)
|
||||
{
|
||||
automationService = newAutomationService;
|
||||
|
||||
if(!isTimerActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Noise level", "Starting periodic noise level measurement engine.", 2);
|
||||
isTimerActive = true;
|
||||
|
||||
Message message = new Message();
|
||||
message.arg1 = 1;
|
||||
schedulingHandler.sendMessageDelayed(message, Settings.timeBetweenNoiseLevelMeasurements * 1000);
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", "Noise level", "Periodic noise level measurement is already running. Won't start it again.", 2);
|
||||
}
|
||||
public static void stopNoiseListener()
|
||||
{
|
||||
if(isTimerActive)
|
||||
{
|
||||
stopRequested = true;
|
||||
Miscellaneous.logEvent("i", "Noise level", "Stopping periodic noise level measurement engine.", 2);
|
||||
|
||||
if(schedulingHandler.hasMessages(1))
|
||||
schedulingHandler.removeMessages(1);
|
||||
|
||||
if(listener != null)
|
||||
listener.interrupt();
|
||||
|
||||
isTimerActive = false;
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", "Noise level", "Periodic noise level measurement is not active. Can't stop it.", 2);
|
||||
}
|
||||
|
||||
public static long getNoiseLevelDb()
|
||||
{
|
||||
return noiseLevelDb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
NoiseListener.startNoiseListener(automationService);
|
||||
}
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
NoiseListener.stopNoiseListener();
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return ActivityPermissions.havePermission("android.permission.RECORD_AUDIO", Miscellaneous.getAnyContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return NoiseListener.isMeasuringActive | NoiseListener.isTimerActive;
|
||||
}
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return new Trigger_Enum[] { Trigger_Enum.noiseLevel };
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.R;
|
||||
import com.jens.automation2.Settings;
|
||||
|
||||
public class PackageReplacedReceiver extends BroadcastReceiver
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
// Toast.makeText(context, "package replaced", Toast.LENGTH_LONG).show();
|
||||
// int intentUid = intent.getExtras().getInt("android.intent.extra.UID"); // userid of the application that has just been updated
|
||||
// int myUid = android.os.Process.myUid(); // userid of this application
|
||||
//
|
||||
// boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
|
||||
|
||||
// if(intentUid == myUid)
|
||||
// {
|
||||
Settings.readFromPersistentStorage(context);
|
||||
|
||||
Miscellaneous.logEvent("i", context.getResources().getString(R.string.applicationHasBeenUpdated), context.getResources().getString(R.string.applicationHasBeenUpdated), 2);
|
||||
if(hasServiceBeenRunning() && Settings.startServiceAfterAppUpdate)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Service", context.getResources().getString(R.string.logStartingServiceAfterAppUpdate), 1);
|
||||
AutomationService.startAutomationService(context, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Service", context.getResources().getString(R.string.logNotStartingServiceAfterAppUpdate), 2);
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// Miscellaneous.logEvent("i", "Service", "Some other app has been updated.", 5);
|
||||
}
|
||||
|
||||
private static boolean hasServiceBeenRunning()
|
||||
{
|
||||
return Settings.hasServiceBeenRunning;
|
||||
}
|
||||
|
||||
public static void setHasServiceBeenRunning(boolean state, Context context)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "State", "Writing stateFile to " + String.valueOf(state), 4);
|
||||
Settings.readFromPersistentStorage(context);
|
||||
// Settings.initializeSettings(context, false);
|
||||
Settings.hasServiceBeenRunning = state;
|
||||
Settings.writeSettings(context);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
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.Trigger.Trigger_Enum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class PhoneStatusListener implements AutomationListenerInterface
|
||||
{
|
||||
protected static int currentStateIncoming = -1;
|
||||
protected static int currentStateOutgoing = -1;
|
||||
protected static String lastPhoneNumber="";
|
||||
protected static int lastPhoneDirection = -1; //0=incoming, 1=outgoing
|
||||
|
||||
protected static boolean incomingCallsReceiverActive = false;
|
||||
protected static boolean outgoingCallsReceiverActive = false;
|
||||
|
||||
protected static IntentFilter outgoingCallsIntentFilter;
|
||||
protected static IncomingCallsReceiver incomingCallsReceiverInstance;
|
||||
protected static BroadcastReceiver outgoingCallsReceiverInstance;
|
||||
|
||||
|
||||
public static boolean isIncomingCallsReceiverActive()
|
||||
{
|
||||
return incomingCallsReceiverActive;
|
||||
}
|
||||
|
||||
public static boolean isOutgoingCallsReceiverActive()
|
||||
{
|
||||
return outgoingCallsReceiverActive;
|
||||
}
|
||||
|
||||
protected static boolean receivedInitialIncomingSignal = false;
|
||||
|
||||
public static int getLastPhoneDirection()
|
||||
{
|
||||
return lastPhoneDirection;
|
||||
}
|
||||
|
||||
protected static void setLastPhoneNumber(String lastPhoneNumber)
|
||||
{
|
||||
PhoneStatusListener.lastPhoneNumber = lastPhoneNumber;
|
||||
}
|
||||
|
||||
public static String getLastPhoneNumber()
|
||||
{
|
||||
return lastPhoneNumber;
|
||||
}
|
||||
|
||||
public static class IncomingCallsReceiver extends PhoneStateListener
|
||||
{
|
||||
@Override
|
||||
public void onCallStateChanged(int state, String incomingNumber)
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "Call state", "New call state: " + String.valueOf(state), 4);
|
||||
|
||||
if(incomingNumber != null && incomingNumber.length() > 0) // check for null in case call comes in with suppressed number.
|
||||
setLastPhoneNumber(incomingNumber);
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case TelephonyManager.CALL_STATE_IDLE:
|
||||
Miscellaneous.logEvent("i", "Call state", "New call state: CALL_STATE_IDLE", 4);
|
||||
if(currentStateIncoming == TelephonyManager.CALL_STATE_OFFHOOK)
|
||||
setCurrentStateIncoming(state);
|
||||
else if(currentStateOutgoing == TelephonyManager.CALL_STATE_OFFHOOK)
|
||||
setCurrentStateOutgoing(state);
|
||||
else
|
||||
currentStateIncoming = state;
|
||||
currentStateOutgoing = state;
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||
Miscellaneous.logEvent("i", "Call state", "New call state: CALL_STATE_OFFHOOK", 4);
|
||||
if(currentStateIncoming == TelephonyManager.CALL_STATE_RINGING)
|
||||
setCurrentStateIncoming(state);
|
||||
else if(currentStateOutgoing == TelephonyManager.CALL_STATE_RINGING)
|
||||
setCurrentStateOutgoing(state);
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_RINGING:
|
||||
String number = "unknown";
|
||||
if(incomingNumber != null && incomingNumber.length() > 0)
|
||||
number = incomingNumber;
|
||||
Miscellaneous.logEvent("i", "Call state", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.incomingCallFrom), number), 4);
|
||||
|
||||
setCurrentStateIncoming(state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class OutgoingCallsReceiver extends BroadcastReceiver
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
setCurrentStateOutgoing(2);
|
||||
setLastPhoneNumber(intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
|
||||
Miscellaneous.logEvent("i", "Call state", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.outgoingCallFrom), getLastPhoneNumber()), 4);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isInACall()
|
||||
{
|
||||
if(isInIncomingCall() | isInOutgoingCall())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isInIncomingCall()
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "Incoming call state", String.valueOf(currentStateIncoming), 5);
|
||||
switch(currentStateIncoming)
|
||||
{
|
||||
// case -1:
|
||||
// return false;
|
||||
// case 0:
|
||||
// return false;
|
||||
// case 1:
|
||||
// return true;
|
||||
case 2:
|
||||
return true;
|
||||
// case 3:
|
||||
// return true;
|
||||
// case 4:
|
||||
// return true;
|
||||
// default:
|
||||
// return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isInOutgoingCall()
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "Outgoing call state", String.valueOf(currentStateOutgoing), 5);
|
||||
switch(currentStateOutgoing)
|
||||
{
|
||||
// case -1:
|
||||
// return false;
|
||||
// case 0:
|
||||
// return false;
|
||||
// case 1:
|
||||
// return true;
|
||||
case 2:
|
||||
return true;
|
||||
// case 3:
|
||||
// return true;
|
||||
// case 4:
|
||||
// return true;
|
||||
// default:
|
||||
// return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void setCurrentStateIncoming(int state)
|
||||
{
|
||||
// Miscellaneous.logEvent("i", "Call state", "New incoming call state: " + String.valueOf(state), 4);
|
||||
if(currentStateIncoming != state)
|
||||
{
|
||||
if(lastPhoneDirection != 1)
|
||||
lastPhoneDirection = 1;
|
||||
|
||||
if(
|
||||
(state == 0 && currentStateIncoming == 2)
|
||||
|
|
||||
(state == 2 && (currentStateIncoming == 0 | currentStateIncoming == 1))
|
||||
)
|
||||
{
|
||||
currentStateIncoming = state;
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByPhoneCall(isInIncomingCall());
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
AutomationService asInstance = AutomationService.getInstance();
|
||||
if(asInstance != null)
|
||||
if(ruleCandidates.get(i).applies(asInstance))
|
||||
ruleCandidates.get(i).activate(asInstance, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
currentStateIncoming = state;
|
||||
}
|
||||
}
|
||||
public static int getCurrentStateIncoming()
|
||||
{
|
||||
return currentStateIncoming;
|
||||
}
|
||||
|
||||
public static void setCurrentStateOutgoing(int state)
|
||||
{
|
||||
if(currentStateOutgoing != state)
|
||||
{
|
||||
if(lastPhoneDirection != 2)
|
||||
lastPhoneDirection = 2;
|
||||
|
||||
if(
|
||||
(state == 0 && currentStateOutgoing == 2)
|
||||
|
|
||||
(state == 2 && (currentStateOutgoing == 0 | currentStateOutgoing == 1)))
|
||||
{
|
||||
PhoneStatusListener.currentStateOutgoing = state;
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByPhoneCall(isInOutgoingCall());
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
AutomationService asInstance = AutomationService.getInstance();
|
||||
if(asInstance != null)
|
||||
if(ruleCandidates.get(i).applies(asInstance))
|
||||
ruleCandidates.get(i).activate(asInstance, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
PhoneStatusListener.currentStateOutgoing = state;
|
||||
}
|
||||
}
|
||||
public static int getCurrentStateOutgoing()
|
||||
{
|
||||
return currentStateOutgoing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void startPhoneStatusListener(AutomationService automationService)
|
||||
{
|
||||
if(outgoingCallsIntentFilter == null)
|
||||
{
|
||||
outgoingCallsIntentFilter = new IntentFilter();
|
||||
outgoingCallsIntentFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
|
||||
}
|
||||
|
||||
if(incomingCallsReceiverInstance == null)
|
||||
incomingCallsReceiverInstance = new IncomingCallsReceiver();
|
||||
|
||||
if(outgoingCallsReceiverInstance == null)
|
||||
outgoingCallsReceiverInstance = new OutgoingCallsReceiver();
|
||||
|
||||
try
|
||||
{
|
||||
if(!incomingCallsReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "PhoneStatusListener", "Starting PhoneStatusListener->incomingCallsReceiver", 4);
|
||||
TelephonyManager tm = (TelephonyManager)automationService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
tm.listen(incomingCallsReceiverInstance, PhoneStateListener.LISTEN_CALL_STATE);
|
||||
incomingCallsReceiverActive = true;
|
||||
}
|
||||
|
||||
if(!outgoingCallsReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "PhoneStatusListener", "Starting PhoneStatusListener->outgoingCallsReceiver", 4);
|
||||
automationService.registerReceiver(outgoingCallsReceiverInstance, outgoingCallsIntentFilter);
|
||||
outgoingCallsReceiverActive = true;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "PhoneStatusListener", "Error starting PhoneStatusListener: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopPhoneStatusListener(AutomationService automationService)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(incomingCallsReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "PhoneStatusListener", "Stopping phoneStatusListener", 4);
|
||||
TelephonyManager tm = (TelephonyManager)automationService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
tm.listen(incomingCallsReceiverInstance, PhoneStateListener.LISTEN_NONE);
|
||||
incomingCallsReceiverActive = false;
|
||||
}
|
||||
|
||||
if(outgoingCallsReceiverActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "PhoneStatusListener", "Stopping phoneStatusListener", 4);
|
||||
automationService.unregisterReceiver(outgoingCallsReceiverInstance);
|
||||
outgoingCallsReceiverActive = false;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "PhoneStatusListener", "Error stopping phoneStatusListener: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
PhoneStatusListener.startPhoneStatusListener(automationService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
PhoneStatusListener.stopPhoneStatusListener(automationService);
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return
|
||||
ActivityPermissions.havePermission("android.permission.READ_PHONE_STATE", Miscellaneous.getAnyContext())
|
||||
&&
|
||||
ActivityPermissions.havePermission(ActivityPermissions.permissionNameCall, Miscellaneous.getAnyContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return PhoneStatusListener.incomingCallsReceiverActive | PhoneStatusListener.isOutgoingCallsReceiverActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return new Trigger_Enum[] { Trigger_Enum.phoneCall };
|
||||
}
|
||||
}
|
@ -0,0 +1,470 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningAppProcessInfo;
|
||||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
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.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class ProcessListener implements AutomationListenerInterface
|
||||
{
|
||||
private static ArrayList<String> runningAppsList1 = new ArrayList<String>();
|
||||
private static ArrayList<String> runningAppsList2 = new ArrayList<String>();
|
||||
private static int lastWritten = 2;
|
||||
private static int runCounter = 0;
|
||||
private static AutomationService automationService;
|
||||
private static boolean isMonitoringActive = false;
|
||||
private static boolean isTimerActive = false;
|
||||
private static ArrayList<RunningAppProcessInfo> runningAppProcessInfoList;
|
||||
private static ProcessListenerMonitoring listener = null;
|
||||
|
||||
public static boolean isProcessListenerActive()
|
||||
{
|
||||
return isMonitoringActive;
|
||||
}
|
||||
|
||||
private static Handler workHandler = new Handler()
|
||||
{
|
||||
@Override
|
||||
public void handleMessage(Message msg)
|
||||
{
|
||||
// try
|
||||
// {
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.messageReceivedStatingProcessMonitoringIsComplete), 5);
|
||||
// This will take care of results delivered by the actual monitoring instance
|
||||
|
||||
for(String entry : getRunningApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.runningApp), entry, 5);
|
||||
|
||||
// execute matching rules containing processes
|
||||
if(getRecentlyStartedApps().size()>0 | getRecentlyStoppedApps().size()>0)
|
||||
{
|
||||
for(String entry : getRecentlyStartedApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStarted), entry, 3);
|
||||
for(String entry : getRecentlyStoppedApps())
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStopped), entry, 3);
|
||||
|
||||
ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByProcess();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(automationService))
|
||||
ruleCandidates.get(i).activate(automationService, false);
|
||||
}
|
||||
}
|
||||
// }
|
||||
// catch(Exception e)
|
||||
// {
|
||||
// Miscellaneous.logEvent("e", "Noise level", "Error in workHandler->handleMessage(): " + e.getMessage());
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
public static ArrayList<String> getRunningApps()
|
||||
{
|
||||
if(runningAppsList1.size() == 0 && runningAppsList2.size() == 0)
|
||||
ProcessListenerMonitoring.refreshRunningAppsList();
|
||||
|
||||
ArrayList<String> runningAppsListReference;
|
||||
|
||||
if(lastWritten == 1)
|
||||
{
|
||||
runningAppsListReference = runningAppsList1;
|
||||
}
|
||||
else
|
||||
{
|
||||
runningAppsListReference = runningAppsList2;
|
||||
}
|
||||
|
||||
return runningAppsListReference;
|
||||
}
|
||||
|
||||
public static ArrayList<String> getRecentlyStartedApps()
|
||||
{
|
||||
ArrayList<String> returnList = new ArrayList<String>();
|
||||
|
||||
if(runCounter == 0) // Nothing ever happened.
|
||||
return returnList;
|
||||
|
||||
if(runCounter == 1)
|
||||
// Only one run so far, all running apps are considered to have just started.
|
||||
return runningAppsList1;
|
||||
|
||||
ArrayList<String> oldOne = null, newOne = null;
|
||||
if(lastWritten == 1)
|
||||
{
|
||||
oldOne = runningAppsList2;
|
||||
newOne = runningAppsList1;
|
||||
}
|
||||
else if(lastWritten == 2)
|
||||
{
|
||||
oldOne = runningAppsList1;
|
||||
newOne = runningAppsList2;
|
||||
}
|
||||
|
||||
for(String runningApp : newOne)
|
||||
{
|
||||
if(!oldOne.contains(runningApp))
|
||||
//Started
|
||||
returnList.add(runningApp);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public static ArrayList<String> getRecentlyStoppedApps()
|
||||
{
|
||||
ArrayList<String> returnList = new ArrayList<String>();
|
||||
|
||||
if(runCounter == 1) // Nothing ever happened.
|
||||
return returnList;
|
||||
|
||||
if(runCounter == 1)
|
||||
// Only one run so far, all running apps are considered to have just started, so return empty list.
|
||||
return returnList;
|
||||
|
||||
ArrayList<String> oldOne = null, newOne = null;
|
||||
if(lastWritten == 1)
|
||||
{
|
||||
oldOne = runningAppsList2;
|
||||
newOne = runningAppsList1;
|
||||
}
|
||||
else if(lastWritten == 2)
|
||||
{
|
||||
oldOne = runningAppsList1;
|
||||
newOne = runningAppsList2;
|
||||
}
|
||||
|
||||
for(String runningApp : oldOne)
|
||||
{
|
||||
if(!newOne.contains(runningApp))
|
||||
//Stopped
|
||||
returnList.add(runningApp);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private static boolean stopRequested = false;
|
||||
private static Handler schedulingHandler = new Handler()
|
||||
{
|
||||
@Override
|
||||
public void handleMessage(Message msg)
|
||||
{
|
||||
// try
|
||||
// {
|
||||
if(msg.arg1 == 1)
|
||||
{
|
||||
if(!stopRequested)
|
||||
{
|
||||
listener = new ProcessListenerMonitoring();
|
||||
listener.doMonitoring();
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.rearmingProcessMonitoringMessage), 5);
|
||||
Message message = new Message();
|
||||
message.arg1 = 1;
|
||||
schedulingHandler.sendMessageDelayed(message, Settings.timeBetweenProcessMonitorings * 1000);
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.notRearmingProcessMonitoringMessageStopRequested), 5);
|
||||
}
|
||||
// }
|
||||
// catch(Exception e)
|
||||
// {
|
||||
// Miscellaneous.logEvent("e", "Noise level", "Error in schedulingHandler->handleMessage(): " + e.getMessage());
|
||||
// }
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private static class ProcessListenerMonitoring
|
||||
{
|
||||
Thread monitoringThread;
|
||||
|
||||
public void doMonitoring()
|
||||
{
|
||||
monitoringThread = new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isMonitoringActive)
|
||||
{
|
||||
isMonitoringActive = true;
|
||||
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.periodicProcessMonitoringStarted), 5);
|
||||
|
||||
refreshRunningAppsList();
|
||||
|
||||
Message answer = new Message();
|
||||
// Bundle answerBundle = new Bundle();
|
||||
// answer.setData(answerBundle);
|
||||
workHandler.sendMessage(answer);
|
||||
|
||||
//activate rule(s)
|
||||
/*ArrayList<Rule> ruleCandidates = Rule.findRuleCandidatesByProcess();
|
||||
for(int i=0; i<ruleCandidates.size(); i++)
|
||||
{
|
||||
if(ruleCandidates.get(i).applies(automationService))
|
||||
ruleCandidates.get(i).activate(automationService);
|
||||
}*/
|
||||
|
||||
isMonitoringActive = false;
|
||||
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.periodicProcessMonitoringStopped), 5);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
monitoringThread.start();
|
||||
}
|
||||
|
||||
public static void refreshRunningAppsList()
|
||||
{
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processes), automationService.getResources().getString(R.string.refreshingProcessList), 5);
|
||||
|
||||
final ActivityManager activityManager = (ActivityManager)automationService.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
final List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE);
|
||||
|
||||
ArrayList<String> runningAppsListReference;
|
||||
if(lastWritten == 1)
|
||||
{
|
||||
// Log.i("Processes", "Writing var 2");
|
||||
runningAppsListReference = runningAppsList2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log.i("Processes", "Writing var 1");
|
||||
runningAppsListReference = runningAppsList1;
|
||||
}
|
||||
|
||||
runningAppsListReference.clear();
|
||||
|
||||
for (int i = 0; i < services.size(); i++)
|
||||
{
|
||||
if(!runningAppsListReference.contains(services.get(i).baseActivity.getClassName()))
|
||||
{
|
||||
// you may broadcast a new application launch here.
|
||||
runningAppsListReference.add(services.get(i).baseActivity.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
// for(String runningApp : runningAppsListReference)
|
||||
// {
|
||||
// Miscellaneous.logEvent("i", "Running app", runningApp, 5);
|
||||
// }
|
||||
|
||||
// List<RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
|
||||
// for(int i = 0; i < procInfos.size(); i++)
|
||||
// {
|
||||
// ArrayList<String> runningPkgs = new ArrayList<String>(Arrays.asList(procInfos.get(i).pkgList));
|
||||
//
|
||||
// Collection diff = subtractSets(runningPkgs, stalkList);
|
||||
//
|
||||
// if(diff != null)
|
||||
// {
|
||||
// stalkList.removeAll(diff);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set marker to the one to be written next.
|
||||
if(lastWritten == 1)
|
||||
lastWritten = 2;
|
||||
else if(lastWritten == 2)
|
||||
lastWritten = 1;
|
||||
else
|
||||
lastWritten = -1;
|
||||
|
||||
if(runCounter == 0 | runCounter == 1)
|
||||
runCounter++;
|
||||
}
|
||||
|
||||
public void interrupt()
|
||||
{
|
||||
monitoringThread.interrupt();
|
||||
}
|
||||
|
||||
private RunningAppProcessInfo getForegroundApp()
|
||||
{
|
||||
RunningAppProcessInfo result = null, info = null;
|
||||
|
||||
final ActivityManager activityManager = (ActivityManager)automationService.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
|
||||
List <RunningAppProcessInfo> l = activityManager.getRunningAppProcesses();
|
||||
Iterator <RunningAppProcessInfo> i = l.iterator();
|
||||
while(i.hasNext())
|
||||
{
|
||||
info = i.next();
|
||||
if(info.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
|
||||
&& !isRunningService(info.processName))
|
||||
{
|
||||
result = info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isRunningService(String processName)
|
||||
{
|
||||
if(processName == null)
|
||||
return false;
|
||||
|
||||
RunningServiceInfo service;
|
||||
|
||||
final ActivityManager activityManager = (ActivityManager)automationService.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
|
||||
List <RunningServiceInfo> l = activityManager.getRunningServices(9999);
|
||||
Iterator <RunningServiceInfo> i = l.iterator();
|
||||
while(i.hasNext())
|
||||
{
|
||||
service = i.next();
|
||||
if(service.process.equals(processName))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isRunningApp(String processName)
|
||||
{
|
||||
if(processName == null)
|
||||
return false;
|
||||
|
||||
RunningAppProcessInfo app;
|
||||
|
||||
final ActivityManager activityManager = (ActivityManager)automationService.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
|
||||
List <RunningAppProcessInfo> l = activityManager.getRunningAppProcesses();
|
||||
Iterator <RunningAppProcessInfo> i = l.iterator();
|
||||
while(i.hasNext())
|
||||
{
|
||||
app = i.next();
|
||||
if(app.processName.equals(processName) && app.importance != RunningAppProcessInfo.IMPORTANCE_SERVICE)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkifThisIsActive(RunningAppProcessInfo target)
|
||||
{
|
||||
boolean result = false;
|
||||
RunningTaskInfo info;
|
||||
|
||||
if(target == null)
|
||||
return false;
|
||||
|
||||
final ActivityManager activityManager = (ActivityManager)automationService.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
|
||||
List <RunningTaskInfo> l = activityManager.getRunningTasks(9999);
|
||||
Iterator <RunningTaskInfo> i = l.iterator();
|
||||
|
||||
while(i.hasNext())
|
||||
{
|
||||
info=i.next();
|
||||
if(info.baseActivity.getPackageName().equals(target.processName))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// what is in b that is not in a ?
|
||||
public static Collection subtractSets(Collection a, Collection b)
|
||||
{
|
||||
Collection result = new ArrayList(b);
|
||||
result.removeAll(a);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static void startProcessListener(AutomationService newAutomationService)
|
||||
{
|
||||
automationService = newAutomationService;
|
||||
|
||||
if(!isTimerActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.startingPeriodicProcessMonitoringEngine), 2);
|
||||
isTimerActive = true;
|
||||
|
||||
Message message = new Message();
|
||||
message.arg1 = 1;
|
||||
// schedulingHandler.sendMessageDelayed(message, Settings.timeBetweenNoiseLevelMeasurements * 1000);
|
||||
schedulingHandler.sendMessageDelayed(message, 10000);
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.periodicProcessMonitoringIsAlreadyRunning), 2);
|
||||
}
|
||||
public static void stopProcessListener(AutomationService newAutomationService)
|
||||
{
|
||||
if(isTimerActive)
|
||||
{
|
||||
stopRequested = true;
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.stoppingPeriodicProcessMonitoringEngine), 2);
|
||||
|
||||
if(schedulingHandler.hasMessages(1))
|
||||
schedulingHandler.removeMessages(1);
|
||||
|
||||
if(listener != null)
|
||||
listener.interrupt();
|
||||
|
||||
isTimerActive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
automationService = newAutomationService;
|
||||
Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.periodicProcessMonitoringIsNotActive), 2);
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<RunningAppProcessInfo> getRunningAppProcessInfo()
|
||||
{
|
||||
return runningAppProcessInfoList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
ProcessListener.startProcessListener(automationService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
ProcessListener.stopProcessListener(automationService);
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return ActivityPermissions.havePermission("android.permission.GET_TASKS", Miscellaneous.getAnyContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return ProcessListener.isProcessListenerActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return new Trigger_Enum[] { Trigger_Enum.process_started_stopped };
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.R;
|
||||
import com.jens.automation2.Settings;
|
||||
|
||||
public class StartupIntentReceiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
Settings.readFromPersistentStorage(context);
|
||||
|
||||
Miscellaneous.logEvent("i", "Boot event", "Received event: " + intent.getAction(), 5);
|
||||
|
||||
if(Settings.startServiceAtSystemBoot)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Service", context.getResources().getString(R.string.logStartingServiceAtPhoneBoot), 1);
|
||||
// Settings.readFromPersistentStorage(context);
|
||||
AutomationService.startAutomationService(context, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("i", "Service", context.getResources().getString(R.string.logNotStartingServiceAtPhoneBoot), 2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package com.jens.automation2.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jens.automation2.AutomationService;
|
||||
import com.jens.automation2.Miscellaneous;
|
||||
import com.jens.automation2.Rule;
|
||||
import com.jens.automation2.Trigger.Trigger_Enum;
|
||||
|
||||
public class TimeZoneListener extends BroadcastReceiver implements AutomationListenerInterface
|
||||
{
|
||||
private static TimeZoneListener timeZoneListenerInstance = null;
|
||||
protected static boolean timeZoneListenerActive = false;
|
||||
protected static AutomationService automationServiceRef = null;
|
||||
protected static IntentFilter timeZoneListenerIntentFilter = null;
|
||||
|
||||
|
||||
public static boolean isTimeZoneListenerActive()
|
||||
{
|
||||
return timeZoneListenerActive;
|
||||
}
|
||||
|
||||
public static void startTimeZoneListener(AutomationService automationService)
|
||||
{
|
||||
if(timeZoneListenerInstance == null)
|
||||
timeZoneListenerInstance = new TimeZoneListener();
|
||||
|
||||
automationServiceRef = automationService;
|
||||
|
||||
try
|
||||
{
|
||||
if(!timeZoneListenerActive && Rule.isAnyRuleUsing(Trigger_Enum.timeFrame))
|
||||
{
|
||||
Miscellaneous.logEvent("i", "TimeZoneListener", "Starting TimeZoneListener", 4);
|
||||
timeZoneListenerActive = true;
|
||||
|
||||
if(timeZoneListenerIntentFilter == null)
|
||||
{
|
||||
timeZoneListenerIntentFilter = new IntentFilter();
|
||||
timeZoneListenerIntentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
||||
timeZoneListenerIntentFilter.addAction(Intent.ACTION_TIME_CHANGED);
|
||||
}
|
||||
|
||||
automationService.registerReceiver(timeZoneListenerInstance, timeZoneListenerIntentFilter);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "TimeZoneListener", "Error starting TimeZoneListener: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
public static void stopTimeZoneListener()
|
||||
{
|
||||
try
|
||||
{
|
||||
if(timeZoneListenerActive)
|
||||
{
|
||||
Miscellaneous.logEvent("i", "TimeZoneListener", "Stopping TimeZoneListener", 4);
|
||||
automationServiceRef.unregisterReceiver(timeZoneListenerInstance);
|
||||
timeZoneListenerActive = false;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Miscellaneous.logEvent("e", "TimeZoneListener", "Error stopping TimeZoneListener: " + Log.getStackTraceString(ex), 3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
String action = intent.getAction();
|
||||
if(action.equals(Intent.ACTION_TIMEZONE_CHANGED))
|
||||
{
|
||||
Miscellaneous.logEvent("i", "TimeZoneListener", "Device timezone changed. Reloading alarms.", 3);
|
||||
AlarmListener.reloadAlarms();
|
||||
}
|
||||
else if(action.equals(Intent.ACTION_TIME_CHANGED))
|
||||
{
|
||||
Miscellaneous.logEvent("i", "TimeZoneListener", "Device time changed. Reloading alarms.", 4);
|
||||
AlarmListener.reloadAlarms();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void startListener(AutomationService automationService)
|
||||
{
|
||||
TimeZoneListener.startTimeZoneListener(automationService);
|
||||
}
|
||||
@Override
|
||||
public void stopListener(AutomationService automationService)
|
||||
{
|
||||
TimeZoneListener.stopTimeZoneListener();
|
||||
}
|
||||
|
||||
public static boolean haveAllPermission()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerRunning()
|
||||
{
|
||||
return TimeZoneListener.isTimeZoneListenerActive();
|
||||
}
|
||||
@Override
|
||||
public Trigger_Enum[] getMonitoredTrigger()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user