I am trying to save data into a text file that does not yet exist online, but my urlConnection.getResponseCode() is returning a 404. I can read from files with similar urls, so I'm pretty certain the url is correct, but I've never written to an online file before.
private class SaveFile extends AsyncTask<String, Void, String> {
private String scheme = "http";
private String authority = "172.16.0.45";
private String path1 = "PrivateFile";
private String path2 = "SavedInstances";
protected void onPreExecute() {
}
protected String doInBackground(String...params) {
String result = null;
String filename = params[0] + ".txt";
String location = params[1];
OutputStream outStream = null;
HttpURLConnection urlConnection = null;
try {
// Save online as opposed to internal storage
if (location.equals("on")) {
Uri.Builder builder = new Uri.Builder();
builder.scheme(scheme);
builder.authority(authority);
builder.appendPath(path1);
builder.appendPath(path2);
builder.appendPath(filename);
String _url = builder.build().toString();
URL url = new URL(_url);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
if (urlConnection.getResponseCode() != 200) // Runs as true
throw new IOException(Integer.toString(urlConnection.getResponseCode()));
else {
outStream = urlConnection.getOutputStream();
}
} else if (location.equals("in")) {// Saving to internal
File file = new File(getFilesDir(), filename);
outStream = new FileOutputStream(file);
}
// Writing the file
PrintWriter writer = new PrintWriter(outStream);
writer.println(utils.size());
writer.println(trans.size());
writer.println(cables.size());
for (int i = 0; i < utils.size(); i++)
writer.println(utils.get(i).getValues());
for (int i = 0; i < trans.size(); i++)
writer.println(trans.get(i).getValues());
for (int i = 0; i < cables.size(); i++)
writer.println(cables.get(i).getValues());
writer.close();
outStream.close();
if (urlConnection != null)
urlConnection.disconnect();
result = "Save Successful";
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (MalformedURLException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
result = e.getMessage();// 404
System.out.println(e.getMessage());
}
return result;
}
protected void onPostExecute(String result) {
Toast.makeText(getApplicationContext(),result,Toast.LENGTH_SHORT).show();
}
}
When I send the exception with getResponseMessage() instead, the message is "not found". What am I missing to get this connection working?
Related
I tried using many codes I've found for downloading files with an AsyncTask with no success yet.
I get an error on the logcat: E/Error:: No such file or directory.
Despite looking for solutions for this error, couldn't find What's missing or wrong.
This is the doInBackground method in which I assume something is missing/wrong:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new DownloadJSON().execute("http://api.androidhive.info/json/movies.json");
}
protected String doInBackground(String...fileUrl) {
int count;
try {
String root = "data/data/com.example.jsonapp2";
URL url = new URL(fileUrl[0]);
URLConnection connection = url.openConnection();
connection.connect();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
File fileName = new File(root+"/movies.json");
boolean existsOrNot = fileName.createNewFile(); // if file already exists will do nothing
// Output stream to write file
OutputStream output = new FileOutputStream(fileName,false);
byte data[] = new byte[1024];
System.out.println("Downloading");
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
Thanks.
Didn't want to bombard with redundant code. If some other code is needed, I'd love to provide it.
UPDATED ANSWER
this is working for me, write file in local storage and read it again on method PostExecute
class DownloadJSON extends AsyncTask<String, Void, Void>{
String fileName;
String responseTxt;
String inputLine;
String folder;
#Override
protected Void doInBackground(String... strings) {
try {
String root = "data/data/com.example.jsonapp2";
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
//Set methods and timeouts
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(15000);
urlConnection.setConnectTimeout(15000);
urlConnection.connect();
//Create a new InputStreamReader
InputStreamReader streamReader = new
InputStreamReader(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
StringBuilder response = new StringBuilder();
//Check if the line we are reading is not null
while((inputLine = reader.readLine()) != null){
response.append(inputLine);
}
//Close our InputStream and Buffered reader
reader.close();
streamReader.close();
responseTxt = response.toString();
Log.d(TAG, "doInBackground: responseText " + responseTxt);
// PREPARE FOR WRITE FILE TO DEVICE DIRECTORY
FileOutputStream fos = null;
fileName = "fileName.json";
folder = fileFolderDirectory();
try {
fos = new FileOutputStream(new File(folder + fileName));
//fos = openFileOutput(folder + fileName, MODE_PRIVATE);
fos.write(responseTxt.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos != null){
fos.close();
}
}
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// -- THIS METHOD IS USED TO ENSURE YOUR FILE AVAILABLE INSIDE LOCAL DIRECTORY -- //
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(folder +fileName));
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String text;
while ((text = br.readLine()) != null) {
sb.append(text).append("\n");
}
Toast.makeText(TestActivity.this, "result " + sb.toString(), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ops, almost forget this method
public static String fileFolderDirectory() {
String folder = Environment.getExternalStorageDirectory() + File.separator + "write_your_app_name" + File.separator;
File directory = new File(folder);
if(!directory.exists()){
directory.mkdirs();
}
return folder;
}
Your root is wrong
String root = "data/data/package.appname";
make sure your root contains right package name or file path.
package name which should be your application id
I am learning Android and porting my Windows app to Android platform. I need an advice how to download a small text file and read content of this file.
I have following code in my Windows app, I need to rewrite it for Android app:
string contents = "file.txt";
string neturl = "http://www.example.com/file.txt";
HttpClient client = new HttpClient();
try {
HttpResponseMessage message = await client.GetAsync(neturl);
StorageFolder folderForFile = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile fileWithContent = await folderForFile.CreateFileAsync(channels, CreationCollisionOption.ReplaceExisting);
byte[] bytesToWrite = await message.Content.ReadAsByteArrayAsync();
await FileIO.WriteBytesAsync(fileWithContent, bytesToWrite);
var file = await folderForFile.GetFileAsync(contents);
var text = await FileIO.ReadLinesAsync(file);
foreach (var textItem in text)
{
string[] words = textItem.Split(',');
...
I have found what on Android I need to create following class for async download
public class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// download the file
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream
OutputStream output = new FileOutputStream("file.txt");
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
In the code above I try to download file and name it as "file.txt", but get exception 'FileNotFoundException file.txt open failed: EROFS (Read-only file system)", I need to save it internally (I do not want to let users to see this file in the file explorers) and rewrite file if it exists.
And I try to execute this task and read file
void DownloadAndReadContent() {
new DownloadFileFromURL().execute("http://www.example.com/file.txt");
try {
BufferedReader br = new BufferedReader(new InputStreamReader(openFileInput("file.txt")));
String str = "";
while ((str = br.readLine()) != null) {
Log.d(LOG_TAG, str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
so downloading to SD card is working
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
InputStream input = new BufferedInputStream(url.openStream(), 8192);
File SDCardRoot = Environment.getExternalStorageDirectory();
SDCardRoot = new File(SDCardRoot.getAbsolutePath() + "/plus");
SDCardRoot.mkdir();
File file = new File(SDCardRoot,"settings.dat");
FileOutputStream output = new FileOutputStream(file);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
and reading:
new DownloadFileFromURL().execute("http://www.example.com/file.txt");
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
Log.d(LOG_TAG, "SD n\a " + Environment.getExternalStorageState());
return;
}
File sdPath = Environment.getExternalStorageDirectory();
sdPath = new File(sdPath.getAbsolutePath() + "/plus");
File sdFile = new File(sdPath, "settings.dat");
try {
BufferedReader br = new BufferedReader(new FileReader(sdFile));
String str = "";
while ((str = br.readLine()) != null) {
String[] words = str.split(",");
// do some work
}
}
Log.d(LOG_TAG, str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
i follow more explain in this site for download mp3 or picture from URL , I follow more method and try to write my method but when i run application it stop.
I make method to query download when click
also put permission for INTERNET & WRITE_EXTERNAL_STORAGE
put the problem is still
this method is download
public static void downloadMain(){
File fileToSave = null;
String scrPath ="http://***";
BufferedInputStream bis;
BufferedOutputStream bos;
fileToSave = new File(Environment.getExternalStorageDirectory().getPath() +"/"+ "A"+"/");
if (!fileToSave.exists())
fileToSave.mkdirs();
fileToSave = new File(Environment.getExternalStorageDirectory().getPath() +"/"+ "A" +"/" + "h"+"/");
if (!fileToSave.exists())
fileToSave.mkdirs();
File file = new File (fileToSave,"***.mp3");
try{
URL url = new URL(scrPath+"***.mp3");
URLConnection ucon = url.openConnection();
ucon.connect();
bis=new BufferedInputStream(ucon.getInputStream());
bos = new BufferedOutputStream(new FileOutputStream(file));
bis=new BufferedInputStream(url.openStream());
byte[] data = new byte[1024];
int a =0;
while(true){
int k = bis.read(data);
if(k==-1){
bis.close();
bos.flush();
bos.close();
break;
}
bos.write(data, 0, k);
a+=k;
}
}catch(IOException e){}
}
I have three main perplexity about your program:
Do you run the following code in an asynctask? (this must run asincronusly otherwise it will block)
Why it loop infinitly?
You couldn't open an url or a file named with a '*' inside of it
Edit:
You must run the download method asincronusly otherwise it wouldn't work, interaction with filesystem and network couldn't be done in the main thread
Edit2:
AsyncTask should be something like this
private class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
// download the file
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/file_name.extension");//put here your path and your mkdirs
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
#Override
protected void onPostExecute(String result) {
if (result != null)
Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
}
}
And you shoould call it like this
DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");
You could also have a look at this answer
I need sometimes read XML file from remote server, and replace data in XML on my Android device.
I read data through XmlPullParser:
XmlPullParser users;
try {
URL xmlUrl = new URL("http://xx.xx.xx.xx/1.xml");
users = XmlPullParserFactory.newInstance().newPullParser();
users.setInput(xmlUrl.openStream(), null);
}
How can I replace it on Android?
Simply use this code, it's overwrites the file with the new file you download from the internet.
public static boolean downloadFile(String fileToDownload, File newPath,
String newFileName) {
try {
URL url = new URL(fileToDownload);
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
if (!newPath.isDirectory()) {
CreateLog.createFolder(newPath.toString());
}
File file = new File(newPath.toString() + "/" + newFileName);
if (!file.isFile()) {
CreateLog.writeLogToFile(newPath.toString() + newFileName,
"%TEMP%");
}
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
}
fileOutput.close();
return true;
} catch (MalformedURLException e) {
CreateLog.addToLog(e.toString());
return false;
} catch (IOException e) {
CreateLog.addToLog(e.toString());
return false;
}
}
public static void createFolder(String filePath) {
File createFolder = new File(filePath);
createFolder.mkdirs();
}
A cleaner method is to use a Asynctask, the code runs in a new thread. But it's a bit harder to code.
private class GetProblems extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
for (String myUrl : params) {
try {
URL url = new URL(myUrl);
URLConnection ucon = url.openConnection();
ucon.setRequestProperty("Accept", "application/xml");
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
String str = new String(baf.toByteArray(), "UTF8");
return str;
} catch (MalformedURLException e) {
CreateLog.addToLog("[GetProblems] " + e.toString());
} catch (IOException e) {
CreateLog.addToLog("[GetProblems] " + e.toString());
}
}
return "error";
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// updateProgressBar(values[0]);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
...write result to a file
}
}
Run the AsyncTask code:
new GetProblems().execute("http://myurl.com/xmlfile.xml");
I am using Dropbox in my project to get tiny url from dropbox which is like http://www.db.tt/xyzabc.
When I try to download the file in HTC My touch my code works fine, but if I try in Motorola Atrix it throws exception unknown host db.tt.
Actually first I have url like http://www.db.tt/xyzabc which is HTTP url I open it than I get exception and in exception I get actual url to file which contain file and is HTTPS url in exception. I start downloading file here is my code which work for me:
public static void fileUrl(String fAddress, String localFileName,
String destinationDir) {
OutputStream outStream = null;
URLConnection uCon = null;
InputStream is = null;
try {
URL url;
byte[] buf;
int ByteRead, ByteWritten = 0;
url = new URL(fAddress);
outStream = new BufferedOutputStream(new FileOutputStream(
destinationDir + localFileName));
try {
// Here i have "http://www.db.tt/xyzabc"
// after i hit url i get exception and in exception that
// FileNotFoundException at https://www.dropbox.com/abcxyz
// i get actual actual url i parse that exception and
//retrive https://www.dropbox.com/xyzabc(actual url)
// but in motorolla atrix instead of that url i get
// unknownhost exception "db.tt"
uCon = url.openConnection();
// uCon.connect();
is = uCon.getInputStream();
} catch (Exception e) {
url = new URL(e.getMessage().substring(
e.getMessage().indexOf("https"),
e.getMessage().length()));
outStream = new BufferedOutputStream(new FileOutputStream(
destinationDir + localFileName));
uCon = url.openConnection();
is = uCon.getInputStream();
}
buf = new byte[size];
while ((ByteRead = is.read(buf)) != -1) {
outStream.write(buf, 0, ByteRead);
ByteWritten += ByteRead;
}
System.out.println("Downloaded Successfully.");
System.out.println("File name:\"" + localFileName
+ "\"\nNo ofbytes :" + ByteWritten);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
ok after few attempt i made it solve my self and here is the solution will be helpfull if someone got same problem it requires some error handling and modification according to need
After seeing class heirarchy of Connection i found that HttpsURLConnection is child of HttpURLConnection and HttpURLConnection is child of UrlConnection so i i used HTTPConnection instead of UrlConnection and as HttpsUrlConnection is concrete for HttpsUrlConnection it solved my problem
i continue iterating till i get Https url after redirect
public static void fileUrl(String fAddress, String localFileName,
String destinationDir) {
OutputStream outStream = null;
URLConnection uCon = null;
HttpURLConnection mHttpCon;
InputStream is = null;
try {
URL url;
byte[] buf;
int ByteRead, ByteWritten = 0;
url = new URL(fAddress);
outStream = new BufferedOutputStream(new FileOutputStream(
destinationDir + localFileName));
try {
mHttpCon = (HttpURLConnection) url.openConnection();
while (!url.toString().startsWith("https")) {
mHttpCon.getResponseCode();
url = mHttpCon.getURL();
mHttpCon = (HttpURLConnection) url.openConnection();
}
is = mHttpCon.getInputStream();
} catch (Exception e) {
e.printStackTrace();
// url = new URL(e.getMessage().substring(
// e.getMessage().indexOf("https"),
// e.getMessage().length()));
// outStream = new BufferedOutputStream(new FileOutputStream(
// destinationDir + localFileName));
//
// uCon = url.openConnection();
// is = uCon.getInputStream();
}
buf = new byte[size];
while ((ByteRead = is.read(buf)) != -1) {
outStream.write(buf, 0, ByteRead);
ByteWritten += ByteRead;
}
System.out.println("Downloaded Successfully.");
System.out.println("File name:\"" + localFileName
+ "\"\nNo ofbytes :" + ByteWritten);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void fileDownload(String fAddress, String destinationDir) {
int slashIndex = fAddress.lastIndexOf('/');
int periodIndex = fAddress.lastIndexOf('.');
String fileName = fAddress.substring(slashIndex + 1);
if (periodIndex >= 1 && slashIndex >= 0
&& slashIndex < fAddress.length() - 1) {
fileUrl(fAddress, fileName, destinationDir);
} else {
System.err.println("path or file name.");
}
}
This answer works - to an extent. I have a similar solution here
There is still a problem with Dropbox short hyperlinks on Atrix. They redirect from http to https but NOT to the required file, instead I get a whole lot of html from inside Dropbox.