How to trigger / debug backdoor functionality in Xamarin.Forms.UITesting? - android

I'm trying to add a BackdoorMethod to a Xamarin.Forms application to bypass the login (IDP - opened in chrome browser) step. I have the feeling that the method is not getting triggered, but not sure, and I don't know how could I make sure about it.
I've read the documentation here: https://learn.microsoft.com/en-us/appcenter/test-cloud/uitest/working-with-backdoors
Check this thread: https://forums.xamarin.com/discussion/85821/xamarin-uitest-backdoor-on-droid-with-splash-screen-how-do-i-access-my-mainactivity
Checked this example: https://github.com/brminnick/UITestSampleApp/tree/master/Src
In the MainActivity.cs file I've defined the BackdoorMethod:
[Preserve, Export(nameof(BypassLoginScreen))]
public string BypassLoginScreen()
{
// some additional code here. the code is working, when I called it
// directly from OnCreate it was executed without any error
return "called";
}
From the test case i'm trying to invoke it like:
public constructorMethod(Platform platform)
{
this.platform = platform;
app = AppInitializer.StartApp(platform);
var result = app.Invoke("BypassLoginScreen"); // result == "<VOID>"
}
I'm not getting any error message, the method simply not called, or not returns anything. (or i don't know what's happening there with it, because breakpoint also not working as the app started from the device)

This should be already working. I have similar code and it works for me.
you can add inside your function
Android.Util.Log.WriteLine(Android.Util.LogPriority.Info, "BypassLoginScreen", $"Some text as info");
And observe the result in Device Logs, Filter by BypassLoginScreen to see if there is any log created with the tag BypassLoginScreen

Related

Android printing with Brother SDK via WiFi throws ERROR_WRONG_LABEL despite selecting correct labelNameIndex

I've been trying to print with Brother Print SDK 3.5.1 on Android 8.1.0. I keep getting ERROR_WRONG_LABEL.
This is the code I use
void printPdf() {
// Specify printer
final Printer printer = new Printer();
PrinterInfo settings = printer.getPrinterInfo();
settings.printerModel = PrinterInfo.Model.QL_810W;
settings.port = PrinterInfo.Port.NET;
settings.ipAddress = "192.168.1.73";
settings.workPath = "storage/emulated/0/Download/";
// Print Settings
settings.labelNameIndex = LabelInfo.QL700.W62RB.ordinal();
settings.printMode = PrinterInfo.PrintMode.FIT_TO_PAGE;
settings.orientation = PrinterInfo.Orientation.PORTRAIT;
settings.isAutoCut = true;
printer.setPrinterInfo(settings);
// Connect, then print
new Thread(new Runnable() {
#Override
public void run() {
if (printer.startCommunication()) {
PrinterStatus result = printer.printPdfFile("/storage/emulated/0/Download/hello world red.pdf", 1);
if (result.errorCode != PrinterInfo.ErrorCode.ERROR_NONE) {
Log.d("TAG", "ERROR - " + result.errorCode);
}
printer.endCommunication();
}
}
}).start();
}
My printer model is QL-810W and I use the black and red W62 roll.
I've tried the Sample Application, where setting W62RB in labelNameIndex prints fine.
Changing the roll for different one with different width didn't help.
I've also tried iterating over numbers 0 to 50 and using them as labelNameIndex.
Based on this thread, I thought that the issue may be in specifying the workPath attribute. Setting workPath to getContext().getCacheDir().getPath() results in ERROR_OUT_OF_MEMORY instead of ERROR_WRONG_LABEL. Not specifying workPath and adding <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> to AndroidManifest.xml results in ERROR_WRONG_LABEL
EDIT
I've modified the Brother Sample app and uploaded it to GitHub. The app now launches Activity_PrintPdf.java by default where I inserted my printing code with hardcoded values at the beginning of onCreate method - this works fine and prints the PDF file as expected.
Then I created a new Empty Activity project in Android Studio, copy pasted the library, added the imports to build.gradle and copy pasted the permissions into AndroidManifest.xml. Then I copy pasted the printing code at the beginning of onCreate method in MainActivity.java. Running the app results in ERROR_WRONG_LABEL.
This is the modified working example app and this is the one that results in the error. I want to use the code as native module that I call from my React Native app, so it's important that I manage to set up the printing code from scratch rather than modifying the existing example app.
EDIT 2
I've inspected the library with a debugger: when executing printer.setPrinterInfo(mPrinterInfo) the library internally calls private boolean createWorkPath(String dirPath) of Printer object. On return from this method, the debugger shows Source code doesn't match the bytecode and seems to forget the created directory. This also internally sets mResult.errorCode = ErrorCode.ERROR_WORKPATH_NOT_SET. However, instead of rising any error here the code just silently proceeds, which later results in ERROR_WRONG_LABEL when trying to print. Running the same code snipper in the modified Sample app works fine.
I'd be grateful if you could help or suggest what to try next.
Thank you!
I've now fixed the issue, which was that the Brother library silently failed to create a temporarily folder and instead of reporting an error, it continued and failed later to read the label information. Based on this thread, it is now required to specify runtime file read and write permissions as opposed to the compile-time ones in AndroidManifest.xml.
Adding
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
at the beginning of onCreate before the printing code fixed the issue.

