Flutter open local asset (PDF) in native application - dart

I am trying to bundle my app with a PDF, and let the user open it in the native viewer.
I have tried:
Copying the data for the PDF to the "Temporary Directory" or the "Document Directory" (from path_provider) and opening from there
To open I am using 'url_launcher' to open the file. I have tried using both file://... urls and just passing the local path ie /.../ etc
The files definitely exist, it seems to be a permissions issue that the files in both locations, in both platforms, are in the app's sandbox.
The file definitely exists, and I can open PDFs from web URLs.
is this something flutter can do?
Update 12/8/19
I just got pinged by SO that this question has had a bunch of views and no good answers. For this project I ultimately tried Cordova, Flutter, React Native and eventually gave up and created two native apps to do what I needed to do. They worked OK but the client wanted to make a bunch of UX changes.
So in the end I wrapped the code from the native side of things into a flutter plugin and then did the UX in flutter. Thats the backstory, here is the technical specs of what I hacked together:
For iOS there was an example of using their PDF kit in iOS 11 from github, I did some work there and there was a bunch of manually created features in the repo, so I attached the PDFs I wanted to that project, and wrote a script to present them, then used the flutter bridge to launch.
For Android it was much the same - I copied the files from the app bundle (not flutter assets) to a temp directory and then created a share link and launched the pdf using the native system viewer.
All in all it was a massive stuff around, no fault of Flutter's though, like I said, I used a bunch of multi platform frameworks and none of them would accomplish the job in a satisfactory way. Im sure a better dev could come up with a workable solution though.
Edit: It has been mentioned to use a combination of url_launcher and open_file. They work great for external files but do not work for bundled assets.

I'm not quite sure if this is still a problem for you. But as I wanted to know the same thing, I tried to figure it out. Here is my result, but I have to mention, that I stored my file in the download folder:
install url_launcher and simple_permissions
add the following lines to your AndroidManifest.xml and the corresponding iOS equivalent:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Code for creating pdf:
SimplePermissions.requestPermission(Permission.WriteExternalStorage);
String dir = (await getExternalStorageDirectory()).path + "/download";
String filename = "$dir/" + title;
File f = new File(filename);
f.writeAsBytesSync(data);
Code for opening the file
var url = 'file://' + f.path;
if (await canLaunch(url)) {
await launch(url, forceSafariVC: false, forceWebView: false);
} else {
throw 'Could not launch $url';
}

Related

WebView.LoadHtml file access error Android 30 Xamarin

I have a Hybrid app I rebuilt after setting the Target Android version to API 30, per a new warning that Google now requires this, and am trying it on a Tablet with Android 11. Originally following an old hybrid sample app, my app copies files from the resources to the file system. This seems to work, as no exceptions are thrown from the File operations. The first thing it does is display a splash screen from an HTML file copied from the afore-mentioned resource copy, using the LoadHtml function of a created WebView, and giving it a URL formatted like this:
file:///data/data/com.mycompanyname.myappnameandroid/files/Content/Splash.html
LoadHtml doesn't throw an exception, but then the screen displays an error message referencing this path and the error "ERR_ACCESS_DENIED". This file does reference CSS files copied to the same directory (referenced like "<link rel="stylesheet" href="site.css" />
" in the HTML header). It will continue on to display the main app pages, but it apparently failed to load CSS files and so forth, as all the styling and scripting is missing. What do I need to change to make this work?
Searching, I find talk of "Scoped Storage", but I can't make any sense of it. I'm hoping there is a simple fix.
There is a simple fix. Add the following to your set up of the WebView:
webView.Settings.AllowFileAccess = true;
Apparently the default changed from true to false.
Thanks to this posting for the clue: Load file into webView with scoped storage

native script: WebView Interface plugin unable to find local resource

I am using webViewInterface plugin in nativescript 8 with webpack v5 I am trying to launch local downloaded file ex. video, audio, HTML files
I am able to download those files but while running that file with the help of webview I am getting
file not found
chromium: [INFO:CONSOLE(1)] "Uncaught TypeError: Cannot read property '_onNativeEvent' of undefined", source: chrome-error://chromewebdata/
In NativeScript, by default, the tilde (~) marks the app root folder (note the App and not the Project!). So if my file is located in <project-name>/app/index.html then I need to set a path like this ~/index.html.
this was working fine with natviescript v6 but after upgrading to nativescript v8 it broke.
can anyone please help???
The app folder is read-only on iOS (at least, on real devices, not necessarily on emulators). You'll need to download the files to either the temp or documents folder and then access from there.
As a reference, see my own struggle with this issue.
OK i have what seems to be the same issue. In my case when i migrated from nativescript 7 to 8 the webpack.config.ts was cleaned up.
In there was something useful that copied all my webview files.
I added some code to my webpack.config.js and now it seems to work
"src" is the folder containing my webview folder.
const webpack = require("#nativescript/webpack");
module.exports = (env) => {
webpack.init(env);
webpack.Utils.addCopyRule({
from: 'webviews/**',
context : 'src'
})
return webpack.resolveConfig();
};
The doc I used.
NS 8 : https://docs.nativescript.org/webpack.html#adding-a-copy-rule
Previous plugin used : https://webpack.js.org/plugins/copy-webpack-plugin/

How to view files(docx, ppt, xlsx, etc.) from my project’s assets in flutter?

