In my application, I need to get the current exchange rates for different currencies. As it has been suggested by this, this and this question a nice way to do it, is to use the Yahoo Finance service.
So, when I want to find, for example, the rate between USD and Canadian dollars, I simply send this link: http://download.finance.yahoo.com/d/quotes.csv?s=USDCAD=X&f=sl1d1t1ba&e=.csv
This is working fine for both my Motorola Atrix phone with Android 2.3.4 and the emulator again with Google API 2.3.3. However, when I try the exact same link from a Galaxy SII with Android ICS 4.0 and an emulator with Google API 4.0, in both cases the quotes.csv file contains only the "Missing Symbols List".
After digging around, I found out that this response can happen in case the rates were not found. But this response is for ANY currency I try under Android 4.0 (either Galaxy SII or emulator). Hence, I cannot get the rates with Android 4.0, but I can with Android 2.x.
Does anyone have experienced the same problem? Is there any workaround?
EDIT: This is the thread code that deals with downloading rates from the Yahoo Currency Service:
//show the progress dialog
downloadingDialog.show();
Runnable getRates = new Runnable() {
public void run(){
dataNotFound = false;
final String baseDir = getApplicationContext().getFilesDir().getAbsolutePath();
//download the rates from yahoo to a CSV file
downloadFileViaHTTP (baseDir);
//read the file line
String filePath = baseDir + "/" + "quotes.csv";
Log.d(tag, "-> filePath = " + filePath);
try {
// open the file for reading
InputStream instream = new FileInputStream(filePath);
// if file the available for reading
if (instream != null) {
// prepare the file for reading
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
//read the line
String fileLine = buffreader.readLine();
Log.d(tag, "fileLine = " + fileLine);
instream.close();
}
}
catch (Exception ex) {
// print stack trace.
}
}
};
final Thread t = new Thread(getRates);
t.start();
And this is my function for downloading the quotes.csv file from the Yahoo site:
public void downloadFileViaHTTP (String localPath) {
Log.d(tag, "downloadFileViaHTTP...");
try {
//this is the Yahoo url
String urlFile = "http://download.finance.yahoo.com/d/quotes.csv?s=" + fromCurrency + toCurrency + "=X&f=sl1d1t1ba&e=.csv";
Log.d(tag,"urlFile = " + urlFile);
URL url = new URL(urlFile);
//create the new connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
//pointer to the downloaded file path
String localFileName = localPath + "/" + "quotes.csv";
//this is the actual downloaded file
File MyFilePtrDest = new File(localFileName);
Log.d(tag,"localFileName = " + localFileName);
//this will be used in reading the data from the Internet
InputStream inputStream = urlConnection.getInputStream();
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(MyFilePtrDest);
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
//write buffer contents to 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);
}
inputStream.close();
//close the output stream when done
fileOutput.flush();
fileOutput.close();
urlConnection.disconnect();
}
catch (IOException e) {
//data were not found
dataNotFound = true;
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This is the log from the Google API 2.3.3 emulator:
12-18 11:04:24.091: D/CurrencyConverter(414): downloadFileViaHTTP...
12-18 11:04:24.091: D/CurrencyConverter(414): urlFile = http://download.finance.yahoo.com/d/quotes.csv?s=EURUSD=X&f=sl1d1t1ba&e=.csv
12-18 11:04:24.282: D/CurrencyConverter(414): localFileName = /data/data/com.myapps.currencyconverter/files/quotes.csv
12-18 11:04:24.461: D/CurrencyConverter(414): -> filePath = /data/data/com.myapps.currencyconverter/files/quotes.csv
12-18 11:04:24.461: D/CurrencyConverter(414): fileLine = "EURUSD=X",1.3172,"12/18/2012","4:03am",1.317,1.3174
And this is the log from the Google API 4.0 emulator:
12-18 11:47:36.130: D/CurrencyConverter(668): downloadFileViaHTTP...
12-18 11:47:36.130: D/CurrencyConverter(668): urlFile = http://download.finance.yahoo.com/d/quotes.csv?s=EURUSD=X&f=sl1d1t1ba&e=.csv
12-18 11:47:36.449: D/dalvikvm(668): GC_CONCURRENT freed 306K, 4% free 11714K/12167K, paused 5ms+10ms
12-18 11:47:36.951: D/CurrencyConverter(668): localFileName = /data/data/com.myapps.currencyconverter/files/quotes.csv
12-18 11:47:37.159: D/CurrencyConverter(668): -> filePath = /data/data/com.myapps.currencyconverter/files/quotes.csv
12-18 11:47:37.159: D/CurrencyConverter(668): fileLine = Missing Symbols List.
As you can see the "fileLine" String variable, in the first case it gets the proper rates, while at the second, the quotes.csv file merely contains the "Missing Symbols List." value.
EDIT2: I have uploaded to a shared folder the complete Android project, so everyone can try it. You may compile and run with both Android 2.x and 4 emulators (or phones if you have :-))
EDIT3: Although this is not a direct answer, still it is a workaround. I use the Google currency calculator instead of the Yahoo one. To use the Google currency calculator, simply change the Yahoo url with this one: http://www.google.com/ig/calculator?hl=en&q=1" + fromCurrency + "=?" + toCurrency. Click this link to see an example of converting 78 Euros to USDs. I checked and it works with both Android versions. However if anyone finds out why this is happening with the Yahoo site, it would be good to share it with us..
Try to remove urlConnection.setDoOutput(true); when you run in ICS. Because ICS turns GET request to POST when setDoOutput(true).
This problem is reported here and here
Related
In the last few days, my Android app is suddenly failing to download files from a web server to store in the app. This is the same for all users I have contacted. It was previously working in Android 11, so it's something that has only just changed. It's a (free) niche app for UK glider pilots to process NOTAMS, and has relatively large number of users who I don't want to let down.
The published app uses getExternalFilesDir(null) to return the directory in which to store the downloaded files, with android:requestLegacyExternalStorage set to "true" in the manifest.
I changed getExternalFilesDir(null) to getFilesDir() in Android Studio since that's what I understand should now be used for internal app data files. This returns /data/user/0/(my package name)/files. I'm running the Pixel 2 API 30 emulator for debugging, and the File Explorer shows that /data/data/(my package name)/files directory has been created. Everything I've read on here says that this is what is supposed to happen and it should all work. However no file was created when I attempted the download.
I changed android:requestLegacyExternalStorage to "false", and this time a file was created as expected. However it was empty and the download thread was giving an exception "unexpected end of stream on com.android.okhttp.Address#89599f3f".
This is the relevant code in my DownloadFile class which runs as a separate thread (comments removed for compactness):
public class DownloadFile implements Runnable
{
private String mUrlString;
private String mFileName;
private CountDownLatch mLatch;
public DownloadFile(String urlString, String fileName, CountDownLatch latch)
{
mUrlString = urlString;
mFileName = fileName;
mLatch = latch;
}
public void run()
{
HttpURLConnection urlConnection = null;
// Note for StackOverflow: following is a public static variable defined in the main activity
Spine.mDownloadStatus = false;
try
{
URL url = new URL(mUrlString);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
urlConnection.connect();
File file = new File(Spine.dataDir, mFileName);
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
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);
}
fileOutput.close();
Spine.mDownloadStatus = true;
}
// catch some possible errors...
catch (IOException e)
{
Spine.mErrorString = e.getMessage();
}
if (urlConnection != null)
urlConnection.disconnect();
// Signal completion
mLatch.countDown();
}
}
I now believe the problem lies with the URL connection, rather than the changes to local file storage access which is what I first thought. Incidentally, if I enter the full URL into my web browser the complete text file is displayed OK, so it's not a problem with the server.
The problem has been narrowed down to changes to the functionality of the website that hosts the data files to be downloaded. It's been made https secure and they are currently working on further changes.
I temporarily moved the hosting to my own website in Android Studio and everything worked so it's down to those website changes and nothing to do with my code (at least it may need changing later to support the upgrade to the main hosting site).
Thanks to all for responding.
I am implementing the UniMag credit card slider API on Xamarin Android so my app can read credit cards. The API is only for native Android so I followed the instructions here to create a wrapper around the API's .jar file. That works great and is super simple.
I can initialize the api and get listener callbacks when connecting and disconnecting the slider device. Since not all Android devices are supported by the API the UniMagReader needs to read a provided config xml file.
The problem I am having is that I cannot get the API to read the file.
The API call to use for this is;
var reader = new UniMagReader(new UniMagMessage(), Android.App.Application.Context);
reader.SetSaveLogEnable(false);
reader.SetVerboseLoggingEnable(true);
reader.RegisterListen();
string fileNameWithPath = GetConfigurationFileFromRaw();
reader.SetXMLFileNameWithPath(fileNameWithPath);
reader.LoadingConfigurationXMLFile(false);
I have tried putting the file in the Resources.Raw, Resources.Assets and the Root directories and tried a few ways of providing the URL to the API.
This is the way the demo app suggests:
private string GetXMLFileFromRaw(string fileName)
{
//the target filename in the application path
string fileNameWithPath = null;
fileNameWithPath = fileName;
try
{
//using (var inStream = Android.App.Application.Context.Assets.Open("default_config.xml")) // assest file access
using (var inStream = Android.App.Application.Context.Resources.OpenRawResource(Resource.Raw.default_config)) // raw file access
{
var length = GetStreamLength(inStream);
byte[] buffer = new byte[length];
inStream.Read(buffer, 0, (int)length);
inStream.Close();
Android.App.Application.Context.DeleteFile(fileNameWithPath);
var fout = Android.App.Application.Context.OpenFileOutput(fileNameWithPath, Android.Content.FileCreationMode.Private);
fout.Write(buffer, 0, (int)length);
fout.Close();
// to refer to the application path
var fileDir = Android.App.Application.Context.FilesDir;
fileNameWithPath = fileDir.Parent + Path.DirectorySeparatorChar + fileDir.Name;
fileNameWithPath += Path.DirectorySeparatorChar + "default_config.xml";
}
}
catch (System.Exception e)
{
fileNameWithPath = null;
}
return fileNameWithPath;
}
// Return the length of a stream that does not have a usable Length property
public static long GetStreamLength(Stream stream)
{
long originalPosition = 0;
long totalBytesRead = 0;
if (stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = 0;
}
try
{
byte[] readBuffer = new byte[4096];
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, 0, 4096)) > 0)
{
totalBytesRead += bytesRead;
}
}
finally
{
if (stream.CanSeek)
{
stream.Position = originalPosition;
}
}
return totalBytesRead;
}
And this is another way I tried:
var file = new Java.IO.File(Android.Net.Uri.Parse("file:///default_config.xml").ToString());
var uri = file.AbsolutePath;
The errors I am getting are coming from the API. When connecting the swiper to the device I see:
[UMSDK] SDK: headset attached
[UMSDK] SDK: reader attached, but no config loaded
From the OnReceiveMsgFailureInfo Callback I see "The XML file does not exist and the auto update disabled."
And in the Application Output I see:
[UMSDK] UmXmlParser: parsing XML failed due to exception
[UMSDK] org.apache.harmony.xml.ExpatParser$ParseException: At line 1, column 0: not well-formed (invalid token)
[UMSDK] at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:519)
[UMSDK] at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:478)
[UMSDK] at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:316)
[UMSDK] at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:279)
[UMSDK] at com.idtechproducts.acom.AcomXmlParser.parseFile(AcomXmlParser.java:91)
[UMSDK] at com.idtechproducts.unimagsdk.UniMagConfigHelper.loadingXMLFile(UniMagConfigHelper.java:116)
[UMSDK] at com.idtechproducts.unimagsdk.UniMagConfigHelper.loadingXMLFile(UniMagConfigHelper.java:46)
[UMSDK] at IDTech.MSR.uniMag.uniMagReader.loadingConfigurationXMLFile(uniMagReader.java:496)
The sample has the file placed in the Assets or Raw folder. To use a file that is in the Assets or Raw folders, you have to get a stream and then write that stream to a file that is accessible outside of the app itself (any file added to the app's project in the IDE ends up packaged within the APK itself so is not accessible by any thing outside of the APK itself). The Java sample you sent does do just that (copied from the sample in your post, but abbreviated to only show specific lines):
private string GetXMLFileFromRaw(string fileName)
{
...
try
{
// Gets the stream from the raw resource
using (var inStream = Android.App.Application.Context.Resources.OpenRawResource(Resource.Raw.default_config)) // raw file access
{
// Reads the stream into a buffer
...
inStream.Read(buffer, 0, (int)length);
...
// Deletes any existing file
Android.App.Application.Context.DeleteFile(fileNameWithPath);
// Writes the stream to a file
...
fout.Write(buffer, 0, (int)length);
...
}
}
...
}
So first set up the file name and path variables:
string filename = "default_config.xml";
string directory = Android.App.Application.Context.FilesDir.AbsolutePath;
string fullPath = Path.Combine(directory, filename);
string xmlFileContents;
Then get a stream.
If default_config.xml file in assets:
using (StreamReader sr = new StreamReader(Assets.Open(filename)))
If default_config.xml in Raw resources:
using (StreamReader sr = new StreamReader(Resources.OpenRawResource(Resource.Raw.default_config))
Then do the following:
{
xmlFileContents = sr.ReadToEnd();
if (File.Exists(fullPath)) {
File.Delete(fullPath);
}
File.WriteAllText(fullPath, xmlFileContents);
}
Then you can pass fullPath to the API:
reader.SetXMLFileNameWithPath(fullPath);
I have the following problem:
I develop a .zip file download with .pdf selected inside a function on c#.
The function creates the .zip file on a temp folder on the server and the HTTP Response return this file.
This function works great when is called from windows, and IOS. But when I call this function on Android it never downloads the file.
On the server I see that the function create the .zip file again and again when it's called from android browser (chrome, dolphin...) and it's never returned.
The strange thing is that I could run it well when I selected 90 .pdf files (although the function is called twice for no reason), but when I select 140 (or more) the issue happens again.
Here is the code:
**string dirName = Utiles.GetNewName();
zipName += ".ZIP\"";
string urlRet = _mSTempPath + #"\" + dirName + ".ZIP";
string urlDelete = _mSTempPath + #"\" + dirName;
System.IO.Stream iStream = null;
// Total bytes to read:
long dataToRead;
//HttpResponse resp = _page.Response;
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
using (ZipFile zip = new ZipFile())
{
foreach (string url in filesURLs)
{
zip.AddFile(url,"");
}
zip.Save(_mSTempPath + #"\" + dirName + ".ZIP");
}
// Open the file.
iStream = new System.IO.FileStream(urlRet, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=\"" + zipName);
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AddHeader("content-length", dataToRead.ToString());
HttpContext.Current.Response.BufferOutput = true;
HttpContext.Current.Response.TransmitFile(urlRet);
HttpContext.Current.Response.Flush();**
Please, I will be very grateful if anyone can help.
Thanks again!
After 2 days of research, I didn't found any solution to my problem :/
I want to download an mp3 file, which is returned only after calling a URL in a browser.
I can't give you the actual url because I'm not allowed to due to rights restrictions, but it is of the form:
http://wscompany.name.com/downloadws/getDlFile/mdkHdKy97RppVWOsIOdDBuG/audio/1478
As you can see, this URL doesn't have the mp3 extension. So if I put this kind of URL in a browser on windows, it returns an MP3 to save onto the disk, which is fine. But if I want to call this URL in android in order to download the final file returned (the mp3), it doesn't work.
I tried with a url containing a mp3 file directly and it works very well (like http://www.mediacollege.com/downloads/sound-effects/urban/factory/Factory_External_01.mp3), but not with an url without the mp3 extension, even though it does returns an mp3, I hope you see what I mean.
Does anyone know how to do that in android ?
Here is my code, using an AsyncTask, called by
new Download(MyActivity.this, urlToCall).execute();
And the Download AsyncTask :
public class Download extends AsyncTask<String, Void, String>
{
ProgressDialog mProgressDialog;
Context context;
String urlDownload;
public Download(Context context,String url)
{
this.context = context;
this.urlDownload=url;
}
protected void onPreExecute()
{
mProgressDialog = ProgressDialog.show(context, "","Please wait, Download for " + urlDownload );
Log.v("DOWNLOAD", "Wait for downloading url : " + urlDownload);
}
protected String doInBackground(String... params)
{
try
{
//URL url = new URL("http://www.mediacollege.com/downloads/sound-effects/urban/factory/Factory_External_01.mp3");
URL url = new URL(urlDownload);
Log.w( "DOWNLOAD" , "URL TO CALL : " + url.toString());
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File folder = new File(Environment.getExternalStorageDirectory()+ "/MyDownloaded/") ;
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
File file = new File(folder,"somefile.mp3");
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file
int totalSize = urlConnection.getContentLength();
//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;
//this is where you would do something to report the prgress, like this maybe
//updateProgress(downloadedSize, totalSize);
Log.w( "DOWNLOAD" , "progress " + downloadedSize + " / " + totalSize);
}
//close the output stream when done
fileOutput.close();
//catch some possible errors...
}
catch (MalformedURLException e)
{
Log.e( "DOWNLOAD" , "ERROR : " + e );
}
catch (IOException e)
{
Log.e( "DOWNLOAD" , "ERROR : " + e );
}
return "done";
}
private void publishProgress( int i )
{
Log.v("DOWNLOAD", "PROGRESS ... " + i);
}
protected void onPostExecute(String result)
{
if (result.equals("done"))
mProgressDialog.dismiss();
}
Thank you in advance, I hope someone will help me :)
DevJ
More than likely the initial URL contains a status 302 redirect to ANOTHER page that actually hosts or provides the mp3. There is a Java library called Jsoup that you can use to get to the actual mp3 file and download it. So let's say you have the initial URL of:
http://wscompany.name.com/downloadws/getDlFile/mdkHdKy97RppVWOsIOdDBuG/audio/1478
The first thing you should do is open up your browser, right click anywhere on the screen and choose "inspect element" or something similar so that you can monitor the network traffic. With the inspect element pane open, enter the above URL and you should see that it first goes to that URL (shows a status of 302 redirect), then goes to ANOTHER URL (possibly), before ending up at the destination (with a status 200). The status 200 page is the actual page you want. You can enter the above URL in Jsoup like this:
Document doc = Jsoup.connect("http://wscompany.name.com/downloadws/getDlFile/mdkHdKy97RppVWOsIOdDBuG/audio/1478").followredirect(true).header("","").header("",""). ...etc .post() or .get();
It returns a Document object (read the Jsoup documentation). This Document object can be parsed to get certain data...like OTHER URLs that you can also pass to the Jsoup.connect method, until you get to the actual mp3 you want to download with Android.
It will be important to look at the request headers listed in the "inspect element" pane and add those headers to the .connect() method by chaining them with multiple .header() methods.
I know this response is 2 years too late, but hopefully it will be helpful for anyone still needing to do what you were attempting.
You can use a network sniffer (like Wireshark) on desktop PC to see what exactly happens when requesting the MP3. My guess is that there is a redirect to another URL.
For several weeks, we've been fighting an issue that's been discussed on SO before, but without a working answer in the specific case we've encountered. So after re-reading dozens of threads and trying all the code folks offered, I'm asking for your assistance, please. (BTW, forget asking Samsung: they proved way less than helpful. )
OS : 4.0.x through 4.2.x (API lvls 14 - 17)
Devices : Samsung S3 which have /storage/sdcard0 (all we tested do.)
... as opposed to the older /mnt/sdcard or /storage/sdcard (note lack of trailing zero).
Use any flavor of
Environment.getExternalStorageDirectory().getAbsolutePath();
// e.g .getPath() .getName() etc.
// or
Environment.getExternalStoragePublicDirectory() ...
or use a media URI to inform system of file location. (Astounding that THAT fails too.)
Now save a file - you'll see it show up in the DDMS file explorer. And you can pull it via ADB to verify. But just try reading that same file back in - using the same app that you wrote it with in the first place ! ENOENT - file not found. Hardcode the path, append '/external_sd/' to the path the os call gives above (Sumsung says this is needed - but it doesn't do squat.)
Change 'sdcard0' to 'sdcard' as some have suggested ... tried all that too. ZILCH.
Permissions, etc are all correct of course ( since when could a process write a file but not read it !?) .
USB cable connected or not, debug mode or not, "real app" vs developer app (untrusted app) - results all the same: ENOENT )
Any ideas or suggestions on how to proceed here?
(With a sledge hammer in hand, staring intently at a new SG3 ... And, SAMSUNG, if you are reading this: "/storage/sdcard0/external_sd/myFileFoo.txt" does NOT work.)
/**
*
* [Edit - added sample of failing code, as requested]
*/
public void testFile () {
ImageView image ;
String m_Path = "/SamsuxS3/" ; // more fun than a barrel of NULLs
String m_MyFile = "myFileFoo.jpg" ;
image = (ImageView) findViewById ( R.id.imageView1 ) ;
//// Test 0:
m_Path = Environment.getExternalStorageDirectory().getAbsolutePath() ;
//// Test 1:
// String getPath = Environment.getExternalStorageDirectory().getPath(); // fails
// m_Path = getPath ;
//// Test 2:
// String getName = Environment.getExternalStorageDirectory().getName() ; //fails
// m_Path = getName ;
//// Test 3:
// String defPics = Environment.DIRECTORY_PICTURES; // fails
// m_Path = m_path + "/" + defPics + "/" ;
//// Test 4:
// m_Path = "/storage/sdcard0/" ; // fails
//// Test 5:
// m_Path = "/storage/sdcard0/external_sd/" // Samsung says so, but it fails too.
//// Test 6: now we're really hacking ...
// m_Path = "/storage/sdcard/" // Fails (although sdcard is mounted as sdcard0 - hmmm)
InputStream fIn = null;
File fileIn = new File(m_Path, m_MyFile);
try { //// This is only one way many attempts...
//// 1) just grab an image from a known resource,
//// 2) try to save it,
//// 3) then read it back into an ImageView.
//// External storage must be mounted or this fails.
InputStream is = getResources().openRawResource(R.drawable.somepicture) ; // works
OutputStream os = new FileOutputStream(fileIn); // OK
byte[] data = new byte[is.available()]; // OK
is.read(data); // OK
os.write(data); // OK - DDMS file explorer verfied
is.close();
os.close();
} catch (IOException e) {
Log.d("Error writing to " + m_Path, e.toString()); // never happened yet
}
//// now we step into the SamDung
////
InputStream fIn2 = null; //// Well, it's redundant but ...
File fileIn2 = new File(m_Path, m_MyFile);
try {
fIn2 = new FileInputStream (fileIn2) ;
//
// Here be the Dragons...
//
// Next line WORKS on every device EXCEPT a Samsung - blows up w/ ENOENT !
//
image.setImageBitmap ( BitmapFactory.decodeStream(fIn2) );
fIn2.close ();
} catch (Exception IOError) {
Log.d("WTF? I'm not moving to Korea: ", IOError.toString()) ;
}
}
The proper way to write a file on Android for Android 3.0+, where you intend to use the file again quickly, is:
os.flush();
os.getFD().sync();
os.close();
for a FileOutputStream named os.
Using this change, your example code works with Environment.getExternalStorageDirectory(), on a Samsung Galaxy S3, running Android 4.1.2.