Why is Facebook's Unity SDK Not Logging Events To Analytics?

For some reason, I am unable to get the FB.LogAppEvent to work inside an android application built with Unity.
Based on the documentation I've read, the code below should work. But it's not producing results inside the analytics dashboard. You'll notice a method that produces an Android toast that confirms activation. This toast does appear on application start. I've tried multiple event types, including custom types from code generated by Facebook's event generator in the event documentation.
https://developers.facebook.com/docs/app-events/unity
https://developers.facebook.com/docs/unity/reference/current/FB.LogAppEvent/
private void Awake()
{
if (!FB.IsInitialized)
FB.Init( () => { OnInit(); } );
else
ActivateFacebook();
}
private void OnInit()
{
if (FB.IsInitialized)
ActivateFacebook();
else
ShowAndroidToastMessage("Failed To Initialize Facebook..");
}
private void ActivateFacebook()
{
FB.ActivateApp();
ShowAndroidToastMessage("Facebook Activated..");
FB.LogAppEvent(AppEventName.ActivatedApp);
}
I suppose the problem is in the way you send event
There are two methods for that:
LogAppEvent(string logEventName);
LogAppEvent(string logEventName, float valueToSum, Dictionary parameters = null);
You are using second method with "valueToSum" = 0, and that indicates there is nothing to sum, so your event probably gets skipped at some point.
You should use the first method
FB.LogAppEvent(AppEventName.ActivatedApp);
Also make sure your analytics is enabled in dashboard.
Do you see any built in analytic events? Feg. App Launches and other Standard events should be visible out of the box.
For me, LogAppEvent(...) successfully works with the Facebook Events Tracker and Analytics when you do a development build with Unity. When I switch to a release build, I then do not get any of the LogAppEvents other than the ActivateApp() notification.
Will update my answer when I get it working with a release build.

displaying runtime errors in android/ios installed app

I've been trying to get errors to display in a text field within the app for ease of error reporting from users.
I've had some success using this code I found on stackoverflow. It's used at the top level of the app but it's not working on device:
//start code
this.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, errorHandler);
function globalErrorHandler(event:UncaughtErrorEvent):void
{
var message:String;
//check for runtime error
if (event.error is Error)
message = (event.error as Error).getStackTrace();
//handle other errors
else if (event.error is ErrorEvent)
message = (event.error as ErrorEvent).text;
else
message = event.error.toString();
//do something with message (eg display it in textfield)
myTextfield.text = message;
}
//end code
At first this wouldn't work on the device and I thought it was because upon the error, when developing on the pc, flashplayer would display the actionscript popup with the error. Which you would need to click "dismiss all" or close and then the globalErrorHandler was called after and then the error written to the textfield. I thought this is what was keeping it from showing up on the device. However, by adding event.preventDefault() I was able to suppress the actionscript popup when developing on the desktop and the error was written to the textfield successfully. This was not the case however on the andriod device. It still just hangs on the error. It's as if the default error event cannot be suppressed on android.
Thanks for your time. Any help appreciated!
EDIT 22/09/2017: I was able to see the error on device finally. It had to do with while on desktop publishing the error would be shown. However, on device the behavior was different and something was covering the textfield, by bring it to the front on error I was able to see it. However, I still see that some errors deeper in the class hierarchy are not being caught.
In our project we have it simpler (and it is working):
stage.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
private function onUncaughtError(e:UncaughtErrorEvent):void
{
// Console is basically a TextField for debug/diagnosis output.
if (e.error) Console.error(e.error.getStackTrace());
e.preventDefault();
}
The other thing you should probably check is whether your TextField actually displays any text at all for there might be text embedding issues, unrelated to the error handling routine.
UPD: Loading SWFs so it doesn't mix with the parent.
var request:URLRequest = new URLRequest(path);
var context:LoaderContext = new LoaderContext;
context.applicationDomain = ApplicationDomain.currentDomain;
var loader:Loader = new Loader;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
loader.load(request, context);

phonegap android local notification cancelAll not working

