1) Android's persistent file system defaults to the SD Card which everyone can read from while in iOS it defaults to a directory that only the app can read.
2) In order to play a Media file the path to a file in the www directory is different for Android and iOS.
So to smooth these difference over you can create a .json file that is included in your www directory which will hold platform specific configuration details and load it via XHR. Here's how to do it:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE HTML> | |
<html> | |
<head> | |
<meta name="viewport" content="width=320; user-scalable=no" /> | |
<meta http-equiv="Content-type" content="text/html; charset=utf-8"> | |
<title>PhoneGap Config Example</title> | |
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8"> | |
<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script> | |
<script type="text/javascript" charset="utf-8"> | |
// Global variables | |
// | |
var Config; | |
function onBodyLoad() { | |
document.addEventListener("deviceready",onDeviceReady,false); | |
}; | |
// PhoneGap is ready | |
// | |
function onDeviceReady(){ | |
var request = new XMLHttpRequest(); | |
request.open("GET", "config.json", true); | |
request.onreadystatechange = function(){//Call a function when the state changes. | |
console.log("state = " + request.readyState); | |
if (request.readyState == 4) { | |
if (request.status == 200 || request.status == 0) { | |
console.log("*" + request.responseText + "*"); | |
Config = JSON.parse(request.responseText); | |
var info = document.getElementById("info"); | |
info.innerHTML = "Default Path: " + Config.defaultPath + "<br/>" + | |
"Media Path: " + Config.mediaPath; | |
} | |
} | |
} | |
request.send(); | |
} | |
function playMedia() { | |
var my_media = new Media(Config.mediaPath + "test.mp3"); | |
my_media.play(); | |
} | |
</script> | |
</head> | |
<body onload="onBodyLoad();" id="stage" class="theme"> | |
<h1>Welcome to PhoneGap!</h1> | |
<h2>this file is located at assets/index.html</h2> | |
<div id="info"> | |
</div> | |
<a href="#" class="btn large" onclick="playMedia();">Play</a> | |
</body> | |
</html> |
Your .json file on Android could look like:
{
"mediaPath": "/android_asset/www/"
}
and on iOS it would look like;
{
"mediaPath": ""
}
So now you can replace clunky if statements like:
if (device.platform == "Android") { var my_media = new Media("/android_asset/www/test.mp3"); } else { var my_media = new Media("test.mp3"); }with:
var my_media = new Media(Config.mediaPath + "test.mp3");and continue to access everything in a cross platform way.
15 comments:
How about just in code ??:
function onDeviceReady(){
Config.mediaPath':(device.platform == "Android") ? "/android_asset/www/" : "";
}
@Jesse
Yeah, you could do that with the ternary operator but as you start to support more and more platforms like BB and WP7 it begins to be a pain.
Simon, what is the advantage of loading the extra configuration using XHR and not as a static file in the index.html?
@Juan,
There isn't really. I was just trying to illustrate how you could do this with XHR.
Hello Simon,
Great Post. Thanks.
What i m trying to do is download a file from a remore server and save it locally on the android device.
Using this:
window.requestFileSystem (with a PERSISTENT requst)
the rootPath that i get is /sdcard
(when an sdcard is available)
But what i would like to do is always get /data/{my package} as the rootPath. Wether there is an sdcard or not.
Is this possible by altering the configurations, as you did before?
Could you explain a little bit what i need to do?
Thanks.
@Zuko
Probably the easiest thing for you go do is to:
window.resolveLocalFileSystemURI("file:///data/data/{package name}", onSuccess, onError);
and the onSuccess method would be called with a DirectoryEntry that represents your internal storage. If you don't want to hard code the path in your html put it in a JSON file like I specify in this post.
How to store file(like doc, pdf) in the internal storage in android phonegap.And how to read that file from internal storage.?
@Pankaj Sharma
I would use the FileTransfer object to download the file to the file system. Then using the path you can load the file.
thanx simon :) i used the file transfer object to download that file and save it to the internal storage , i used the plugin (https://github.com/markeeftb/FileOpener) to read that file. but it giving me message that "this Document can not be opened". i think this plugin is only for teh local storage. can you tellme how to read the file if it is in the internal storage..?
@Pankaj Sharma
I did a quick look at that plugin and it should work just fine as long as you have an application installed that can open a file of that type.
thanx Simon for the reply , but it still not working for me.
i used these line of code to open downloaded file window.plugins.fileOpener.open("file:///data/data/com.example.cordove_filedownload/ATT.pdf"); or
window.plugins.fileOpener.open("/data/data/com.example.cordove_filedownload/ATT.pdf"); then its giving me Toast message with "This document can not be opened."
if i use window.plugins.fileOpener.open("file:///mnt/sdcard/ATT.pdf"); then it will opening that pdf file in the reader. but not in case of internal storage.
@Pankaj Sharma
Oh, I see now. Yes, this makes perfect sense. When you fire an intent from an Android program you are actually starting a whole new program. Your app and the app that reads the pdf are run as two separate user ids. When the file is on the /sdcard the file permissions are world readable but when you store the file in /data/data/{package name} the files are only readable by your app.
If you want to be able to serve files from the apps internal directory you will need to either create a content resolver or write a PDF viewer that executes inside your app instead of being an external program.
thanx Simon :) Is their any plugin for Content Resolver , that i directly use in my application to open a file from the internal storage. oe else i have to create my own content resolver.
plz give me some idea How to create Content Resolver ?
@Pankaj Sharma
No, there is not Content Provider plugin that I know of, you'll have to expose one yourself.
https://developer.android.com/guide/topics/providers/content-providers.html
Elegant, thank you. Check out hooks in case, your .json files get deleted after_build
Post a Comment