I am prepared code for download images from server and store in sdcard.For that i have prepared code,
URL url;
try {
url = new URL("http://myserver_path/applikaza/appstore/apks/ScrResoluton/scrresolution.jpg");
input = url.openStream();
String storagePath = Environment.getExternalStorageDirectory().toString();
String basepath = storagePath + "/Guayama/" + folderName;
output = new FileOutputStream(basepath + "/home.png");
byte[] buffer = new byte[5000];
int bytesRead = 0;
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
output.write(buffer, 0, bytesRead);
}
} catch (MalformedURLException e) { // TODO Auto-generated catch block
e.printStackTrace();
} finally {
output.close();
input.close();
}
but got NullPointerException at output.close().I think done mistake some where .please help me.
The reason you get a NullPointerException at output.close() is because your URL is incorrectly formed. For starters, it doesn't contain a valid protocol. This will cause MalformedURLException to be thrown on the line
url = new URL("E:/Suresh/images/home.png");
and you'll then go straight to the catch block, followed by the finally block which calls output.close(), but output is null since the line
output = new FileOutputStream(basepath + "/home.png");
was never executed.
You need to correct your URL (see the description here) and you need to correct your exception handling, as in the case of MalformedURLException, this will only ever be thrown where you set the value of url, and so you will never have a non-null value for output or input when your "finally" block is executed.
Your URL should probably be of the form "http://something/Suresh/images/home.png" or maybe "file://something/Suresh/images/home.png". If the home.png file is located on another machine to the Android device, try and access it via a web browser and use the URL shown by the web browser complete with "http://".
Related
I am trying to get the Logcat (at least last few lines) on a button click but nothing comes up -
view.findViewById(R.id.logdone).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Make file name.
String fullName = "userlogs";
// Extract to file.
File file = new File(fullName);
InputStreamReader reader = null;
FileWriter writer = null;
try
{
// get input stream
String cmd = "logcat -d -v time";
Process process = Runtime.getRuntime().exec(cmd);
reader = new InputStreamReader (process.getInputStream());
// write output stream
writer = new FileWriter (file);
char[] buffer = new char[10000];
do
{
int n = reader.read (buffer, 0, buffer.length);
if (n == -1)
break;
writer.write (buffer, 0, n);
} while (true);
reader.close();
writer.close();
}
catch (IOException e)
{
if (writer != null)
try {
writer.close();
} catch (IOException e1) {
}
if (reader != null)
try {
reader.close();
} catch (IOException e1) {
}
e.printStackTrace();
return;
}
}
}
NOTE:
I do have permissions -
<uses-permission android:name="android.permission.READ_LOGS" />
UPDATE:
My most of the content is in Log.d() then Log.v() then Log.e() then Log.i(). But how to get the last event lines on a button click. My purpose is to get those lines and send them via email to the developer.
I am using the popular third party API known as ACRA to send email which is working fine.
I can use StringBuilder to put all my device logs into it and then to send via email.
But I am unable to get.
Any elegant way that works well effectively ?
Given the comment I made about the READ_LOGS permission no longer being granted to non-system apps, I would instead recommend using a MemoryHandler with a standard Java Logger. On a button click, you can push the messages to a target StreamHandler (which you can use to just dump them into the output buffer of your choice).
Is it possible to get the last few lines of a logcat on a button click?
There has never been a documented and supported way for apps to get anything from LogCat. And, as Turix notes, things were locked down further in Android 4.2.
Any elegant way that works well effectively ?
Log the data yourself to a file that you control, rather than (or in addition to) logging the data to LogCat.
I have an app for Android which downloads hundreds of files from the Internet. Some files turn out to be 0-byte after download. The app attempts to detect such cases and delete such files after download but sometimes it fails. The problem is more frequent on Android 4.x devices.
Here is the method which does the downloading. I gets the number of actually read bytes from inputStream.read(buffer).
public class Utils
{
public static class DownloadFileData
{
int nTotalSize;
int nDownloadedSize;
}
public interface ProgressCallback
{
void onProgress(long nCurrent, long nMax);
}
public static boolean downloadFile(String sFileURL, File whereToSave, DownloadFileData fileData, ProgressCallback progressCallback)
{
InputStream inputStream = null;
FileOutputStream fileOutput = null;
try
{
URL url = new URL(sFileURL);
URLConnection connection = url.openConnection();
//set up some things on the connection
connection.setDoOutput(true);
connection.connect();
fileOutput = new FileOutputStream(whereToSave);
inputStream = connection.getInputStream();
fileData.nTotalSize = connection.getContentLength();
fileData.nDownloadedSize = 0;
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)
{
// if interrupted, don't download the file further and return
// also restore the interrupted flag so that the caller stopped also
if (Thread.interrupted())
{
Thread.currentThread().interrupt();
return false;
}
// add the data in the buffer to the file in the file output stream
fileOutput.write(buffer, 0, bufferLength);
// add up the size so we know how much is downloaded
fileData.nDownloadedSize += bufferLength;
if (null != progressCallback && fileData.nTotalSize > 0)
{
progressCallback.onProgress(fileData.nDownloadedSize, fileData.nTotalSize);
}
}
return true;
}
catch (FileNotFoundException e)
{
return false; // swallow a 404
}
catch (IOException e)
{
return false; // swallow a 404
}
catch (Throwable e)
{
return false;
}
finally
{
// in any case close input and output streams
if (null != inputStream)
{
try
{
inputStream.close();
inputStream = null;
}
catch (Exception e)
{
}
}
if (null != fileOutput)
{
try
{
fileOutput.close();
fileOutput = null;
}
catch (Exception e)
{
}
}
}
}
Here is the piece of code which processes the downloads. Since sometimes the number of read bytes is incorrect (it is > 0 and the real file has the size 0 bytes) I check the size of the downloaded file with outputFile.length(). But this again gives a value > 0 even though the file is really 0 byte. I tried to also just create a new file and read its size with recheckSizeFile.length(). Still the size is determined as > 0 while it's really 0 byte.
Utils.DownloadFileData fileData = new Utils.DownloadFileData();
boolean bDownloadedSuccessully = Utils.downloadFile(app.sCurrenltyDownloadedFile, outputFile, fileData, new Utils.ProgressCallback()
{
... // progress bar is updated here
});
if (bDownloadedSuccessully)
{
boolean bIsGarbage = false;
File recheckSizeFile = new File(sFullPath);
long nDownloadedFileSize = Math.min(recheckSizeFile.length(), Math.min(outputFile.length(), fileData.nDownloadedSize));
// if the file is 0bytes, it's garbage
if (0 == nDownloadedFileSize)
{
bIsGarbage = true;
}
// if this is a video and if of suspiciously small size, it's
// garbage, too
else if (Utils.isStringEndingWith(app.sCurrenltyDownloadedFile, App.VIDEO_FILE_EXTENSIONS) && nDownloadedFileSize < Constants.MIN_NON_GARBAGE_VIDEO_FILE_SIZE)
{
bIsGarbage = true;
}
if (bIsGarbage)
{
++app.nFilesGarbage;
app.updateLastMessageInDownloadLog("File is fake, deleting: " + app.sCurrenltyDownloadedFile);
// delete the garbage file
if (null != outputFile)
{
if (!outputFile.delete())
{
Log.e("MyService", "Failed to delete garbage file " + app.sCurrenltyDownloadedFile);
}
}
}
else
{
... // process the normally downloaded file
}
I am not sure but I think there is a bug in Android with reading file size. Has anyone seen a similar problem? Or am I maybe doing something wrong here?
Thanks!
EDIT: how i determine that the files are 0-byte:
all the files which get downloaded go thru the described routines. When I then later view the download folder with a file browser (Ghost Commander), some of the files (like maybe 10%) are 0-byte. They can't be played by a video player (shown as "broken file" icon).
It looks to me like your problem is that you only check for "garbage" files if the Utils.downloadFile call returns true. If the download fails in the getInputStream call or the first read, you will have created a file with zero length which will never be deleted.
You should call flush() on your FileOutputStream to ensure that all data is written to the file. This should make your issue with 0-byte files occur less often.
To check for 0 byte files using File.length() should work properly. Can you open a shell (adb shell) on the device and run ls -l to see the byte count displayed by it is 0 (maybe your file manager has some weird issues). Also please debug (or put some log statements) that sFullPath contains the correct file paths. I can't see where sFullPath gets set in your code above and why you don't just use outputFile but recreate another File object.
From my Android app I try to download from the windows Azure blob storage using the following URL: http://iclyps.blob.core.windows.net/broadcasts/23_6.mp4
The resulting file is corrupt when I download it from within my app. Same error occurs when I download it using the default Browser or Chrome. Also from the Easy Downloader app, the same error occurs. Only a download from my PC or using Firefox Beta from the Android device (or emulator), the file is retrieved correctly.
I use the following code (snippet):
try {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
//and connect!
urlConnection.connect();
bis = new BufferedInputStream(urlConnection.getInputStream(), BUFSIZE);
bos = new BufferedOutputStream(
context.openFileOutput(TMPFILE, Context.MODE_PRIVATE), BUFSIZE);
/*
* Read bytes to the buffer in chunks of BUFSIZE bytes until there is nothing more to read.
* Each chunk is written to the output file.
*/
byte[] buf = new byte[BUFSIZE];
int nBytes = 0;
int tBytes = 0;
while ((nBytes = bis.read(buf, 0, BUFSIZE)) > 0) {
bos.write(buf, 0, nBytes);
tBytes += nBytes;
}
if (tBytes == 0) throw new Exception("no bytes received");
bos.flush();
MobyLog.d(TAG, "download succeeded: #bytes = " + Integer.toString(tBytes));
return true;
} catch (Exception e) {
MobyLog.e(TAG, "download failed: " + e);
context.deleteFile(TMPFILE); // remove possibly present partial file.
return false;
} finally {
if (bis != null) try { bis.close(); } catch (IOException e) {MobyLog.e(TAG, "bis close exception: " + e); };
if (bos != null) try { bos.close(); } catch (IOException e) {MobyLog.e(TAG, "bos close exception: " + e); };
}
Analyzing the files shows that the first part (about 700K) of the original file is repeated a number of times in the corrupted files, resulting in an invalid mp4 file.
Putting the file on another webserver (Apache/IIS), and downloading the file from that location does result in a correct download.
Has anyone experienced a similar problem performing a download from Azure? Can someone provide a solution?
Cheers,
Harald...
Have you tried using the azure-sdk-for-java in your android app?
Our scenario is slightly different in that we using the sdk to pull and push images from blob storage to a custom android app. But the fundamentals should be the same.
I started developing an android app that have to interact with MMS attachements, in particular, get attachements such as text, bitmaps, audio, video etc. and store them on the phone in a specific folder.
So i started reading some books and some post on the web but it isn't a very common argument, and i didn't find an official way to do what i want to do.
I found a fairly good article here on stack-overflow here: How to Read MMS Data in Android?... it works very well for me, but there are 2 problems:
The article shows you how to get MMS data by querying over the "hidden" SMS-MMS content provider, and as far as i know, Google doesn't guarantee that they'll keep the current structure in every android's future relase.
The article only explains how to get Text data and Bitmap data from MMS...what about video/audio? I tried to get a video/audio stream from an InputStream such as the example did with Bitmaps, unfortunately with no luck...
I'm very disappointed about the absence of official tutorial or "How-To" over this argument because SMS and MMS management is a very common need in mobile developement.
I hope someone can help me....
Thanks in advance!!
I found a fairly simple way to read Video/Audio data from MMS, so i decided to publish this part of my class that provides MMS attachements, for all users that need this.
private static final int RAW_DATA_BLOCK_SIZE = 16384; //Set the block size used to write a ByteArrayOutputStream to byte[]
public static final int ERROR_IO_EXCEPTION = 1;
public static final int ERROR_FILE_NOT_FOUND = 2;
public static byte[] LoadRaw(Context context, Uri uri, int Error){
InputStream inputStream = null;
byte[] ret = new byte[0];
//Open inputStream from the specified URI
try {
inputStream = context.getContentResolver().openInputStream(uri);
//Try read from the InputStream
if(inputStream!=null)
ret = InputStreamToByteArray(inputStream);
}
catch (FileNotFoundException e1) {
Error = ERROR_FILE_NOT_FOUND;
}
catch (IOException e) {
Error = ERROR_IO_EXCEPTION;
}
finally{
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
//Problem on closing stream.
//The return state does not change.
Error = ERROR_IO_EXCEPTION;
}
}
}
//Return
return ret;
}
//Create a byte array from an open inputStream. Read blocks of RAW_DATA_BLOCK_SIZE byte
private static byte[] InputStreamToByteArray(InputStream inputStream) throws IOException{
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[RAW_DATA_BLOCK_SIZE];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}
In this way you can extract "Raw" data such as Audio/Video/Images from MMS by passing:
the context where you need to use this function
the URI of the MMS part that contains data you want to extract (for ex. "content://mms/part/2")
the byref param that returns an eventual error code thrown by the procedure.
Once you have your byte[], you can create an empty File and then use a FileOutputStream to write the byte[] into it. If the file path\extension is correct and if your app has all the right
permissions, you'll be able to store your data.
PS. This procedure has been tested a few times and it worked, but i don't exclude can be some unmanaged exception cases that may produce error states. IMHO it can be improoved too...
I am read & write username & password to android device using my application to internal storage. I am successful writing to the device, but while reading I get error. On start of the aplication I read that file and I get "The applicaton (...) has stopped unexpectedly. Please try again." with "Force Close" button and the app closes. I tried different ways to read, but all showed same results. I write my data as username + "\n" + passwrd + "\n". This is the code for reading data :
private static String ReadFromFile(String fileName) {
String text = "";
FileInputStream fis = null;
byte[] fileData;
try {
StringBuffer sb = new StringBuffer();
int c = 0;
fis = AppContext.openFileInput(fileName);
if (fis.available() != 0) {
fileData = new byte[fis.available()];
c = fis.read(fileData);
Log.i(TAG, "Read Byes = " + c );
java.util.StringTokenizer stk = new java.util.StringTokenizer(new String(fileData), "\n");
text = stk.toString();
} else
throw new IOException("fis.available() <= 0"); /*
c = (char)fis.read();
while (c != -1){
if (c != -1)
sb.append(c);
c = (char)fis.read();
}
text = sb.toString();
*/
fis.close();
} catch (FileNotFoundException e) {
text = "null " + e.getMessage();
} catch (IOException e) {
text = "null " + e.getMessage();
} finally {
fis = null;
}
return text;
}
/*
try {
StringBuffer sb = new StringBuffer();
RandomAccessFile raf = new RandomAccessFile(ENC_LOGIN_FILE, "r");
while ((str1 = raf.readLine()) != null){
sb.append(str1);
}
str1 = sb.toString();
} catch (FileNotFoundException e) {
errorMessage = "File Not Found: " + e.getMessage();
//e.printStackTrace();
} catch (IOException ioe) {
errorMessage = "IOExcp: " + ioe.getMessage();
//e.printStackTrace();
}*/
No path is used and the filename directly is given to write & read file. I checked out Problem facing in reading file from Internal memory of android from where I tried StringTokenizer.
Can anyone help me know where am I going wrong. The following permission are set :
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.READ_SYNC_STATS"></uses-permission>
<uses-permission android:name="android.permission.READ_LOGS"></uses-permission>
Also how do I debug the application. How to check the data written in Log. If I use SOP, where does it dispaly - it doesn't display in Console window ? Please help me, I am n newbie in android development.
One more thing to clarify : My motto is to store username and password in such a way that user must not be able to read them directly. I have already used MODE_PRIMITIVE. Is their a need to use JSONObject to save this data. I had a look at JSON in couple of sites & API but couldn't make out why and where it should be used. Using MODE_PRIMITIVE I believe even the user can't read the file. Only my application can read it. Then I don't think I should use JSON. Please correct me if I am wrong.
Any help is highly appreciated.
Thanks.
A suggestion:
If you are only saving username and password then use SharedPreferences instead of saving the data in a file. It is a much secure way and plus very hassle free.
Use this blog article on How to use Shared Preferences:
http://saigeethamn.blogspot.com/2009/10/shared-preferences-android-developer.html
fis = AppContext.openFileInput(fileName);
fileData = new byte[fis.available()];
java.util.StringTokenizer stk =
new java.util.StringTokenizer(new String(fileData), "\n");
It appears to me that you're trying to create a new String using an uninitialized array as input. You've asked for the array to be a specific size, but you haven't done anything to read data into the array. (Note that available() only asks for the size of the data that can be read without blocking; it doesn't actually read the data. For that you need the read() method.)
Try this:
fis = AppContext.openFileInput(fileName);
fileData = new byte[fis.available()];
fis.read(fileData);
java.util.StringTokenizer stk =
new java.util.StringTokenizer(new String(fileData), "\n");
You should check the return value of fis.read(), but give this a try to see if it lets you progress further.