hi I am using phonegap local notification plugin in my android project.
notification are working great.
i can delete a notification with ID
but in my app i have to delete all notification option, for which this plugin gives a method to cancelAll notification.
which is:-
plugins.localNotification.cancelAll();
but this is not working.
i am using this plugin from here
https://github.com/phonegap/phonegap-plugins/tree/master/Android/LocalNotification
any help will be appreciated.
I think this might be the answer to this one. As it says in the description of the cancelAllNotifications() method (LocalNotification.java line 124):
Android can only unregister a specific alarm. There is no such thing as cancelAll. Therefore we rely on the Shared Preferences which holds all our alarms to loop through these alarms and unregister them one by one.
However, take a look at the code where the cancelAllNotifications() method is called (line 59):
} else if (action.equalsIgnoreCase("cancelall")) {
unpersistAlarmAll();
return this.cancelAllNotifications();
}
Here's what unpersistAlarmAll() looks like (line 181):
private boolean unpersistAlarmAll() {
final Editor alarmSettingsEditor = this.cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit();
alarmSettingsEditor.clear();
return alarmSettingsEditor.commit();
}
What's happening is that the alarmIds are being cleared from sharedPreferences before cancelAllNotifications() is called, effectively leaving no alarms to be canceled.
I'm not sure where the best place to move the call to unpersistAlarmAll() is, and I'd be happy to get some suggestions. In the meantime I have moved it to within cancelAllNotifications(), after the result returned from alarm.cancelAll(alarmSettings) is tested (line 133), like so:
if (result) {
unpersistAlarmAll();
return new PluginResult(PluginResult.Status.OK);
So far this seems to be working fine. Perhaps another way to do this would be to scrap the whole unpersistAlarmAll() method and instead call unpersistAlarm(String alarmId) (line 168) after each individual alarm is successfully canceled.
Depending on what you are trying to do, you could use the "Statusbar notificaiton". This plugin will enable you to put message on the android status bar.
https://github.com/phonegap/phonegap-plugins/tree/master/Android/StatusBarNotification

Error calling method on NPObject! in Android 2.2

I'm using addJavascriptInterface within my Android application to allow JavaScript to invoke functions I've created in my native Java application.
This worked well in Android 2.1, however in Android 2.2 I receive the error message "Error calling method on NPObject!"
When I instrument the method call the internals of the native method are getting called, however the exception is being throw in JavaScript.
I was getting this exact error:
Uncaught Error: Error calling method on NPObject!
Turns out I was attempting to invoke a JavascriptInterface function from a webview like so:
AndroidJS.populateField(field);
and on the Java side, the function didn't accept a parameter:
public void populateField() {}
Simply allowing the Java function to accept a parameter solved this error for me.
E.g.,
public void populateField(String field) {}
This may not be, and probably is not, the only reason this error could be thrown. This is simply how I resolved my specific scenario. Hope this helps! :)
OK, I have same problem as well, just in today.
What I did is putting code in UI Thread, like code below :
/**
* 給網頁Javascript呼叫的method
* Method for Javascript in HTML
* #param java.lang.String - Playlist ID
*/
public int callListByPID(final String pId)
{
Log.i(Constants.TAG, "PAD Playlist ID from HTML: "+pId);
runOnUiThread(new Runnable()
{
public void run()
{
// Put your code here...
}
});
return 1;
}
This solved my problem, and hope it can help some body... :-)
In my experience this problem is caused by Javascript interfaces bringing back objects that Javascript doesn't automatically identify.
In Android this is caused by wrappers like Boolean or Long in comparison to their native versions boolean and long.
//This will fail
public Long getmyLongVal() {
return 123456789;
}
//This will work
public long getMyNativeLongVal() {
return 123456789;
}
So remove your wrapper classes to any methods being used by Javascript if you want to avoid NPObject errors.
Here's a twist I found on this problem that could be useful for some of the folks running into this problem (and it likely explains intermittent failures that seem to defy explanation)...
If any exceptions are thrown (and not caught) in the return handler code prior to allowing the javascript interface callback to return clean, it will propagate back as a failed call and you will also get this error - and it would have nothing to do with missing functions or parameters.
The easiest way to find this case (whether or not you use this in your final implementation) is to push whatever handler code you have back onto the UI thread (the callback will not be on the UI thread) - this will allow the callback to return clean and any subsequent exceptions that occur will propagate properly up until you catch them or until the app crashes. Either way you will see exactly what is really happening. Otherwise the uncaught exception passes back to javascript where it will not be handled or reported in any way (unless you specifically built error trapping code into the JS you were executing).
Good Luck All.
bh
I had the same problem with Javascript-to-Java interface (WebView.addJavascriptInterface).
In Android 2.1 everything worked just fine but in Android 2.2 Javascript failed to call methods from this interface. It returned an error: Uncaught Error: Error calling method on NPObject!
It seems that on Android 2.2, the WebView has problem with Boolean data type returned from interface functions.
Changing:
public Boolean test_func() { return true; }
... to:
public int test_func() { return 1; }
... solved the problem.
This I believe is no longer supported anymore ( Always game NPObject error ) .
Please refer to the answer in this thread
Visit open an activity from a CordovaPlugin

Categories

Resources