Return from Android Gallery in jUnit? - android

I have an application in which if you click a button, it opens the Android Gallery application. The user can then select an image for my application. The thing is, if I click that button in JUnit, it opens up the Gallery and then just sits there. I have to manually choose a picture. I just want to be able to open the Gallery and then go back or if possible select an image.
I tried several options such as -
sendKeys(KeyEvent.KEYCODE_BACK)
Robotiums goBack(), goBackToActivity(), sendKey() functions
Robotiums clickOnScreen() function to click and select an image
but none of these seem to work. So what do I do?

I had the same problem. You can't do this, as the Android Gallery is another application running in its own sandbox which you cannot reach from your testing code.
However, I came up with the following solution. You can build your own dummy application that provides an Intent filter for opening images. In this application you simply return the intent with an ok.
Now you only have to select your application as the default application when first opening your image from your test application. Afterwards, everything should work automatically.
Once you're done with testing, you can reset the default intent filter in your Android device's settings.
The code for my solution can be found in this discussion: How to provide content for Intent.ACTION_GET_CONTENT

It is possible to simulate response returned from gallery.
The code snippet below do all the work.
final Intent data = new Intent();
data.setData(Uri.parse("content://media/external/images/media/458")); // put here URI that you want select in gallery
Runnable runnable = new Runnable(){
#Override
public void run() {
getActivity().onActivityResult(3333,-1, data);
synchronized(this) {
this.notify();
}
}
};
synchronized(runnable) {
getActivity().runOnUiThread(runnable);
runnable.wait();
}
This method has two drawbacks:
onActivityResult method of your activity should be public which brakes encapsulation.
Test will not actually click button which opens gallery and onClick handler won't be executed.
But the benefit of such approach is that you don't need to build mock application and change any defaults in android settings.

Related

Cordova-Plugin-Camera-Preview - is there a way to listen for a tapPhoto event?

I want to run some code on a photo capture, but there isn't an obvious way to to this. I set tapPhoto to true so that the plugin captures pictures when the user taps the screen, and it seems to be working since it triggers the camera sound. My issue is that there does not seem to be a way to run code once the capture happens, so that I can close the camera, retrieve the image data, etc. This is my code:
angular.module('myApp').factory('photoService', function(...){
var cameraOptions = {
camera: CameraPreview.CAMERA_DIRECTION.BACK,
tapPhoto: true
}
CameraPreview.startCamera(cameraOptions);
//onCapture isn't a real part of the plugin, but this is just the code I want to run each
//time the user taps the phone screen
CameraPreview.onCapture = function(imgData){
showPhoto(imgData);
CameraPreview.stopCamera();
}
});
I saw online that takePicture() is basically what I want, but it looks like we have to call it once for it to work subsequent times (https://github.com/cordova-plugin-camera-preview/cordova-plugin-camera-preview/issues/364) and I don't want to do that because my app essentially opens the camera, allows the user to take a single photo, and then closes the camera, so having to take double the number of pictures than necessary is not ideal. Is there another way to achieve the functionality I want?

How to open common incomplete products link with different toolbar in android studio

I have an eCommerce website and that has been running as an android app using WebView method. I have basic knowledge in android studio but not depth. My concern is wanna open Second Activity from Main Activity when user clicks on any product in app that contains link as "https://www.ecommerce.in/product/XXXXX". Here "https://www.ecommerce.in/product/" is common to all products but "XXXXX" will change to every product when user clicks on different products and this Second Activity should open using another toolbar without related to Main Activity toolbar and my code is like this:
webView.setWebViewClient(new ourViewClient()
{
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if(url.contains("https://www.ecommerce.in/product/XXXXX"))
{
Intent intent = new Intent(MainActivity.this, ProductsActivity.class);
startActivity(intent);
}
}
});
This code is not working at all. Hope, I get a solution for this and thank you for your help in advance.
First, it looks like you're trying to filter out links with a contains:
if(url.contains("https://www.ecommerce.in/product/XXXXX"))
But you've made it too restrictive. It is literally looking for "XXXXX" in the URL. Also, this doesn't really get you much in terms of security. WebViews are very dangerous. I'd suggest looking through this link for some basic suggestions.
Anyways, if you just want to open the ProductActivity it looks like all you have to do is update the test as follows:
if (url.startsWith("https://www.ecommerce.in/product/"))
Note if you need that URL then you have to pass it to the ProductActivity as part of the intent and grab it in the ProductActivity, but be sure to verify the URL before just loading it to make sure sit starts with the common part.
It might be that someone is trying to get your Activity to do things it shouldn't be.

Android Expresso/UI Automator How do i automate clicking on Android screens outside my app (app picker)

