I am building an accessiblity service for 3-party application using AccessibilityService API. But I don't know how to scroll an accessibilitynodeinfo backward? Can you guys help me out?
node.perform(AccessibilityNodeInfo.ACTION_SCROLL_BACKSCROLL) didn't work.
I believe this is what you want:
void scrollBackward(AccessibilityNodeInfo) throws NotScrollable {
while (node != null) {
if (node.isScrollable()) {
node.performAction(ACTION_SCROLL_BACKWARD);
return;
}
node = node.getParent();
}
throw new NotScrollable("This node cannot be scrolled");
}
Note: I'm on my phone typing this up, so forgive me if this doesn't quite compile. It should be very close.
Related
I am using Google CoreAR package in my React-Native app for AR support. There are some devices which support AR and some not. I am getting error while I run the application in non-supported devices. I want to render a message instead showing error on the screen. For this Google CoreAR package is providing the solution which is not working for me.
void maybeEnableArButton() {
ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this);
if (availability.isTransient()) {
// Continue to query availability at 5Hz while compatibility is checked in the background.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
maybeEnableArButton();
}
}, 200);
}
if (availability.isSupported()) {
mArButton.setVisibility(View.VISIBLE);
mArButton.setEnabled(true);
} else { // The device is unsupported or unknown.
mArButton.setVisibility(View.INVISIBLE);
mArButton.setEnabled(false);
}
}
The problem with above code snippet is that availability.isSupported() is always returning true and that's why else part of code is not running. Can you guys please help me with this?
Thank you.
I found solution for this problem. ArCoreApk.Availability has some methods which can be used. You can find these methods in the
documentation. The method ArCoreApk.Availability
return either SUPPORTED_INSTALLED or SUPPORTED_NOT_INSTALLED depending on device support. So based on this return value we can do the stuff.
I did like this.
#ReactMethod
public ArCoreApk.Availability getSupport(){
ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this.getReactApplicationContext());
return availability.name();
}
I am developing an accessibility service for Android. The service calls an app, and that app has a RecyclerView. Then I want to click on an element of the RecyclerView with performAction(AccessibilityNodeInfo.ACTION_CLICK) but it is not working. I know there are a few similar questions but none of them works for me. Also I checked the official documentation for the class of the performAction method https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo
This is my code:
#Override
public void onAccessibilityEvent(Accessibility event){
AccessibilityNodeInfo source = event.getSource();
if(source != null){
List<AccessibilityNodeInfo> list = source.findAccessibilityNOdeInfosByText("mystring");
list.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
This is my configuration xml file:
<accessibility-srvice xmlns...
android:accessibilityFeedbackType = "feedbackGeneric"
android:AccessibilityFlags = "flagDefault"
android:canPerformGestures = "true"
android:canRetrieveWIndowCOntent = "true"
I think I misunderstood something, but i don't know what can be. Any help is appreciated.
The simple answer is that while finding the node by text is fine, that particular node was not the node with the desired onClick event. The solution is to call
list.get(0).getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK)
The clarifying discussion is below
I think .performAction(AccessibilityNodeInfo.ACTION_CLICK) is right, but there might be some other concerns. Sorry for posting as an answer but a comment is too small.
Are you sure the onAccessibilityEvent is being called? I don't think that is the right event, but I can't be sure. Maybe put a log in there to ensure it's calling the event when you expect it to be called.
Also, looking at the source might restrict your search, maybe instead of event.getSource() try using rootInActiveWindow (I use Kotlin so it might have a method, see https://developer.android.com/reference/android/accessibilityservice/AccessibilityService#getRootInActiveWindow(int))
EDIT: 28 March 2022
I have run this code on my own accessibility service and it does click the button. But it's very prone to overflow.
var ranOnce = false // prevent overflow
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
if (event == null) return
if (event.eventType == TYPE_WINDOW_STATE_CHANGED) return
if (event.source != null && !ranOnce) {
val nodeList = rootInActiveWindow.findAccessibilityNodeInfosByText("Menu")
//event.source.findAccessibilityNodeInfosByText("Menu") // <-- always nothing in list
Log.d("onAccessibilityEvent", "List of nodes: $nodeList")
if (nodeList.size > 0) {
android.util.Log.d("onAccessibilityEvent", "Node info: ${nodeList[0]}")
ranOnce = true
nodeList[0].performAction(AccessibilityNodeInfo.ACTION_CLICK) //<-- caused an infinite loop!
} else {
Log.d("onAccessibilityEvent", "No nodes found")
}
} else {
Log.d("onAccessibilityEvent", "event.source is null!")
}
}
I created a chat application that uses Twilio Sdk. Everything works fine but after a Video Call ends, I get this notification which doesn't go away whatever I try to do. After this notification appears, if I try to initiate Video Call, it doesn't work then. Maybe its using some of my resources like microphone which does not allow the app to start Video Calling because the Android system shows that microphone is still being used. Also this is appearing on my Redmi 9C. I have already searched everywhere on the net but no such solution found. It also states its a bug in some devices but there must be something that can be done to resolve this. Help would be appreciated thank you.
This is the code that is used to disconnect from a room:
private fun killAllVideoProcess() {
if (localVideoTrack != null) {
if (localParticipant != null) {
localParticipant!!.unpublishTrack(localVideoTrack!!)
}
localVideoTrack!!.release()
localVideoTrack = null
}
if (room != null && room!!.state != Room.State.DISCONNECTED) {
room!!.disconnect()
disconnectedFromOnDestroy = true
}
if (localAudioTrack != null) {
localAudioTrack!!.release()
localAudioTrack = null
}
if (localVideoTrack != null) {
localVideoTrack!!.release()
localVideoTrack = null
}
}//killAllVideoProcess ends
I'm using SignalR. I can receive Messages and show Notification when the app is open or is in the background. but when closed application I can't receive messages. Does anyone have a solution to this?
I have the following code in MainActivity OnCreate:
ActivityChat.connection.received(json -> runOnUiThread(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.O)
public void run() {
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject != null && jsonObject.has("A")) {
jsonArray = jsonObject.getAsJsonArray("A");
String method = jsonObject.get("M").getAsString();
//PushNotifications(method,jsonArray);
if (method.equals("addNewMessage")) {
if (jsonArray != null && jsonArray.size() != 0) {
if (jsonArray.get(2).getAsString().equals(driverID)) {
if (TransportClass.showCaseView != null && !TransportClass.showCaseView.isShowing()) {
Notificate();
}
}
}
}
}
}
}));
This is by design, but not by the design of the SignalR client itself; this is a design consideration when building a mobile app on either native iOS or Android. When the app isn't in focus, the app isn't in the background running, either. AFAIK, in most cases the app is only running when you have it open on the phone. This is when the SignalR connection would be active - the moment you close the app, you also close the connection.
You'd want to use something like notifications here to tell the user to open the app, then when they do, the real-time connection would be there again.
We are using crashlyticsDidDetectCrashDuringPreviousExecution to detect java crashes and report them to our BI systems, but our app is mostly C++ and we are using crashlytics NDK, we can't find anything similar to crashlyticsDidDetectCrashDuringPreviousExecution.
Is there any way that we can actually detect an NDK crash when the app starts?
thanks
Oded
Mike from Fabric here.
Currently, there isn't a way to do this within Fabric or the SDK for an NDK crash.
NOTE: This works on older version only (Crashlytics 2.6.7 and CrashlyticsNDK 1.1.6)
I'm also looking for a solution for this.
We currently found a partial solution. I'm not sure how good it is, it's definitely not official, plus it's asynchronic (which we're trying to overcome by looping), but it's the best solution I found and it seems like it's working
Fabric.with(this, new Crashlytics.Builder().core(core.build()).build(), new CrashlyticsNdk(), new Crashlytics());
if (!userLeft) { // our handling to fix bug, see explanation below
new Thread(new Runnable() {
#Override
public void run() {
SessionEventData crashEventData = null;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000); // in ms
} catch (InterruptedException e) { }
crashEventData = CrashlyticsNdk.getInstance().getCrashEventData();
if (crashEventData != null)
{
// there was a crash!
// crash timestamp can be found at crashEventData.timestamp
break;
}
}
}
}).start();
}
Explaination for userLeft:
We had some bug with reporting crash for users that exited app, and this is the solution for that. We set this flag to true, and save it on the device (SharedPreferences). We do it on our main activity (which extends NativeActivity), on finish() func.
Code:
#Override
public void finish() {
// set some key such as USER_LEFT to TRUE
super.finish();
}
After that, just get that USER_LEFT value, assign it into userLeft param, and set it back to false on SharedPerferences.
Any insights about this solution?