Android testing - change system value for testing logical branch - android

I've got a method that tries to start a browser with a specific URL, or if the device does not have a browser installed, instead starts an Activity with a WebView and loads the same URL. Basically this:
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
getActivity().startActivity(intent);
} catch (ActivityNotFoundException e) {
Intent intent = new Intent(getActivity(), MyWebView.class);
intent.putExtra(EXTRA_URL, url);
getActivity().startActivity(intent);
}
}
How can I test both branches? Is it possible to unregister the Browser activity from the device, temporarily and programmatically?
I had considered a Shadow Activity that just throws an ActivityNotFoundException when that particular Intent was passed to it (i'd check the data URI), but AFAIK there's no way to turn that Shadow on for one test and off for the other.
TYIA

This is really over engineering. The odds that the user doesn't have a web browser on the device is 0. It isn't worth worrying about.
If you're worried about the url being invalid and unparsable, its unlikely this would fix that problem, as it would be unparsable in your web view activity as well. If you really want to be paranoid I'd catch it and toast an error.
As for testing it- refactor to make it testable. Write this as a function that takes a URL as a parameter. For the bad version, use a URL like thisisnotavalidscheme://example.com. That will fail as nobody is going to be registered for that scheme.

Related

Open Facebook native app from your android app

My question is directly connected with this one Open Facebook page from Android app? Which answer (for the version at the moment) is not the marked one but this one
public static Intent newFacebookIntent(PackageManager pm, String url) {
Uri uri;
try {
pm.getPackageInfo("com.facebook.katana", 0);
// https://stackoverflow.com/a/24547437/1048340
uri = Uri.parse("fb://facewebmodal/f?href=" + url);
} catch (PackageManager.NameNotFoundException e) {
uri = Uri.parse(url);
}
return new Intent(Intent.ACTION_VIEW, uri);
}
Which is confirmed working last on 7th of February 2015.
My question is should you use the whole url (like www.facebook.com/mypage) or just add the url of the page so it'll be fb://facewebmodal/f?href=mypage. I tried both and it just opens the fb app without an actual page. It shows blank fb page on both tries.
Can someone give me an example with url for some public page that works?
You can try to write mypage as https://www.facebook.com/ID. The whole uri should then be
fb://facewebmodal/f?href=https://www.facebook.com/ID
and change ID to the page you want to visit.
That functionality is not documented or supported, so you may get unknown result. You may want to try passing the Page ID or Profile ID instead of names. You can get the ID by calling https://graph.facebook.com/<name> and parse the result.
I had the same issue. I searched for a while and tried all the answers on here Open facebook page from android app (in facebook version > v11) and there Open Facebook page from Android app?, finally I figured out what the real problem is. There is nothing wrong in the code, however the weird behavior is about facebook app itself. If the facebook app is on the background, it just switches back to the foreground without navigating to the requested page. You just swipe it out from the background (kill instances) and try your code again.
Considering most of the users leave facebook app on the background, this is some kind of an issue needs to be fixed. Although I think it is about the facebook app itself, somehow it can be related with the device. I'm using Nexus 6 with v 6.0.1 and had no chance to test it on another android versioned device.
i using this for my apps its working just fine, kotlin
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("fb://page/100674618166286"));
startActivity(intent);
} catch(e: Exception) {
startActivity( Intent(Intent.ACTION_VIEW, Uri.parse("http://www.facebook.com/iqtousd")));
}
Remember have a similar issue.
Try the mobile url :
instead of
String facebookUrl = "https://facebook.com/...";
use
String facebookUrl = "https://m.facebook.com/...";

Launching Android Netflix App And Passing Video Id

