diff --git a/CHANGES.txt b/CHANGES.txt index cd1565e..31c3718 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,11 @@ Change log for AWARE-Light +4.1.6.light.bundle +- A crash that occurred when enabling accessibility before starting a study has been fixed. +- The screen text sensor now correctly collects duplicate text when the foreground app changes, ensuring that screen text is captured during app switches, home screen access, and notification checks. +- Fix display issues: long question titles can be displayed completely. +- Fix the ESM queue logic to ensure that the correct number of questions are displayed according to the configurator settings. +- Fix logic of reschedule next day random esm trigger, avoid repeat appear of esm notification. +- A stronger password detection added in ScreenText Sensor 4.1.5.light.bundle - Logging if the application is terminated by user actions or system actions to aware_log table diff --git a/aware-core/aware.gradle b/aware-core/aware.gradle index 73a3cf1..4420726 100644 --- a/aware-core/aware.gradle +++ b/aware-core/aware.gradle @@ -4,7 +4,7 @@ buildscript { mqtt_libs = '1.2.1' ion_libs = "2.+" google_libs = "17.0.0" - version_code = 3 + version_code = 6 version_readable = "4.1." + version_code + "." + "light.bundle" compile_sdk = 28 target_sdk = 28 diff --git a/aware-core/src/main/java/com/aware/Applications.java b/aware-core/src/main/java/com/aware/Applications.java index 36d1256..f0b7f38 100644 --- a/aware-core/src/main/java/com/aware/Applications.java +++ b/aware-core/src/main/java/com/aware/Applications.java @@ -41,8 +41,12 @@ import org.json.JSONException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; + import android.graphics.Rect; /** @@ -95,10 +99,13 @@ public class Applications extends AccessibilityService { ArrayList contentBuffer = new ArrayList(); - ArrayList textBuffer = new ArrayList(); + Set textBuffer = new HashSet<>(); int TEXT_BUFFER_LIMIT = 100; + private String previousForegroundApp = ""; + + private static List sensitiveInputType = Arrays.asList(129, 225, 145); // int mDebugDepth = 0; private static int screenStatus = 0; // ACTION_AWARE_SCREEN_OFF ACTION_AWARE_SCREEN_UNLOCKED @@ -123,10 +130,17 @@ private void textTree(AccessibilityNodeInfo mNodeInfo){ // conditions to filter the meaningless input if (mNodeInfo.getText() != null && !mNodeInfo.getText().toString().equals("")){ Rect rect = new Rect(); + // check is password, check inputtype is (129, ) + String viewId = mNodeInfo.getViewIdResourceName(); + - mNodeInfo.getBoundsInScreen(rect); + if (!mNodeInfo.isPassword() && !sensitiveInputType.contains(mNodeInfo.getInputType())){ + if ((viewId != null && !viewId.matches("(?i).*password.*")) | viewId == null){ + mNodeInfo.getBoundsInScreen(rect); - currScreenText += mNodeInfo.getText() + "***" + rect.toString() + "||"; // Add division sign for the tree + currScreenText += mNodeInfo.getText() + "***" + rect.toString() + "||"; // Add division sign for the tree + } + } } if (mNodeInfo.getChildCount() < 1) return; @@ -168,12 +182,9 @@ private String getApplicationName(String package_name) { public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getPackageName() == null) return; - - - - // if text buffer is full then send all contents in the content buffer - if (textBuffer.size() == TEXT_BUFFER_LIMIT){ - + // if content buffer is full then send all contents in the content buffer + if (contentBuffer.size() == TEXT_BUFFER_LIMIT){ + // Log.d("Screen_Text", "==========LIMIT REACH============"); for (ContentValues content: contentBuffer){ getContentResolver().insert(ScreenText_Provider.ScreenTextData.CONTENT_URI, content); @@ -184,6 +195,8 @@ public void onAccessibilityEvent(AccessibilityEvent event) { } textBuffer.clear(); contentBuffer.clear(); + + // Log.d("Screen_Text", "==========CLEAN BUFFER============"); } @@ -193,7 +206,19 @@ public void onAccessibilityEvent(AccessibilityEvent event) { // 0: only track data of the inclusive packages for screentext function // 1: only track data except the exclusive packages for screentext function // 2: by default track all apps - int criteria = (int) Long.parseLong(Aware.getSetting(getApplicationContext(), Aware_Preferences.PACKAGE_SPECIFICATION)); + + + int criteria = 2; // Default value + + try { + String criteriaSetting = Aware.getSetting(getApplicationContext(), Aware_Preferences.PACKAGE_SPECIFICATION); + if (!criteriaSetting.isEmpty()) { + criteria = Integer.parseInt(criteriaSetting); + } + } catch (NumberFormatException e) { + Log.e("Error", "Failed to parse PACKAGE_SPECIFICATION setting: " + e.getMessage()); + } + if (criteria == 0 || criteria == 1){ String app_names = Aware.getSetting(getApplicationContext(), Aware_Preferences.PACKAGE_NAMES); String curr_app = event.getPackageName().toString(); @@ -208,48 +233,74 @@ else if (criteria == 1 && app_names.contains(curr_app)) { // package in exclusiv if (Aware.getSetting(getApplicationContext(), Aware_Preferences.STATUS_SCREENTEXT).equals("true") && getScreenStatus() == 0) { + // Get the current foreground app + String currentForegroundApp = event.getPackageName().toString(); - // get text tree + // Get text tree AccessibilityNodeInfo mNodeInfo = event.getSource(); textTree(mNodeInfo); - - if (!currScreenText.equals("") && track_screentext && !event.isPassword()) { - + if (!currScreenText.isEmpty() && track_screentext && !event.isPassword()) { ContentValues screenText = new ContentValues(); screenText.put(ScreenText_Provider.ScreenTextData.TIMESTAMP, System.currentTimeMillis()); screenText.put(ScreenText_Provider.ScreenTextData.DEVICE_ID, Aware.getSetting(getApplicationContext(), Aware_Preferences.DEVICE_ID)); - if (event.getPackageName() != null){ + if (event.getPackageName() != null) { screenText.put(ScreenText_Provider.ScreenTextData.PACKAGE_NAME, event.getPackageName().toString()); - } else{ + } else { screenText.put(ScreenText_Provider.ScreenTextData.PACKAGE_NAME, ""); } if (event.getClassName() != null) { screenText.put(ScreenText_Provider.ScreenTextData.CLASS_NAME, event.getClassName().toString()); - } else{ + } else { screenText.put(ScreenText_Provider.ScreenTextData.CLASS_NAME, ""); } - screenText.put(ScreenText_Provider.ScreenTextData.USER_ACTION, event.getAction()); screenText.put(ScreenText_Provider.ScreenTextData.EVENT_TYPE, event.getEventType()); screenText.put(ScreenText_Provider.ScreenTextData.TEXT, currScreenText); int hashedText = currScreenText.hashCode(); - // Add to content: get rid of the duplicate text - if (!textBuffer.contains(hashedText)){ - textBuffer.add(hashedText); - contentBuffer.add(screenText); + // Check if the foreground app has changed + if (!currentForegroundApp.equals(previousForegroundApp)) { +// // Log.d("Screen_Text", "==========App Switch============"); + if (!textBuffer.contains(hashedText)) { + textBuffer.add(hashedText); + contentBuffer.add(screenText); +// // Log.d("Screen_Text", "Add ContentText: " + currScreenText); + } + + + // Log.d("Screen_Text", "Current ContentBuffer Size: " + contentBuffer.size()); -// Log.d(TAG,"Buffer sizeļ¼š" + textBuffer.size()); + for (ContentValues content: contentBuffer){ + getContentResolver().insert(ScreenText_Provider.ScreenTextData.CONTENT_URI, content); + + if (awareSensor != null) awareSensor.onScreentext(content); + Intent screen_text_data = new Intent(ScreenText.ACTION_SCREENTEXT_DETECT); + sendBroadcast(screen_text_data); + } + + textBuffer.clear(); + contentBuffer.clear(); + // Log.d("Screen_Text", "==========CLEAN BUFFER============"); + // Update the previous foreground app + previousForegroundApp = currentForegroundApp; + + } else { + // Add to content: get rid of the duplicate text + if (!textBuffer.contains(hashedText)) { + textBuffer.add(hashedText); + contentBuffer.add(screenText); + // Log.d("Screen_Text", "Add ContentText: " + currScreenText); + } } currScreenText = ""; - } + } diff --git a/aware-core/src/main/java/com/aware/ui/esms/ESM_Checkbox.java b/aware-core/src/main/java/com/aware/ui/esms/ESM_Checkbox.java index 8733be0..abf8bb7 100644 --- a/aware-core/src/main/java/com/aware/ui/esms/ESM_Checkbox.java +++ b/aware-core/src/main/java/com/aware/ui/esms/ESM_Checkbox.java @@ -130,7 +130,6 @@ public void onClick(View v) { final EditText otherText = new EditText(getActivity()); otherText.setHint(getResources().getString(R.string.aware_esm_other_follow)); editor.addView(otherText); - otherText.requestFocus(); editOther.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); Button confirm = new Button(getActivity()); diff --git a/aware-core/src/main/java/com/aware/ui/esms/ESM_Freetext.java b/aware-core/src/main/java/com/aware/ui/esms/ESM_Freetext.java index 3efc08e..85d02aa 100644 --- a/aware-core/src/main/java/com/aware/ui/esms/ESM_Freetext.java +++ b/aware-core/src/main/java/com/aware/ui/esms/ESM_Freetext.java @@ -44,6 +44,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { esm_dialog = builder.create(); esm_dialog.setCanceledOnTouchOutside(false); + try { TextView esm_title = (TextView) ui.findViewById(R.id.esm_title); esm_title.setText(getTitle()); @@ -54,7 +55,6 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { esm_instructions.setMovementMethod(ScrollingMovementMethod.getInstance()); final EditText feedback = (EditText) ui.findViewById(R.id.esm_feedback); - feedback.requestFocus(); feedback.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/aware-core/src/main/java/com/aware/ui/esms/ESM_Number.java b/aware-core/src/main/java/com/aware/ui/esms/ESM_Number.java index d906ce2..8065aec 100644 --- a/aware-core/src/main/java/com/aware/ui/esms/ESM_Number.java +++ b/aware-core/src/main/java/com/aware/ui/esms/ESM_Number.java @@ -54,7 +54,6 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { esm_instructions.setMovementMethod(ScrollingMovementMethod.getInstance()); final EditText feedback = (EditText) ui.findViewById(R.id.esm_feedback); - feedback.requestFocus(); feedback.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/aware-core/src/main/java/com/aware/ui/esms/ESM_Radio.java b/aware-core/src/main/java/com/aware/ui/esms/ESM_Radio.java index 8bb7e37..49d32a9 100644 --- a/aware-core/src/main/java/com/aware/ui/esms/ESM_Radio.java +++ b/aware-core/src/main/java/com/aware/ui/esms/ESM_Radio.java @@ -123,7 +123,6 @@ public void onClick(View v) { final EditText otherText = new EditText(getActivity()); otherText.setHint(getResources().getString(R.string.aware_esm_other_follow)); editor.addView(otherText); - otherText.requestFocus(); editOther.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); Button confirm = new Button(getActivity()); diff --git a/aware-core/src/main/java/com/aware/utils/Scheduler.java b/aware-core/src/main/java/com/aware/utils/Scheduler.java index 3c04506..e8bf677 100644 --- a/aware-core/src/main/java/com/aware/utils/Scheduler.java +++ b/aware-core/src/main/java/com/aware/utils/Scheduler.java @@ -355,20 +355,20 @@ private static void rescheduleRandom(Context context, Schedule schedule) { timer.setTimeInMillis(r); Log.d(TAG, "RANDOM TIME:" + timer.getTime().toString() + "\n"); - - schedule.setTimer(timer); + Schedule newSchedule = new Schedule(schedule); + newSchedule.setTimer(timer); if (r == max) { - schedule.setScheduleID(original_id + "_random_" + r + "_last"); + newSchedule.setScheduleID(original_id + "_random_" + r + "_last"); } else { - schedule.setScheduleID(original_id + "_random_" + r); + newSchedule.setScheduleID(original_id + "_random_" + r); } ContentValues data = new ContentValues(); data.put(Scheduler_Provider.Scheduler_Data.TIMESTAMP, System.currentTimeMillis()); data.put(Scheduler_Provider.Scheduler_Data.DEVICE_ID, Aware.getSetting(context, Aware_Preferences.DEVICE_ID)); - data.put(Scheduler_Provider.Scheduler_Data.SCHEDULE_ID, schedule.getScheduleID()); - data.put(Scheduler_Provider.Scheduler_Data.SCHEDULE, schedule.build().toString()); + data.put(Scheduler_Provider.Scheduler_Data.SCHEDULE_ID, newSchedule.getScheduleID()); + data.put(Scheduler_Provider.Scheduler_Data.SCHEDULE, newSchedule.build().toString()); data.put(Scheduler_Provider.Scheduler_Data.PACKAGE_NAME, context.getPackageName()); Log.d(Scheduler.TAG, "Random schedule: " + data.toString() + "\n"); @@ -1090,7 +1090,7 @@ private void performAction(Schedule schedule) { sendBroadcast(scheduler_action); Aware.debug(this, "Scheduler triggered: " + schedule.getScheduleID() + " schedule: " + schedule.build().toString() + " package: " + getPackageName()); - + Log.d(TAG, "Scheduler triggered: " + schedule.getScheduleID() + " schedule: " + schedule.build().toString() + " package: " + getPackageName()); if (schedule.getActionType().equals(ACTION_TYPE_BROADCAST)) { Intent broadcast = new Intent(schedule.getActionIntentAction()); JSONArray extras = schedule.getActionExtras(); @@ -1185,11 +1185,14 @@ private void performAction(Schedule schedule) { if (schedule.getRandom().length() > 0 && schedule.getScheduleID().contains("_last") && schedule.getScheduleID().contains("_random_")) { //clean-up random strings + String lastScheduleID = schedule.getScheduleID(); String originalScheduleID = schedule.getScheduleID().substring(0, schedule.getScheduleID().indexOf("_random_")); + Log.d(TAG, originalScheduleID + " is this"); schedule.setScheduleID(originalScheduleID); //recreate random scheduler for tomorrow Scheduler.rescheduleRandom(getApplicationContext(), schedule); + schedule.setScheduleID(lastScheduleID); } } @@ -1234,6 +1237,17 @@ public Schedule(String schedule_id) { } } + public Schedule(Schedule schedule) { + try{ + this.schedule = new JSONObject(schedule.schedule.toString()); + this.trigger = new JSONObject(schedule.trigger.toString()); + this.action = new JSONObject(schedule.action.toString()); + } + catch (JSONException e){ + e.printStackTrace(); + }// Deep copy + } + public Schedule(JSONObject schedule) { this.rebuild(schedule); } @@ -1603,6 +1617,7 @@ public JSONArray getContexts() throws JSONException { * @throws JSONException */ public Schedule random(int daily_amount, int minimum_interval) throws JSONException { + Log.i("TEST", "random did work"); JSONObject json_random = getRandom(); json_random.put(RANDOM_TIMES, daily_amount); json_random.put(RANDOM_INTERVAL, minimum_interval); diff --git a/aware-core/src/main/res/layout/esm_checkbox.xml b/aware-core/src/main/res/layout/esm_checkbox.xml index 90cc8da..052b62d 100644 --- a/aware-core/src/main/res/layout/esm_checkbox.xml +++ b/aware-core/src/main/res/layout/esm_checkbox.xml @@ -4,64 +4,76 @@ android:layout_width="match_parent" android:layout_height="wrap_content" > - - - - + android:layout_height="match_parent" + android:fillViewport="true"> - - - + android:layout_height="match_parent" + android:focusable="true" + android:focusableInTouchMode="true" + > - + + + + + -