Open browser with Data URI Scheme instead of a URL - android

Well, I was breaking the hell of my brain cells with this and no solution came up...
Usually, in Android, to open the Web Browser in a specified Website, we do this:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
startActivity(browserIntent);
So, I got a Data URI Scheme (dunno if it is written this way, i'm not an expert on this kind of stuff) like this:
data:text/html;charset=utf8;base64,<base64 html code>
If I copy and paste this in a web browser, it will handle it the way I want it.
But how can I do it programatically in Android?
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(dataHTMLBase64));
startActivity(browserIntent);
dataHTMLBase64 stores the Data URI Scheme I mentioned before.
The code above won't work. It won't even launch chrome.
What can I do?
PS: I'm not good with English. Please warn me if I didn't express myself the right way...

Actually, it appears that one can launch a Data URI in an Android browser quite easily.
String url = "data:text/html;charset=utf8,<b>Hee-haw!</b>";
startActivity(Intent.makeMainSelectorActivity(
Intent.ACTION_MAIN, Intent.CATEGORY_APP_BROWSER)
.setData(Uri.parse(url.toString())));
Using apktool I reviewed the AndroidManifest.xml of the Google Chrome .apk file.
(apktool is quite easy to install, and then the command is simply apktool d example.apk)
I found the relevant intent filters (listed below) so there are many possible ways to launch the browser. Of course other browsers may have different intent filters, but it seems that APP_BROWSER is a good choice.
<activity-alias android:exported="true" android:name="com.google.android.apps.chrome.Main" android:targetActivity="org.chromium.chrome.browser.document.ChromeLauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.APP_BROWSER"/>
<category android:name="android.intent.category.NOTIFICATION_PREFERENCES"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="googlechrome"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:scheme="about"/>
<data android:scheme="javascript"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="googlechrome"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:scheme="about"/>
<data android:scheme="content"/>
<data android:scheme="javascript"/>
<data android:mimeType="text/html"/>
<data android:mimeType="text/plain"/>
<data android:mimeType="application/xhtml+xml"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="multipart/related" android:scheme="file"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MEDIA_SEARCH"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.speech.action.VOICE_SEARCH_RESULTS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
</intent-filter>
<intent-filter>
<action android:name="com.sec.android.airview.HOVER"/>
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="#xml/searchable"/>
</activity-alias>

If you get these data URIs from somewhere you could do two things:
Parse the data content out of it and use it in some WebViewand call loadData(...) on it to display the contents
Save the data content of the URIs to some file, use FileProvider to make this file accessible outside of your app and use the URI returned by that to fire up a browser / view intent

Related

How to list my application on file manager's open with?

I want to open a file with my application. Added this intent filter, but file manager is not listing to my app. The file is a custom text file with type of .tdr. What am I doing wrong ?
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="file/*"/>
</intent-filter>
Also tried mime type "/"
I have multiple intent filters, this is one of them.
as "blackapps" said i had to use android.intent.action.VIEW
this now works:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:mimeType="*/*"
android:scheme="file"/>
</intent-filter>

It is mandatory to specify the "android:host" for all url in android for Deep Link?