In the app I am working on I want to support Netfilx streaming. I intend on doing this by simply starting Netflix and passing a specific URI so it plays a specific video when started. Simple right? Well, the issue is I'm not sure how to pass the video id info in the Intent I use to start the Activity.
I've read the post here , but am unsure where to use this. I used Intent.setData() since it accepts a URI, but to no avail.
Here is what I have been doing (I am hard coding the movie data, this is just for testing purposes) :
// the Netflix intent
Intent intent = getPackageManager().getLaunchIntentForPackage("com.netflix.mediaclient");
//the uri
Uri uri = Uri.parse("http://movies.netflix.com/WiPlayer?movieid=70266228&trkid=13462049&ctx=0%2C1%2Ce2bd7b74-6743-4d5e-864f-1cc2568ba0da-61921755");
intent.setData(uri);
//launches but does not go to the video
startActivity(intent);
I've also tried using the URI protocol in the link above like so:
Uri uri = Uri.parse("nflx://movies.netflix.com/WiPlayer?movieid=70266228&trkid=13462049&ctx=0%2C1%2Ce2bd7b74-6743-4d5e-864f-1cc2568ba0da-61921755");
but still am not seeing the video play.
I feel like I am missing something simple here, although I have had very little luck Googling for this, I could find next to nothing about starting the Netflix Android app from another application. The Netflix developer resources don't have any info on this.
Does anyone have any suggestions on how I can do this or where I should be looking for documentation on this? Any help would be appreciated. Thanks much!
Just some Android Apps intent names to help anyone.
Format: appName, packageName, className
Skype: com.skype.raider, com.skype.raider.Main
Netflix: com.netflix.mediaclient, com.netflix.mediaclient.ui.launch.UIWebViewActivity
ESexplorer: com.estrongs.android.pop, com.estrongs.android.pop.view.FileExplorerActivity
Youtube: com.google.android.youtube,com.google.android.youtube.HomeActivity
Chrome: com.android.chrome,com.google.android.apps.chrome.Main
VLC: org.videolan.vlc, org.videolan.vlc.gui.MainActivity
MBOXSettings: com.mbx.settingsmbox, com.mbx.settingsmbox.SettingsMboxActivity
I've managed to do this. With the following code. First you need the movieId (or videoId) for netflix, then compose the URL to watch.
String netFlixId = "43598743"; // <== isn't a real movie id
String watchUrl = "http://www.netflix.com/watch/"+netFlixId;
Then with this intent
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName("com.netflix.mediaclient", "com.netflix.mediaclient.ui.launch.UIWebViewActivity");
intent.setData(Uri.parse(watchUrl));
startActivity(intent);
}
catch(Exception e)
{
// netflix app isn't installed, send to website.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(item.url));
startActivity(intent);
}
I haven't tried with TV Shows yet. But this works beautifully. If you want to send to the profile page of the movie.. Send it to a url formatted this way
http://www.netflix.com/title/324982
I also found out how to search for a title.
try {
Intent intent = new Intent(Intent.ACTION_SEARCH);
intent.setClassName("com.netflix.mediaclient", "com.netflix.mediaclient.ui.search.SearchActivity");
intent.putExtra("query", item.label);
startActivity(intent);
}
catch(Exception e)
{
Toast.makeText(this, "Please install the NetFlix App!", Toast.LENGTH_SHORT).show();
}
Here is how to start a movie from an ADB command for com.netflix.mediaclient
adb shell am start -n com.netflix.mediaclient/.ui.launch.UIWebViewActivity -a android.intent.action.VIEW -d http://www.netflix.com/watch/60000724
I still can't find a way to do it for com.netflix.ninja (Netflix for Android TV)

ACTION_GET_CONTENT to Google Images

As the docs say: "ACTION_GET_CONTENT could allow the user to browse over the web and download the desired data".
And that's what I need, from Google Images. Although, if I use this intent's type the app crashes (I suppose it only expects ACTION_VIEW to open the browser):
Intent intent = new Intent();
intent.setData(Uri.parse(url));
intent.putExtra("return-data", true);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, PICK_IMAGE);
It needs to (edited to clarify what I need):
Estabilish the connection to the web browser
The URL to Google Images
Retrieve the image's URL after the user has chosen one (it needs to close the browser, the ACTION_VIEW just keeps on going until the user decides to close it and does not retrieve any information).
As far the URL I have is this one, but it needs something else because it is going to a default search, not for images:
String url = "http://images.google.com/search?q=" + imagename;
I appreciate any help.
Try using the following url. It works fine for me in my app:
"http://images.google.com/search?num=10&hl=en&site=&tbm=isch&source=hp&biw=980&bih=710&q=" + YourQueryString
You need the tbm query parameter set to the value isch for image search. So the minimal URL would look like:
"http://google.com/search?tbm=isch&q=" + queryString