My Android application has a button to download a file and then send it to an application on the device. Android pops up a screen listing the Applications on the device for the user to select which application to use.
I would like to automate this flow but i can not see how I can automate clicking on the Application Picker that Android presents. I presume this is because it is outside of my application.
I tried using Android Studio's "Record Expresso Test", I performed the following test steps
click on the action which sends my image to an app on the device (action1)
saw the Android Application picker appear and chose photos
Clicked back to close photos app and go back to my app
click on a different action in my app (action2)
I see in the recorded test code for steps 1 and 4 above, but nothing for 2 and 3. Therefore it makes me think that Expresso can not be used for this particular test flow.
Does anyone know how I could test this flow using Expresso?
EDIT:
Thank you to "John O'Reilly" for recommending UI Automator. I can see that I can use the UI Automator code within my Expresso test successfully. However I am having trouble writing a precise verification of the Application Selector.
The selector will have a title of "Open With". Using Android Device Monitor I can see the hierarchy of objects as illustrated below.
Some classes and IDs are internal so I can not search on those things. I do not want to code to look for a specific application as when the test is run on another machine it may not have that application. I just need to verify that the application picker has been displayed.
// the app selector has a FrameLayout as one of its parent views, and a child Text View which has the "Open With" title
UiObject labelOnly = new UiObject(new UiSelector()
.className("android.widget.FrameLayout")
.childSelector(new UiSelector()
.className("android.widget.TextView")
.text(openWithLabel)
)
);
boolean labelOnly_exists = labelOnly.exists();
// the app selector has a FrameLayout as one of its parent views, and a child ListView (containing the apps)
UiObject listOnly = new UiObject(new UiSelector()
.className("android.widget.FrameLayout")
.childSelector(new UiSelector()
.className("android.widget.ListView")
)
);
boolean listOnly_exists = listOnly.exists();
// I can use the listView to search for a specific app, but this makes the tests fragile if a different device does not have that app installed
UiObject listAndAppName = new UiObject(new UiSelector()
.className("android.widget.ListView")
.instance(0)
.childSelector(new UiSelector()
.text("Photos")));
boolean listAndAppName_exists = listAndAppName.exists();
How could i write a statement that verifies that what is on the screen is the application picker? I was hoping maybe have a selector that searches for a FrameLayout which has a child textView containing "Open With" and also contains a child ListView. With these 2 checks together it should identify only the application picker.
The credit for the answer to this question should go to John O'Reilly who pointed me to use the UI Automator.
I resolved the issue of checking what Android screen is invoked when my test clicks on an action by just checking there is a TextView on the screen with the title I am expecting. Its not perfect as this will pass if there is any TextView on the screen with the text so does not precisely check its the application picker.
However, for my test this should be enough of a check as my app (which would be behind the app picker) should not have a TextView with the expected title, so if the title is found its pretty much likely to be the application picker.
public static boolean verifyAndroidScreenTitlePresent(String title) {
UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
UiObject titleTextUI = new UiObject(new UiSelector()
.className("android.widget.TextView")
.text(title)
);
boolean titleExists = titleTextUI.exists();
// close the app selector to go back to our app so we can carry on with Expresso
mDevice.pressBack();
return titleExists;
}

Turbolinks 5 and Android: Fails when use file upload (webview)

Problem
When the user clicks on choose file, I intercept that click natively and I call the native view (screen 3 in the mockup).
After the user select the file he wants to upload, I need to "reload" the view in order to add the name of the file in the form, so the user can get the feedback that he selected the file correctly.
In order to do this, I'm calling onRestart with the following code:
#Override
protected void onRestart() {
super.onRestart();
// mCM is a variable to detect when the user is choosing a file.
if (null == mCM) {
// Since the webView is shared between activities, we need to tell Turbolinks
// to load the location from the previous activity upon restarting
TurbolinksSession.getDefault(this)
.activity(this)
.adapter(this)
.restoreWithCachedSnapshot(true)
.view(turbolinksView)
.visit(location);
}
}
As you can see, in this method when is uploading a file I do NOT reload the view using TurbolinksSession.
But if I don't call TurbolinksSession, Turbolinks never calls visitProposedToLocationWithAction.
Scenario
NOTE: Download the image if you want to see the image bigger.
What am I missing? Is there a way to solve this problem and get the expected result?
In this 2 issues you can find a solution and resolution of the problem (read it in this order):
https://github.com/turbolinks/turbolinks-android/issues/53
https://github.com/turbolinks/turbolinks-android/issues/65
https://github.com/turbolinks/turbolinks/issues/88

Android Pinterest SDK: PinIt button no longer functioning

We noticed the Pin It button is no longer working within our application. Pressing it doesn't result in anything occurring.
The PinItListener doesn't get any exception callbacks, but it returns false for whether it was pinned in onComplete.
Trying out the PinItDemo project bundled with the SDK, nothing occurs on click either. I tried it with our client ID and a new client ID I set up.
Since it stopped functioning between releases of our application, I'm assuming it's a Pinterest change. Did a Pinterest update break the PinItSDK? Is there something we can do to fix it?
I'm not sure if PinItSDK doesn't work anymore or what the problem is. But there is another way you can pin the content. You can use the base url to open Create Pin form like
http://www.pinterest.com/pin/create/button/?media=http://www.ournorthstar.com/wp-content/uploads/2013/10/test1.jpg&title=Sample&description=This+is+a+test+description
and pass it as an intent and start the activity.
Eg:
String shareUrl = "http://www.pinterest.com/pin/create/button/?media=http://www.ournorthstar.com/wp-content/uploads/2013/10/test1.jpg&title=Sample&description=This+is+a+test+description"
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(shareUrl));
startActivity(myIntent);
This issue was fixed in Pinterest for Android 2.1.4

Categories

Resources