I have to filter two URL for an activity. I'm using Deep Links to App Content by specifying a url for the Deep Link Screen.
These are my urls
appdemo://deeplink
native://
I'm already added these two scheme to my Android Manifest file, looks like
<data android:scheme="appdemo" android:host="deeplink" />
<data android:scheme="native" />
my question is that, by providing scheme and host on the Android Manifest file, native:// this link does not work. it requires the android:host name also
(native://deeplink).
It is mandatory to specify the "android:host" for all url in android?
If no, how can i specify the different scheme.
The idea beside deep links is to use the same structure as normal links:
scheme://host/path
The main benefit is that you can teach your app even to open some Internet links, e.g. to open youtube (Android will ask, if you want to open in browser or YouTube app or your app):
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="youtube.com"/>
<data android:host="www.youtube.com"/>
<data android:host="m.youtube.com"/>
<data android:host="youtu.be"/>
<data android:pathPattern=".*"/>
</intent-filter>
So, answering your questions:
Yes, it is mandatory to specify both scheme and host.
A good practice of handling two different links in one activity is to use different paths. Like this:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="appdemo" android:host="deeplink" android:pathPrefix="/path1/"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="appdemo" android:host="deeplink" android:pathPrefix="/path2/"/>
</intent-filter>
Then you can get your path in onNewIntent:
Uri data = intent.getData();
String path = data == null ? null : data.getPath();
...and build some logic depending on this path.
The above answer is acceptable and, in my case i want to navigate a new activity through this intent filter, and i got some information to the above answer and made some changes in my code and fix the issue.
Also I'm not specifying the host name for my second intent.
<activity
android:name=".DeepLinkActivity"
android:exported="true"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appdemo" android:host="deeplink" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="native" />
</intent-filter>
</activity>
Now my both url navigate to DeepLinkActivity.
appdemo://deeplink
native://
Do you think this is not an optimized way?
Any other suggestions for that please mention.

Android Intent filter for url with redirect

How to setup intent filter for url with redirection?
https://mail.mailserverXXX.com/m/redirect?url=http://foosubdomain.foodomain.com/#object?id=e1162d22-222b-4522-2210-c222102d6022
This filter does not work for URL above.
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="foosubdomain.foodomain.com"/>
</intent-filter>
This filter works for URL above. But this is not what needed. I need to filter by host in redirect part foosubdomain.foodomain.com
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="mail.mailserverXXX.com"/>
</intent-filter>
Well bad news. After a long check I found that intent-filter doesnt even parse everything after question mark
In other words from link
https://mail.mailserverXXX.com/m/redirect?url=http://foosubdomain.foodomain.com/#object?id=e1162d22-222b-4522-2210-c222102d6022
Intent-filter works only with that part
https://mail.mailserverXXX.com/m/redirect
So there is impossible to write universal solution for your problem.

How do I find out if My activity was started by an Activity of my own app?

I have a library project that displays pdfs. My main project has a few PDFs that I want to display. So I use it. Also, I have added intent filters for the activity that displays the pdf(so that other apps can also use it to display pdfs).
I want to detect if my PDFVIEWER was started by my own activity or not(I want to display the Title Bar if its started externally) how do I do that?
Here is my activity declaration:
<activity
android:name="com.artifex.mupdfdemo.MuPDFActivity"
android:theme="#android:style/Theme.Holo.Light"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.ms-xpsdocument"/>
<data android:mimeType="application/xps"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/pdf"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/x-cbz"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="file"/>
<data android:mimeType="*/*"/>
<data android:pathPattern=".*\\.xps"/>
<data android:host="*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="file"/>
<data android:mimeType="*/*"/>
<data android:pathPattern=".*\\.pdf"/>
<data android:host="*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="file"/>
<data android:mimeType="*/*"/>
<data android:pathPattern=".*\\.cbz"/>
<data android:host="*"/>
</intent-filter>
</activity>
I can't tell you, if it's possible to get the activity which started the intent, but as a workaround you can put a Boolean value in your Intent to make sure your PDFViewer was started by your app.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(fileUri);
intent.putExtra("myAppStarted", true);
And in your started activity:
boolean displayTitleBar = getIntent().getBooleanExtra("myAppStarted", false);
Please note it is recommended to use static final String variable with "myAppStarted" instead of hardcoding the String in different places.
You can use getCallingActivity, provided your activity was started using startActivityForResult. A better solution would be to add extra information into your intent that tells you if the calling activity is yours.
AppCompat.getReferrer() should return the package name of the Activity that started yours.

Handling share and other actions from Chrome

I have an app which can play some videos, think MXPlayer plus a light browser. So I would like to get the opportunity to handle certain video files when someone clicks on a link in chrome of one those files, and also I would like to appear on the share popup of chrome when someone wants to share the link (so that my app may open the page). I have so far gotten my app to show up on the share popups of other apps but I just can not get it to show up on the share popup of Chrome. Here are my intent filters:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:mimeType="video/*"/>
<data android:mimeType="*/avi"/>
<data android:mimeType="*/mkv"/>
<data android:mimeType="application/mp4"/>
</intent-filter>
<intent-filter android:icon="#drawable/ic_launcher">
<action android:name="android.intent.action.SEND"/>
<data android:mimeType="*/*"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
Can someone tell me what I am doing wrong? Also I should mention I only want http/https streams, I do not want local files.
Thanks.
I managed to get it working by using this for the share menu option:
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:mimeType="text/plain"></data>
</intent-filter>
and this for when someone clicks on a link and chrome pops a dialog of where to open it:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
</intent-filter>

Categories

Resources