We have an Android app, which we deploy by opening a browser on the device go to the customer url, then the browser downloads the file. We are also trying to download a separate .xml settings file. If I try this with in the browser, the xml will just display. In the Android app, could I copy the xml from the cache?
Is there any other way of downloading the xml?
Could I use a different file type, which the browser would download?
Thanks
Here's a method to download an xml file from a URL
try {
//set the download URL, a url that points to a file
URL url = new URL("http://your/path/to/file.xml");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
//set the path where we want to save the file
File SDCardRoot = Environment.getExternalStorageDirectory();
//create a new file, specifying the path, and the filename
//which we want to save the file as.
File file = new File(SDCardRoot,"data.xml");
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(file);
//this will be used in reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file
int totalSize = urlConnection.getContentLength();
progressDialog.setMax(totalSize);
//variable to store total downloaded bytes
int downloadedSize = 0;
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
//now, read through the input buffer and write the contents to the file
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
//add the data in the buffer to the file in the file output stream (the file on the sd card
fileOutput.write(buffer, 0, bufferLength);
//add up the size so we know how much is downloaded
downloadedSize += bufferLength;
}
//close the output stream when done
fileOutput.close();
//catch some possible errors...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You should probably do this in the background, i.e. use an AsyncTasc.
If you need to load a small xml file the Document class is fairly straight forward to use. You can use an http get request to grab the xml file. Here is a simple function you can call, pass in a url, and get a xml document object you can dig into:
public static Document getXML(final String url) throws ExecutionException, InterruptedException {
Document out = null;
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Document> result = executor.submit(new Callable<Document>() {
public Document call() throws Exception {
HttpGet uri = new HttpGet(url);
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse resp = null;
try {
resp = client.execute(uri);
} catch (IOException e) {
e.printStackTrace();
}
StatusLine status = resp.getStatusLine();
if (status.getStatusCode() != 200) {
Log.d("http error", "HTTP error, invalid server status code: " + resp.getStatusLine());
}
// try {
HttpEntity entity = resp.getEntity();
InputStream in = entity.getContent();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document dom = null;
try {
dom = builder.parse(in);
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return dom;
}
});
try {
out = result.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return out;
}
Related
I have a resource file in my /res/raw/ folder (/res/raw/textfile.txt) which I am trying to read from my android app for processing.
public static void main(String[] args) {
File file = new File("res/raw/textfile.txt");
FileInputStream fis = null;
BufferedInputStream bis = null;
DataInputStream dis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
while (dis.available() != 0) {
// Do something with file
Log.d("GAME", dis.readLine());
}
fis.close();
bis.close();
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I have tried different path syntax but always get a java.io.FileNotFoundException error. How can I access /res/raw/textfile.txt for processing? Is File file = new File("res/raw/textfile.txt"); the wrong method in Android?
***** Answer: *****
// Call the LoadText method and pass it the resourceId
LoadText(R.raw.textfile);
public void LoadText(int resourceId) {
// The InputStream opens the resourceId and sends it to the buffer
InputStream is = this.getResources().openRawResource(resourceId);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String readLine = null;
try {
// While the BufferedReader readLine is not null
while ((readLine = br.readLine()) != null) {
Log.d("TEXT", readLine);
}
// Close the InputStream and BufferedReader
is.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Note this will return nothing, but will print the contents line by line as a DEBUG string in the log.
If you have a file in res/raw/textfile.txt from your Activity/Widget call:
getResources().openRawResource(...) returns an InputStream
The dots should actually be an integer found in R.raw... corresponding to your filename, possibly R.raw.textfile (it's usually the name of the file without extension)
new BufferedInputStream(getResources().openRawResource(...)); then read the content of the file as a stream
This is what doing to read from a .txt file in my android activity. Though the app runs, I find that no file is created/appended. In logcat following line is shown,
java.io.FileNotFoundException: /home/Desktop/RiaC_android/Test/app/src/main/assets/SampleFile.txt: open failed: ENOENT (No such file or directory)
The code I'm currently using, though I have tried before,
BufferedWriter out = new BufferedWriter(
new FileWriter("test_File.txt"));
however, the result remains same.
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.widget.TextView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView)findViewById(R.id.textView);
File testFile = new File("/home/Desktop/RiaC_android/Test/app/src/main/assets", "SampleFile.txt");
FileWriter writer = null;
try {
writer = new FileWriter(testFile, true);
writer.write("Hello File!!");
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
if (testFile.exists())
tv.setText("File created!!");
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
Any suggestions about what I'm doing wrong?
You can't write file to assets folder.The assets folder is read-only at runtime. Pick a different location to save your data. ie , Environment.getExternalStorageDirectory() don't use Environment.getExternalStorageDirectory().getAbsolutePath().
For reading files from asset use the following method
public String readFromAsset(String fileName, Context context) {
StringBuilder returnString = new StringBuilder();
InputStream fIn = null;
InputStreamReader isr = null;
BufferedReader input = null;
try {
fIn = context.getResources().getAssets()
.open(fileName, Context.MODE_WORLD_READABLE);
isr = new InputStreamReader(fIn);
input = new BufferedReader(isr);
String line = "";
while ((line = input.readLine()) != null) {
returnString.append(line);
}
} catch (Exception e) {
e.getMessage();
} finally {
try {
if (isr != null)
isr.close();
if (fIn != null)
fIn.close();
if (input != null)
input.close();
} catch (Exception e2) {
e2.getMessage();
}
}
return returnString.toString();
}
You can't write to /asset directory because it is read-only.
The assets folder is like folders res, src, gen, etc. These are all useful to provide different files as input to build system to generate APK file for your app.
All these are read-only while your app is running. At run-time you can write to SD card.
You do not access assets/ at runtime using File. You access assets/ at runtime using AssetManager, which you can get via getResources().getAssets().
To read from /asset folder, use the following code:
AssetManager assetManager = getResources().getAssets();
InputStream inputStream = null;
try {
inputStream = assetManager.open("SampleFile.txt");
if ( inputStream != null)
Log.d("TAG", "It worked!");
} catch (Exception e) {
e.printStackTrace();
}
You cannot modify files in asset folder. just think them readonly files.
If you want to create text file and modify them, create a file using getExternalCacheDir and new File method.
public static File CreateTextFile(Context context, String filename) throws IOException {
final File root = context.getExternalCacheDir();
return new File(root, filename);
}
EDIT APPENDED BELOW
1. To write text simply, do as below
String text = "bla bla";
FileWriter writer=null;
try {
File file = CreateTextFile("something.txt"); // proposed method
if(!file.exists())
file.createNewFile();
writer = new FileWriter(file);
/** Saving the contents to the file*/
writer.write(text);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
2. To read cache file,
Check this link: https://stackoverflow.com/a/5971667/361100
3. One more example
Below example is to write fetched text from internet.
String webUrl = "http://www.yourdata.com/data.txt";
try {
URL url = new URL(webUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);
urlConnection.connect();
File file = CreateTextFile("something.txt"); // proposed method
if(!file.exists())
file.createNewFile();
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ;
}
fileOutput.close();
if(downloadedSize==totalSize)
filepath=file.getPath();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
filepath=null;
}
i am using below code for downloading pdf file from server and store into sdcard. its running fine on android 4.4 device. while its not working on android 5.0.2 device.
public static String downloadFile(String fileUrl, File directory){
try {
URL url = new URL(fileUrl);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(false);
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(directory);
int totalSize = urlConnection.getContentLength();
byte[] buffer = new byte[MEGABYTE];
int bufferLength = 0;
while((bufferLength = inputStream.read(buffer))>0 ){
fileOutputStream.write(buffer, 0, bufferLength);
}
fileOutputStream.close();
result = "true";
} catch (FileNotFoundException e) {
e.printStackTrace();
result = "false";
} catch (MalformedURLException e) {
e.printStackTrace();
result = "false";
} catch (IOException e) {
e.printStackTrace();
result = "false";
}
return result;
}
On Line: InputStream inputStream = urlConnection.getInputStream(); i got java.io.FileNotFoundException error.
i tried so many things but didnt work. help me to solved this bug.
So my latest app runs into this problem where it complains in the logcat that theres no room left on the device to save files but that is definitely not the case as I can close my app open the stock camera and take a picture. How has everybody else dealt with this problem.
Edit: The error occurs in this method
private void writeFile(Bitmap bmp, File f) {
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
bmp.compress(Bitmap.CompressFormat.PNG, 80, out);//<---error here
} catch (NullPointerException e) {
e.printStackTrace();
Log.w("nullpointerException on image error", "nullpointer");
} catch (FileNotFoundException e) {
Log.w("fileNotfoundException on image error", "filenotfound");
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
try { if (out != null ) out.close(); }
catch(Exception ex) {}
}
}
and this is the logcat report on this error:
java.io.IOException: no space left on device
at org.apache.harmony.luni.platform.OSFileSystem.write(Native Method)
at dalvik.system.BlockGuard$WrappedFileSystem.write(BlockGuard.java:171)
at java.io.FileOutputStream.write(FileOutputStream.java:300)
at android.graphics.Bitmap.nativeCompress(Native Method)
at data.ImageManager.writeFile(ImageManager.java:215)
at data.ImageManager.getBitmap(ImageManager.java:192)
at data.ImageManager.access$1(ImageManger.java:102)
at data.ImageManager$ImageQueueManager.run(ImageManager.java:290)
at java.lang.Thread.run(Thread.java:1019)
Edit: Heres how I though you create a directory on external memory
This is what Im using to create the place that I thought would be the sd card
String sdState = android.os.Environment.getExternalStorageState();
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();
cacheDir = new File(sdDir,"data/gr");
}
else
cacheDir = context.getExternalCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
if(sdState.equals(android.os.Environment.MEDIA_MOUNTED)){
File adSdDir = android.os.Environment.getExternalStorageDirectory();
adCacheDir = new File(adSdDir,"data/ad");
}else
adCacheDir = context.getExternalCacheDir();
if(!adCacheDir.exists())
adCacheDir.mkdirs();
}
and then in the method that I look for or create the image to go into the directory:
private Bitmap getBitmap(ImgRequestObj ids) {
String url = null;
String filename = ids.objId.toString();
File f = null;
try{
if(ids.objName.equals("mark")){
url = graffMarksURL;
f = new File(cacheDir, filename);
}else if(ids.objName.equals("admark")){
url = adMarksURL;
f = new File(adCacheDir, filename);
}
// Is the bitmap in our cache?
Bitmap bitmap = BitmapFactory.decodeFile(f.getPath());
if(bitmap != null) return bitmap;
// Nope, have to download it
try {
BitmapFactory.Options bfOptions=new BitmapFactory.Options();
bfOptions.inDither=false; //Disable Dithering mode
bfOptions.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
bfOptions.inInputShareable=true; //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
DefaultHttpClient client;
HttpResponse response = null;
HttpParams params = null;// new Http parameters to be used for extra buffering room in VM
HttpPost post = null;
InputStream is = null;
BufferedInputStream bis = null;
Bitmap bmp = null;
ArrayList<NameValuePair> nvp1 = new ArrayList<NameValuePair>();
nvp1.add(new BasicNameValuePair("id", ids.objId.toString()));
// - martin passing id to php script select statement
client = new DefaultHttpClient();
try {
post = new HttpPost(url);
params = post.getParams();//Setting the new Http params to post
post.setEntity(new UrlEncodedFormEntity(nvp1));
try{
HttpConnectionParams.setSocketBufferSize(params, 8192);//Defining the new buffer size
response = client.execute(post);
}
catch(HttpResponseException e){
e.getCause();
}
//Capture response from query and prepare as input
HttpEntity entity = response.getEntity();
// move content to Input Stream
is = entity.getContent();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bis = new BufferedInputStream(is);
try{
bmp = BitmapFactory.decodeStream(bis, null, bfOptions);
}finally{}
if( is != null )
try {
is.close();
//response = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Log.w("inputstream of image closed", "for this image "+id.toString());
if( bis != null )
try {
//response = null;
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bitmap = bmp;
writeFile(bitmap, f);
try{
bmp = null;
}catch(NullPointerException e){
e.printStackTrace();
}
return bitmap;}
catch(Exception e){
e.printStackTrace();
}
return bitmap;
}catch(NullPointerException e){
e.printStackTrace();
}
return null;
}
you are actually using internal memory by using getCacheDir() in your else statement. However, if you want to store large data then its recommended to use getExternalCacheDir() because not all android phones have huge internal storage, but they do/may have bigger external storage.
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = context.getExternalCacheDir();
cacheDir = new File(sdDir,"data");
}
else
Log.e("storage", "SD card not found");
I ended up changing my code where I create my directories to the following:
String sdState = android.os.Environment.getExternalStorageState();
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();
cacheDir = new File(sdDir,"data/gr");
}
else
cacheDir = context.getExternalFilesDir(sdState); <--changed
if(!cacheDir.exists())
cacheDir.mkdirs();
if(sdState.equals(android.os.Environment.MEDIA_MOUNTED)){
File adSdDir = android.os.Environment.getExternalStorageDirectory();
adCacheDir = new File(adSdDir,"data/ad");
}else
adCacheDir = context.getExternalFilesDir(sdState); <--changed
if(!adCacheDir.exists())
adCacheDir.mkdirs();
}
So far using this I am able to once again save images I take with the camera with all the images in my area download.
I am getting MalformedURLexception in the following code, and i have no idea, whats causing it.
public void down(String url)
{ try {
URL url1 = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) url1.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File SDCardRoot = Environment.getExternalStorageDirectory();
//create a new file, specifying the path, and the filename
//which we want to save the file as.
File file = new File(SDCardRoot,"somefile.ext");
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
//add up the size so we know how much is downloaded
downloadedSize += bufferLength;
//report progress
}
fileOutput.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
It says unknown protocol.
The connection is totally fine unti the reading part comes up,
before that the code is even printing right size of the file.
Also the file i am trying to download has a url like
http://download12.aomethin.com/blaa-blaa
If i try to add www, the request starts redirecting.
Although i think this might be a noobish but I also want to know how to get the name of this file and save file with that name instead of the one i choose.
Edit: the program is working now i just need to know how do i get the right name of the file. And make this a background process.
downloading on the main thread is not a good practice; you should implement it on a new thread; because while downloading, the main thread is busy for downloading the file. If the waiting time be more than expected the system will generate "Not responding" error.
In order to do that you can use "TaskAsync" or "IntentService" or even making a new thread. though, I suggest [TaskAsync] as it is easy to implement.
here is a good practice to set the file name yourself:
public void downloadClicked() {
InputStream in = null;
FileOutputStream f = null;
try {
String path ="ftp://administrator:password#131.164.140.118:21/MyShedule.zip";
String targetFileName = "MyShedule.zip";
URL u = new URL(path);
URLConnection c = u.openConnection();
c.setDoOutput(true);
c.connect();
String string = Environment.getExternalStorageDirectory().getPath().toString();
in = c.getInputStream();
f = new FileOutputStream(new File(string +"/kidsLibrary/"+ targetFileName));
IOUtils.copy(in, f);
} catch (MalformedURLException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} catch (ProtocolException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} catch (FileNotFoundException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} catch (IOException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(f);
}
}