Im working on a flutter app that needs to view document files. Is there a way to open or view document files from my assets?
FlutterPdfViewer.loadAsset(filepath) works fine but OpenFile.open(filepath) only works with files within the phone’s storage.
I can’t find any packages to view other file types besides pdf files from my project’s assets. Are there other ways? I hope you can help me.
I had the same problem and didn't find a solution, so I think, that open_file plugin calls a native app to open a file. That's why you can't open a file from assets using other application.
I think that you have to save that file in storage, after that call open_file OpenFile.open() method.

How to deploy arbitrary resources for React Native with CodePush

I'm using CodePush to deploy the js bundle and a couple of resources to my react-native iOS app. Instead of using the react-native bundler to collect all the static images from my project I have a build step that just copies a folder called "static" into release/assets. But beside the "static" folder I als have other folders in release/assets that contain images and videos wich are use dynamically in the app via uri (e.g. { uri: 'assets/images/myImage.jpg' }). When building the app in XCode I just include the assets folder in the package.
From the CodePush documentation I gather that deploying the release folder should update all my assets. But it doesn't.
I downloaded the xcappdata via XCode and there you can see, that CodePush downloaded everything and stored it in /Library/Application Support/CodePush/[id]/release. But it still doesn't show up in the app.
Any ideas? Do I misunderstand the functionality of CodePush?
As you've seen, when you release a directory to the CodePush server via the CLI, it will round trip the entire contents of it to end-user's devices when they perform an update check/synchronization. That said, just because a file is in that update doesn't mean it will be useable unfortunately.
The behavior that you're seeing is actually a limitation of the way that the Image component resolves URIs in React Native. If you use the assets system to specify the "source" property (via a require("image.png") call), it will look for that file relative to the currently running JS bundle. This is how CodePush allows updating images, because as long as our plugin places the "assets" folder next to the JS bundle file on disk, the <Image> component will naturally find them.
However, when you specify an object with a URI (as you're doing) as the value of the "source" property, the Image component looks for that file relative to the binary on disk, and therefore, it will never look for it where it was placed by CodePush when you update them.
Because of this, CodePush only supports updating images which are loading via the require syntax. I'll make sure to update our docs to clarify that. Apologies for the confusion!

Cordova iOS: Load videos with downloaded html's and video files

I have the following issue:
I have an iOS Cordova Application.
The application download a zip file and decompress it in "cdvfile://localhost/persistent/content/myfolder" by ussing the following Cordova plugins: org.apache.cordova.file-transfer, org.apache.cordova.file and https://github.com/MobileChromeApps/zip.git
Inside the zip there is an "index.html" file with "video tags" on it.
I was able to succesfully load and execute the "index.html" file, but the video doesn't load.
I know that the video file was decompressed successfully because:
I check the file inside my iPad.
I embed the video in the index of the cordova app (not the downloaded one) in the following way and it works:
var videocontainer = document.getElementsByTagName('video')[0];
var videosource = document.getElementsByTagName('source')[0];
var newmp4 = cordova.file.documentsDirectory + 'content/myfolder/videos/myvideo.mp4';
videosource.setAttribute('src', newmp4);
videocontainer.load();
videocontainer.play();
But, the video is not loaded/played inside the downloaded HTML file. To understand what I'm doing, I have to develop an application that will be updated by downloading its contents from zips, and the contents includes pages with videos embeded on them. It works on PC and Android, but not in iOS.
I tried the following things:
Loading the page in "_self". The page is displayed but not the video.
Loading the page in an iframe. Same result.
Loading the page within an inAppBrowser (plugin). Same result.
Video tag with source src="videos/myvideo.mp4" (works in Web and Android). Same result.
Video tag with source src="./videos/myvideo.mp4" (works in Web and Android). Same result.
Video tag with source src= cordova.file.documentsDirectory + 'content/myfolder/videos/myvideo.mp4' (with JS, by passing the path in a query string, same path that works in the root index.html as I described before). Same result.
Video tag with source src= cordova.file.documentsDirectory + 'cdvfile://localhost/persistent/content/myfolder/videos/myvideo.mp4'. Same result.
All the combination of previous things. Same result....
Loading the downloaded resources in a DIV is not an option, because the resources (images, css, javascripts, audios, videos, etc.) are downloaded on other iOS device's folder: the app's Documents' folder (cdvfile://localhost/persistent/).
I thing I tried almost everything... Why is not trivial to play a video tag, inside an html, that are both in the app's Documents' folder???
:-(
EDIT 1: Cordova Version = 3.6.3
Solution Founded!!
In almost all the android and iOS examples, downloaded content is being executed from "cordova.file.documentsDirectory".
Then, when you link this content in a or (by using AJAX), everything works fine (CSS, images, links) but media tags ( and ).
Again, I dont know why, but almost all the examples downloads and unzip contents by using this path.
After several days being blocked with this issue (I found lots of forums where the devs have to modify all their projects by using plugins like Cordova Media, jaeger25 Html5Video, etc, etc), I tried by using the following path: "cordova.file.dataDirectory"
I download, unzip and execute the HTMLs from this path and everything works with no parsing/modifications to the HTML files (that in my case were thousands). 100% compability with and tags with relative sources' path in an IFRAME!!!!!!
I guess you code the video links into the index.html inside the zip you decompress on the device.
Those links need to get "updated" with some javascript parser, BEFORE you actually load or navigate to this page in your phonegap app.
If your example is caused in Android, you definetly need to include the HTML5 Video plugin here:
https://github.com/jaeger25/Html5Video
On iOS the tag will work for local files. But the links need to be absolute.
And the links will change if you recompile your app or reinstall it.
The files will be available, but the APP ID will have changed and the absolute path also.
Example of an iOS path:
/var/mobile/Applications/<application UUID>/Documents/path/to/file
Hope you solved your problem.

Resources