I am an iOS developer assigned a task in Android, so bear with me, I'm a bit green in Android.
I am attempting to load a local html file that is stored in the device download directory in a folder called user_guide. I want the html file to load in the device's browser (not in a webview for reasons outside the scope of this post). I am using the following code to launch the browser:
String downloadPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();
String path = "file://" + downloadPath + "/user_guide/index.html"; // + R.raw.test;
Uri pathUrl = Uri.parse(path);
Intent browserIntent = new Intent(Intent.ACTION_VIEW);
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
browserIntent.setData(pathUrl);
context.startActivity(browserIntent);
I obtained the value of path by setting a breakpoint and manually set it in Chrome on my device to verify that is does work and loads the proper file. However, when I try to run this code in the app, I get the following toast message:
Cannot display PDF (index.html is of invalid format)
I'm confused about this message since I am trying to load an html file, not a PDF. Can anyone help me out? THanks!
Try changing "browserIntent.setData(pathUrl)" to
browserIntent.setDataAndType(pathUrl, "text/html")
to explicitly specify that it's HTML.
I found this suggestion at https://stackoverflow.com/a/7009685/10300291.
Related
I have a mobile app that wraps around the web-app, using webview.
The web-app has a button to open a large .zip file (e.g. 100 MB).
The user clicks a button, and selects a .zip file.
This triggers an onChange function with a variable of type File (Blob), which includes attributes like:
file name
file size
file type (application/zip)
The javascript code then parses the .zip file, extracts specific data within it and uses it within the web-app.
This works well within the web-app, when the app is called via the Chrome browser.
For example when operated in chrome browser on an Android phone, I can pull the .zip file and open it in the web-app.
I want to do the same but using the mobile app.
I am able to pick up the .zip file using a File Chooser, but I have problems to fetch the file from the Javascript code.
When calling fetch(fileUri) from the Javascript side I'm getting errors.
I'm using the following uri
/storage/emulated/0/Android/data/com.example/files/Download/file2.zip
The fetch succeeds but returns a blob with size of 165 (i.e. not the actual size of the file) which hosts the error message:
{
"error": "Not Found",
"message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."
}
The program flow is like so:
I select a .zip file via FileChooser.
In onActivityResult, the uri value is /document/msf:12858 (seen via uri = intent.getData();)
The uri needs to be mapped into a real path file url, such that the fileUrl will be passed to Javascript (via webview).
Javascript will then fetch the file using the fileUrl.
I searched how to get the real path file url when selecting a file with FileChooser, and found
this, and this links.
I wasn't able to get the real file path, so I decided to read the file and write it to another location, so I can get a file path. (this is not efficient and done just to check the functionality).
I create the new file using the following code:
InputStream stream = context.getContentResolver().openInputStream(uri);
File file2 = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "file2.zip");
writeBytesToFile(stream, file2);
I don't see any errors when creating the file, and when creating the file, the number of bytes that are read and written to the new file are as expected.
For file2, I get a value of:
/storage/emulated/0/Android/data/com.example/files/Download/file2.zip
Then, within the Javascript code I fetch this file path.
But I'm getting a Blob with the "file-not-found" content as above.
So:
How can I verify that the file is indeed created and that the path can be fetched from Javascript?
How can I get the real file path of the original selected file, so I don't have to read and write the original file to new location just to get the file path?
Thanks
EDIT1:
I have "Intent intent" and not "Intent data" in the signature of onActivityResult.
I replaced String filePath = intent.getData() with
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
try {
intent_to_resolve = new JSONObject();
if (resultCode == RESULT_OK) {
// try1
String filePath1 = intent.getData().toString();
Log.d("Verbose", "filePath1: " + filePath1);
// try2
String filePath2 = intent.toString();
Log.d("Verbose", "filePath2: " + filePath2);
...
I'm getting the following value for filePath:
filePath1: content://com.android.providers.downloads.documents/document/msf%3A12858
filePath2: Intent { dat=content://com.android.providers.downloads.documents/document/msf:12858 flg=0x43 }
I am developing a NativeScript Android app and using QuickBlox.
I can open images and audio files inside the app, but there are some issues with .pdf, Word and Excel documents.
Code written by a co-worker:
var attID = message.attachments[0].id
var fileSrc = ChatManager.getQB().content.publicUrl(attID) + "/" + "/download.xml?token=" + ChatManager.getSessionToken()
I get the URL with blob + session token, then:
var intent = new android.content.Intent(android.content.Intent.ACTION_VIEW, android.net.Uri.parse(args.object.src));
intent.addCategory(android.content.Intent.CATEGORY_BROWSABLE);
application.android.startActivity.startActivity(intent);
In this way I successfully download .pdf files, but .doc, .docx, .xls and .xlsx return without extension.
I also tried getting the URL through privateUrl() (without interpolating the token), with the same result.
Another not working method:
httpModule.request({
url: uid,
method: 'GET',
headers: {
'QuickBlox-REST-API-Version': '0.1.0',
'QB-Token': ChatManager.getSessionToken()
}
}).then(res => {
var file = res.content.toFile();
var intent = new android.content.Intent(android.content.Intent.ACTION_VIEW);
var uri = android.net.Uri.fromFile(new java.io.File(file.path));
intent.setDataAndType(uri, 'application/pdf');
application.android.startActivity.startActivity(android.content.Intent.createChooser(intent, 'Apri file...'));
});
Any way I try, it feels like QuickBlox returns the extension on .pdf files only. Any suggestions?
UPDATE:
I tried opening the URL on different devices.
https://api.quickblox.com/blobs/[blobId]?token=[token]
On Chrome for Windows and iOS Safari, the file is downloaded or opened in browser correctly. On Android, it returns without extension on these browsers: Chrome e LineageOS stock browser. On Internet Samsung 7.4.00.70, it's opened in the browser correctly.
With httpModule.request(), I get this warning in the debug console on result:
Resource interpreted as Document but transferred with MIME type [my file mime type]
At the moment I am using this workaround in native code, but later I'll need to find something that works on iOS too.
I'm not marking this as an answer since it doesn't solve the problem
var r = new android.app.DownloadManager.Request(android.net.Uri.parse(args.object.src));
r.setDestinationInExternalPublicDir(android.os.Environment.DIRECTORY_DOWNLOADS, fileName.text);
r.allowScanningByMediaScanner();
r.setNotificationVisibility(android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
var dm = application.android.startActivity.getSystemService(android.content.Context.DOWNLOAD_SERVICE);
dm.enqueue(r);
So I have been at it for a while, and I really cannot get it to work. What I want is this:
To access some file outside the project folder through a WebView.
Here is some code that I have been trying to get it working:
String url = "file://///\\myProjectName" + Environment.getExternalStorageDirectory().toString()+ File.separator + "hw.html";
WebView webView = (WebView) findViewById(R.id.WebviewLOAD);
webView.loadUrl(url);
I just get a ERR_FILE_NOT_FOUND with any type of file. For a test-HTML file I created, I get this along with file not found error:
"The webpage at file:///myProjectName/storage/emulated/0/hw.html could not be loaded because"....
I tried removing Environment.getExternalStorageDirectory().toString() but then i just get file:///myProjectName/hw.html along with the file not found error.
So I want to navigate to the right file and be able to open it, but I just can't seem to get it right. I'm open for any suggestions?
So, basically you can't do this. Instead you want to run a local server in the background and make the WebView and server work together.
I did it with Jooby with an SQLite database.
Using the Android sample in the WebViewer folder I have an application in Android Studio which when run on my device works and displays the xod file given as expected. However I've tried to change the lines:
String documentPath = getFilesDir().getPath() + "/GettingStarted.xod";
InputStream in = getAssets().open("xod/GettingStarted.xod");
to
String documentPath = getFilesDir().getPath() + "/sample.pdf";
InputStream in = getAssets().open("xod/sample.pdf");
And have also changed the endsWith(".xod") to endsWith(".pdf") but I only get a grey screen. For this to work does the file have to be a .xod? As it works for xod files but not pdf files.
Thanks for your time.
Yes, for mobile viewing you need to convert your files to the web-optimized XOD format.
The PDF backend for WebViewer is not available for mobile browsers. This is due to limitations of the hardware and the mobile browsers.
For desktop browsers, to switch from XOD backend to PDF backend, you need to follow the steps. See here for more details, especially if you run into any errors.
var myWebViewer = new PDFTron.WebViewer({
path: "lib",
type: "html5",
documentType: "pdf",
initialDoc: "GettingStarted.pdf"
}, viewerElement);
Notice the documentType parameter is set to pdf.
I'm trying to post a notification that lets the user open a locally stored file. My code looks like this:
Intent notificationIntent = new Intent(Intent.ACTION_VIEW);
notificationIntent.setAction(android.content.Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(new File(filename));
notificationIntent.setData(uri);
Where "filename" is the full path to a locally stored file, usually in the /mnt/sdcard/download directory. The files I want to display are of various types: images, PDF documents, HTML, etc.
This works, but sometimes Android tries to open the file as the wrong type. For example, a jpeg file will open in a web browser view and instead of seeing the image, I see the binary data from the file displayed as text. Other times it works file. For example, some PDF files correctly open in a PDF viewer and some do not.
I'm not sure why this is. The documentation says I should not have to pass an explicit content type. If I do set the content type explicitly, things seem to work fine. The problem is, I don't always know what the content type should be (the file is downloaded from an external source and can be anything, and no, the MIME type is not in the HTTP headers, I checked for that).
What can I do here? Is there some function I can call with a filename to have Android return me the best content type for that file? Moreover, why is this not happening automatically when the Intent is processed?
Thanks.
You've most likely figured this out; I'm posting in case someone else is stuck on this. I do the following to get the mime-type of the file:
//Get the file path
Uri path = Uri.fromFile(file);
MimeTypeMap type_map = MimeTypeMap.getSingleton();
//Get the extension from the path
String extension = MimeTypeMap.getFileExtensionFromUrl(path.toString());
extension = extension.toLowerCase();
if (extension.contains(".")) {
extension = extension.substring(extension.lastIndexOf("."));
}
String mime_type = type_map.getMimeTypeFromExtension(extension);