Setting default browser for activity programmatically

I'm developing an android app and among other functionality I need to open some urls in external web browser. Can I programmatically set a default application for that, so the user won't be able to choose from the list of available browsers? I mean, I want to set default browser only for my app but not for the whole operating system.
Yes, for this you can force your application to always open native android browser only. For this you have to identify the launching Activity of Browser application, something like this:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.google.android.browser","com.google.android.browser.BrowserActivity"));
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.BROWSABLE");
Uri uri = Uri.parse(url);
intent.setData(uri);
try
{
startActivity(intent);
}
catch (Exception e)
{
e.printStackTrace();
}
You can use .setPackage for the intent: http://developer.android.com/reference/android/content/Intent.html#setPackage(java.lang.String) . Call it with the browser's package name (defined in its manifest, package attribute).
I'm using something similar for firing up the Google+ application for sharing a string:
Intent shareIntent = ShareCompat.IntentBuilder.from(getActivity())
.setText("Dummy string to share")
.setType("text/plain")
.getIntent()
.setPackage("com.google.android.apps.plus");
startActivity(shareIntent);
In my example, "com.google.android.apps.plus" is the package name for the Google+ application.
Sharedpreference for Browser class is "MODE_private" , so we can't access the home_page changing steps directly programatically,
iff we want to do, we should do through Browser.java opensource code and we should get some idea from there itself.

Android: starting a default application or one which may be different on different devices

I would like to start a default application: browser, contact-book, phone, email, music app, etc. I have found many q/a, like browser opening a specific URL or blank, and here the answer is even "No not possible". But I would like to just open/launch it without telling it to go to a specific URL or sending a mail to someone, etc.
However, I also saw some Home applications where this seems to be working (at least for some apps). On my colleague's device there is for example a different contact-book (no google) which is detected and opened correctly.
I have seen in the Android documentation some intent categories that point to these problems, but these are only >= API.11. So I can't use/test them on my device.
Question: Is it not somehow possible to launch a default application (having the app chooser is of course ok) without providing extra data? If no, what do you think are these Home apps doing (perhaps workarounds are somehow possible).
PS: for the phone app I think, I have a workaround using Intent.ACTION_DIAL without any other information which will open simply the dialer.
UPDATE: I modified the title. Some applications like the address book may not be the same on different devices. So in this case I would like to start the address-book app, whichever this is.
This answer is not a 100% answer, but some workarounds on some typical applications.
Still open are: music player, address book
Browser: I get a list of applications that handle "http"-data intents, and then I look if one is available in the list of preferred applications.
Intent appFilter = new Intent(Intent.ACTION_VIEW);
appFilter.setData(Uri.parse("http://www.google.com"));
List<ResolveInfo> browserInfoList = pm.queryIntentActivities(appFilter, 0);
List<IntentFilter> outFilters = new ArrayList<IntentFilter>();
List<ComponentName> outActivities = new ArrayList<ComponentName>();
pm.getPreferredActivities(outFilters, outActivities, null);
if(outActivities.size() > 0) {
for(ComponentName cn : outActivities) {
String cnClass = cn.getClassName();
String cnPkg = cn.getPackageName();
for (ResolveInfo info : browserInfoList) {
if(info.activityInfo.name.equals(cnClass) &&
info.activityInfo.packageName.equals(cnPkg)) {
return cn;
}
}
}
}
In case no default is found, I open a browser chooser dialog, see here.
Phone: as described in the question:
Intent intent = new Intent(Intent.ACTION_DIAL);
startActivity(intent);
You can start apps by the function "startActivity" if you know about the canonical app name
like "android.com.browser". Do this simple by searching for AndroidManifest.xml in the app
source code (look at Codeaurora.com or at github/Cyanogenmod) and grab the app name you want.
After you know about the App name ("Activity") implement the code as follows:
Intent intent = new Intent();
intent.setClassName(this, "com.android.browser");
intent.setCategory(Intent.ACTION_MAIN);
startActivity(intent);
THIS is only a example, sometimes you have to put intent extras or data values, this information can be found in the app's AndroidManifest.xml too.

Categories

Resources