diff --git a/app/src/apkFlavor/AndroidManifest.xml b/app/src/apkFlavor/AndroidManifest.xml index 05a50201..b56de5a9 100644 --- a/app/src/apkFlavor/AndroidManifest.xml +++ b/app/src/apkFlavor/AndroidManifest.xml @@ -66,7 +66,6 @@ - - - - - - - - - - @@ -170,6 +157,7 @@ + diff --git a/app/src/fdroidFlavor/AndroidManifest.xml b/app/src/fdroidFlavor/AndroidManifest.xml index 599b3819..8ff496a6 100644 --- a/app/src/fdroidFlavor/AndroidManifest.xml +++ b/app/src/fdroidFlavor/AndroidManifest.xml @@ -155,6 +155,7 @@ + diff --git a/app/src/googlePlayFlavor/AndroidManifest.xml b/app/src/googlePlayFlavor/AndroidManifest.xml index 0ad5f67b..c0b847a3 100644 --- a/app/src/googlePlayFlavor/AndroidManifest.xml +++ b/app/src/googlePlayFlavor/AndroidManifest.xml @@ -149,6 +149,7 @@ + diff --git a/app/src/main/java/com/jens/automation2/Action.java b/app/src/main/java/com/jens/automation2/Action.java index 9dab1066..449f9ec7 100644 --- a/app/src/main/java/com/jens/automation2/Action.java +++ b/app/src/main/java/com/jens/automation2/Action.java @@ -18,7 +18,7 @@ public class Action Rule parentRule = null; public static final String actionParameter2Split = "ap2split"; - public static final String intentPairSeperator = "intPairSplit"; + public static final String intentPairSeparator = "intPairSplit"; public static final String vibrateSeparator = ","; public enum Action_Enum { @@ -42,7 +42,7 @@ public class Action setDataConnection, speakText, playMusic, - controlMediaPlayback, + controlMediaPlayback, setScreenBrightness, playSound, vibrate, @@ -277,7 +277,7 @@ public class Action } else if (this.getAction().equals(Action_Enum.startOtherActivity)) { - returnString.append(": " + parameter2.replace(Action.intentPairSeperator, "/")); + returnString.append(": " + parameter2.replace(Action.intentPairSeparator, "/")); } else if (this.getAction().equals(Action_Enum.sendTextMessage)) { diff --git a/app/src/main/java/com/jens/automation2/Actions.java b/app/src/main/java/com/jens/automation2/Actions.java index 3454deb3..9d494eaf 100644 --- a/app/src/main/java/com/jens/automation2/Actions.java +++ b/app/src/main/java/com/jens/automation2/Actions.java @@ -1036,7 +1036,7 @@ public class Actions // Pack intents for (int i = 3; i < params.length; i++) { - String[] singleParam = params[i].split(Action.intentPairSeperator); + String[] singleParam = params[i].split(Action.intentPairSeparator); /*Class c = Class.forName(singleParam[0]); for(Method m : c.getMethods()) @@ -1493,16 +1493,7 @@ public class Actions break; } -// AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); -// if (mAudioManager.isMusicActive()) -// { -// if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) -// return controlMediaPlaybackFromApi21(keyCode); -// else -// { - return controlMediaByDispatch(keyCode); -// return controlMediaPlaybackByBroadcast(keyCode); -// } + return controlMediaByDispatch(keyCode); } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @@ -1515,63 +1506,6 @@ public class Actions return true; } - static boolean controlMediaPlaybackByBroadcast(int keyCode) - { - KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); - Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); - intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); - context.sendOrderedBroadcast(intent, null); - - keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode); - intent = new Intent(Intent.ACTION_MEDIA_BUTTON); - intent.putExtra(Intent.EXTRA_KEY_EVENT, keyCode); - - context.sendOrderedBroadcast(intent, null); - AutomationService.getInstance().sendBroadcast(intent); - - return true; - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - static boolean controlMediaPlaybackFromApi21(int keyCode) - { - KeyEvent keyEvent_down = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); - KeyEvent keyEvent_up = new KeyEvent(KeyEvent.ACTION_UP, keyCode); - - ComponentName myNotificationListenerComponent = new ComponentName(context, MediaControlHelperNotificationListenerService.class); - MediaSessionManager mediaSessionManager = ((MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE)); - - if (mediaSessionManager == null) - { - Log.e("controlMedia", "MediaSessionManager is null."); - return false; - } - - List activeSessions = mediaSessionManager.getActiveSessions(myNotificationListenerComponent); - if (activeSessions.size() > 0) - { - MediaController mediaController = activeSessions.get(0); - mediaController.dispatchMediaButtonEvent(keyEvent_down); - mediaController.dispatchMediaButtonEvent(keyEvent_up); - } - - return true; - } - - @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) - public static class MediaControlHelperNotificationListenerService extends NotificationListenerService - { - @Override - public void onNotificationPosted(StatusBarNotification sbn) { - super.onNotificationPosted(sbn); - } - - @Override - public void onNotificationRemoved(StatusBarNotification sbn) { - super.onNotificationRemoved(sbn); - } - } - private String getTransactionCode() { try diff --git a/app/src/main/java/com/jens/automation2/ActivityControlCenter.java b/app/src/main/java/com/jens/automation2/ActivityControlCenter.java index d0bf29d7..04cb1c33 100644 --- a/app/src/main/java/com/jens/automation2/ActivityControlCenter.java +++ b/app/src/main/java/com/jens/automation2/ActivityControlCenter.java @@ -21,6 +21,7 @@ import org.apache.commons.lang3.StringUtils; import java.io.File; import java.util.ArrayList; +import java.util.Locale; public class ActivityControlCenter extends Activity { @@ -347,7 +348,24 @@ public class ActivityControlCenter extends Activity systemInfoText.append("Device: " + android.os.Build.DEVICE + Miscellaneous.lineSeparator); systemInfoText.append("Model: " + android.os.Build.MODEL + Miscellaneous.lineSeparator); systemInfoText.append("Product: " + android.os.Build.PRODUCT + Miscellaneous.lineSeparator); - systemInfoText.append("Flavor: " + BuildConfig.FLAVOR); + systemInfoText.append("Flavor: " + BuildConfig.FLAVOR + Miscellaneous.lineSeparator); + systemInfoText.append("Country: " + Miscellaneous.getUserCountry(Miscellaneous.getAnyContext()) + Miscellaneous.lineSeparator); + systemInfoText.append("OS language: " + Locale.getDefault().getDisplayName()); + + /* + I've checked the Locale methods on my Android 4.1.2 device, and the results: + + Locale.getDefault().getLanguage() ---> en + Locale.getDefault().getISO3Language() ---> eng + Locale.getDefault().getCountry() ---> US + Locale.getDefault().getISO3Country() ---> USA + Locale.getDefault().getDisplayCountry() ---> United States + Locale.getDefault().getDisplayName() ---> English (United States) + Locale.getDefault().toString() ---> en_US + Locale.getDefault().getDisplayLanguage()---> English + Locale.getDefault().toLanguageTag() ---> en-US + */ + return systemInfoText.toString(); } diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionControlMedia.java b/app/src/main/java/com/jens/automation2/ActivityManageActionControlMedia.java new file mode 100644 index 00000000..9a86dc6c --- /dev/null +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionControlMedia.java @@ -0,0 +1,112 @@ +package com.jens.automation2; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.RadioButton; +import android.widget.Toast; + +import androidx.annotation.Nullable; + +public class ActivityManageActionControlMedia extends Activity +{ + RadioButton rbMediaPlayPause, rbMediaPlay, rbMediaPause, rbMediaStop, rbMediaPrevious, rbMediaNext; + Button bSaveControlMediaAction; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_manage_action_control_media); + + rbMediaPlayPause = (RadioButton)findViewById(R.id.rbMediaPlayPause); + rbMediaPlay = (RadioButton)findViewById(R.id.rbMediaPlay); + rbMediaPause = (RadioButton)findViewById(R.id.rbMediaPause); + rbMediaStop = (RadioButton)findViewById(R.id.rbMediaStop); + rbMediaPrevious = (RadioButton)findViewById(R.id.rbMediaPrevious); + rbMediaNext = (RadioButton)findViewById(R.id.rbMediaNext); + + bSaveControlMediaAction = (Button)findViewById(R.id.bSaveControlMediaAction); + + bSaveControlMediaAction.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View view) + { + if(checkInput()) + { + Intent answer = new Intent(); + + if(rbMediaPlayPause.isChecked()) + answer.putExtra(ActivityManageRule.intentNameActionParameter2, "0"); + else if(rbMediaPlay.isChecked()) + answer.putExtra(ActivityManageRule.intentNameActionParameter2, "1"); + else if(rbMediaPause.isChecked()) + answer.putExtra(ActivityManageRule.intentNameActionParameter2, "2"); + else if(rbMediaStop.isChecked()) + answer.putExtra(ActivityManageRule.intentNameActionParameter2, "3"); + else if(rbMediaPrevious.isChecked()) + answer.putExtra(ActivityManageRule.intentNameActionParameter2, "4"); + else if(rbMediaNext.isChecked()) + answer.putExtra(ActivityManageRule.intentNameActionParameter2, "5"); + + setResult(RESULT_OK, answer); + finish(); + } + } + }); + + Intent input = getIntent(); + + if(input.hasExtra(ActivityManageRule.intentNameActionParameter2)) + { + String existing = input.getStringExtra(ActivityManageRule.intentNameActionParameter2); + switch (existing) + { + case "0": + rbMediaPlayPause.setChecked(true); + break; + case "1": + rbMediaPlay.setChecked(true); + break; + case "2": + rbMediaPause.setChecked(true); + break; + case "3": + rbMediaStop.setChecked(true); + break; + case "4": + rbMediaPrevious.setChecked(true); + break; + case "5": + rbMediaNext.setChecked(true); + break; + } + } + } + + boolean checkInput() + { + if( + !rbMediaPlayPause.isChecked() + && + !rbMediaPlay.isChecked() + && + !rbMediaPause.isChecked() + && + !rbMediaStop.isChecked() + && + !rbMediaPrevious.isChecked() + && + !rbMediaNext.isChecked() + ) + { + Toast.makeText(ActivityManageActionControlMedia.this, getResources().getString(R.string.pleaseSelectActionValue), Toast.LENGTH_SHORT).show(); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java b/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java index 2e4b4916..8d6492f2 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageActionStartActivity.java @@ -387,9 +387,9 @@ public class ActivityManageActionStartActivity extends Activity Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterNameForIntentPair), Toast.LENGTH_LONG).show(); return; } - else if(etParameterName.getText().toString().contains(Action.intentPairSeperator)) + else if(etParameterName.getText().toString().contains(Action.intentPairSeparator)) { - Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show(); + Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); return; } else if(etParameterName.getText().toString().contains(";")) @@ -403,9 +403,9 @@ public class ActivityManageActionStartActivity extends Activity Toast.makeText(ActivityManageActionStartActivity.this, getResources().getString(R.string.enterValueForIntentPair), Toast.LENGTH_LONG).show(); return; } - else if(etParameterValue.getText().toString().contains(Action.intentPairSeperator)) + else if(etParameterValue.getText().toString().contains(Action.intentPairSeparator)) { - Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeperator), Toast.LENGTH_LONG).show(); + Toast.makeText(ActivityManageActionStartActivity.this, String.format(getResources().getString(R.string.stringNotAllowed), Action.intentPairSeparator), Toast.LENGTH_LONG).show(); return; } else if(etParameterValue.getText().toString().contains(";")) @@ -414,7 +414,7 @@ public class ActivityManageActionStartActivity extends Activity return; } - String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeperator + etParameterName.getText().toString() + Action.intentPairSeperator + etParameterValue.getText().toString(); + String param = supportedIntentTypes[spinnerParameterType.getSelectedItemPosition()] + Action.intentPairSeparator + etParameterName.getText().toString() + Action.intentPairSeparator + etParameterValue.getText().toString(); intentPairList.add(param); spinnerParameterType.setSelection(0); diff --git a/app/src/main/java/com/jens/automation2/ActivityManageRule.java b/app/src/main/java/com/jens/automation2/ActivityManageRule.java index da340576..954e6209 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageRule.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageRule.java @@ -116,6 +116,8 @@ public class ActivityManageRule extends Activity final static int requestCodeActionCreateNotificationEdit = 804; final static int requestCodeActionCloseNotificationAdd = 805; final static int requestCodeActionCloseNotificationEdit = 806; + final static int requestCodeActionControlMediaAdd = 807; + final static int requestCodeActionControlMediaEdit = 808; public static ActivityManageRule getInstance() { @@ -363,6 +365,11 @@ public class ActivityManageRule extends Activity activityEditVibrateIntent.putExtra("vibratePattern", a.getParameter2()); startActivityForResult(activityEditVibrateIntent, requestCodeActionVibrateEdit); break; + case controlMediaPlayback: + Intent activityEditControlMediaIntent = new Intent(ActivityManageRule.this, ActivityManageActionControlMedia.class); + activityEditControlMediaIntent.putExtra(ActivityManageRule.intentNameActionParameter2, a.getParameter2()); + startActivityForResult(activityEditControlMediaIntent, requestCodeActionControlMediaEdit); + break; case createNotification: Intent activityEditCreateNotificationIntent = new Intent(ActivityManageRule.this, ActivityManageActionCreateNotification.class); String[] elements = a.getParameter2().split(Action.actionParameter2Split); @@ -1416,6 +1423,16 @@ public class ActivityManageRule extends Activity this.refreshActionList(); } } + else if(requestCode == requestCodeActionControlMediaAdd) + { + if(resultCode == RESULT_OK) + { + newAction.setParentRule(ruleToEdit); + newAction.setParameter2(data.getStringExtra(ActivityManageRule.intentNameActionParameter2)); + ruleToEdit.getActionSet().add(newAction); + this.refreshActionList(); + } + } else if(requestCode == requestCodeActionCreateNotificationAdd) { if(resultCode == RESULT_OK) @@ -1452,6 +1469,18 @@ public class ActivityManageRule extends Activity this.refreshActionList(); } } + else if(requestCode == requestCodeActionControlMediaEdit) + { + if(resultCode == RESULT_OK) + { + ruleToEdit.getActionSet().get(editIndex).setParentRule(ruleToEdit); + + if(data.hasExtra(intentNameActionParameter2)) + ruleToEdit.getActionSet().get(editIndex).setParameter2(data.getStringExtra(intentNameActionParameter2)); + + this.refreshActionList(); + } + } else if(requestCode == requestCodeActionCreateNotificationEdit) { if(resultCode == RESULT_OK) @@ -1782,17 +1811,18 @@ public class ActivityManageRule extends Activity ruleToEdit.getActionSet().add(newAction); refreshActionList(); } - else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.controlMediaPlayback.toString())) - { - newAction.setAction(Action_Enum.controlMediaPlayback); - getActionControlMediaPlayback(ActivityManageRule.this).show(); - } else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.vibrate.toString())) { newAction.setAction(Action_Enum.vibrate); Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionVibrate.class); startActivityForResult(intent, requestCodeActionVibrateAdd); } + else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.controlMediaPlayback.toString())) + { + newAction.setAction(Action_Enum.controlMediaPlayback); + Intent intent = new Intent(ActivityManageRule.this, ActivityManageActionControlMedia.class); + startActivityForResult(intent, requestCodeActionControlMediaAdd); + } else if(Action.getActionTypesAsArray()[which].toString().equals(Action_Enum.createNotification.toString())) { newAction.setAction(Action_Enum.createNotification); @@ -2030,34 +2060,6 @@ public class ActivityManageRule extends Activity return alertDialog; } - private AlertDialog getActionControlMediaPlayback(final Context myContext) - { - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); - alertDialogBuilder.setTitle(myContext.getResources().getString(R.string.selectCommand)); - final String choices[] = { - myContext.getString(R.string.playPause), - myContext.getString(R.string.play), - myContext.getString(R.string.pause), - myContext.getString(R.string.stop), - myContext.getString(R.string.previous), - myContext.getString(R.string.next) - }; - alertDialogBuilder.setItems(choices, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - newAction.setParameter2(String.valueOf(which)); - - ruleToEdit.getActionSet().add(newAction); - refreshActionList(); - } - }); - AlertDialog alertDialog = alertDialogBuilder.create(); - - return alertDialog; - } - protected void refreshTriggerList() { Miscellaneous.logEvent("i", "ListView", "Attempting to update TriggerListView", 4); diff --git a/app/src/main/java/com/jens/automation2/ActivityPermissions.java b/app/src/main/java/com/jens/automation2/ActivityPermissions.java index ce503851..674a074d 100644 --- a/app/src/main/java/com/jens/automation2/ActivityPermissions.java +++ b/app/src/main/java/com/jens/automation2/ActivityPermissions.java @@ -530,7 +530,7 @@ public class ActivityPermissions extends Activity case playMusic: break; case controlMediaPlayback: - addToArrayListUnique(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, requiredPermissions); +// addToArrayListUnique(Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, requiredPermissions); // addToArrayListUnique(Manifest.permission.MEDIA_CONTENT_CONTROL, requiredPermissions); break; case sendTextMessage: diff --git a/app/src/main/java/com/jens/automation2/Miscellaneous.java b/app/src/main/java/com/jens/automation2/Miscellaneous.java index 27b6230f..4886c02b 100644 --- a/app/src/main/java/com/jens/automation2/Miscellaneous.java +++ b/app/src/main/java/com/jens/automation2/Miscellaneous.java @@ -27,6 +27,7 @@ import android.os.IBinder; import android.provider.MediaStore; import android.provider.Settings.Secure; import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; import android.util.Base64; import android.util.Log; import android.widget.Toast; @@ -84,6 +85,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Scanner; import java.util.Set; import java.util.zip.ZipEntry; @@ -1719,4 +1721,37 @@ public class Miscellaneous extends Service { return arraySearch(requestList.toArray(new String[requestList.size()]), needle, caseSensitive, matchFullLine); } + + /** + * Get ISO 3166-1 alpha-2 country code for this device (or null if not available) + * @param context Context reference to get the TelephonyManager instance from + * @return country code or null + */ + public static String getUserCountry(Context context) { + try + { + final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + final String simCountry = tm.getSimCountryIso(); + if (simCountry != null && simCountry.length() == 2) + { // SIM country code is available + return simCountry.toLowerCase(Locale.US); + } + else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) + { // device is not 3G (would be unreliable) + String networkCountry = tm.getNetworkCountryIso(); + if (networkCountry != null && networkCountry.length() == 2) + { // network country code is available + return networkCountry.toLowerCase(Locale.US); + } + } + } + catch (SecurityException se) + { + return "unknown"; + } + catch (Exception e) + { } + + return null; + } } \ No newline at end of file diff --git a/app/src/main/java/com/jens/automation2/XmlFileInterface.java b/app/src/main/java/com/jens/automation2/XmlFileInterface.java index b7d698a2..ba5bec3e 100644 --- a/app/src/main/java/com/jens/automation2/XmlFileInterface.java +++ b/app/src/main/java/com/jens/automation2/XmlFileInterface.java @@ -1284,14 +1284,14 @@ public class XmlFileInterface { String newTag; - if(tag.contains(Action.intentPairSeperator)) // already has new format + if(tag.contains(Action.intentPairSeparator)) // already has new format newTag = tag; else - newTag = tag.replace("/", Action.intentPairSeperator); + newTag = tag.replace("/", Action.intentPairSeparator); String[] newTagPieces = newTag.split(";"); - if(newTagPieces.length < 2 || (!newTagPieces[0].contains(Actions.dummyPackageString) && newTagPieces[1].contains(Action.intentPairSeperator))) + if(newTagPieces.length < 2 || (!newTagPieces[0].contains(Actions.dummyPackageString) && newTagPieces[1].contains(Action.intentPairSeparator))) { newTag = Actions.dummyPackageString + ";" + newTag; newTagPieces = newTag.split(";"); @@ -1301,7 +1301,7 @@ public class XmlFileInterface newTag += ";" + ActivityManageActionStartActivity.startByActivityString; else if(newTagPieces.length >= 3) { - if(newTagPieces[2].contains(Action.intentPairSeperator)) + if(newTagPieces[2].contains(Action.intentPairSeparator)) newTag = newTagPieces[0] + ";" + newTagPieces[1] + ";" + ActivityManageActionStartActivity.startByActivityString + ";" + newTagPieces[2]; } diff --git a/app/src/main/res/layout/activity_manage_action_control_media.xml b/app/src/main/res/layout/activity_manage_action_control_media.xml new file mode 100644 index 00000000..36ae4309 --- /dev/null +++ b/app/src/main/res/layout/activity_manage_action_control_media.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +