FileNotFoundException occur when capture the screen and save the screenshot into SDCard after power off the cellular phone, It seems that the server to flash the buffer into disk has disconnected during shutdown, but anyone can help me explain more detail? The output error message is:
02-24 14:03:28.180 27412 27412 D TakeScreenshotService:
#isFloatingBallVisible() ,visible = false
02-24 14:03:29.402 27412 10176 E SaveImageInBackgroundTask: error in
SaveImageInBackgroundData,
exception:java.io.FileNotFoundException:
/storage/emulated/0/Pictures/Screenshots/Screenshot_20170224-140329.jpg:
open failed: ENOTCONN (Transport endpoint is not connected)
02-24 14:03:29.526 27412 27412 D TakeScreenshotService: onUnbind,
isMultiScrenshot:false intent:Intent {
cmp=com.android.systemui/.screenshot.TakeScreenshotService }
The corresponding codes are:
#Override
protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
Log.d(TAG, "doInBackground:");
if (params.length != 1) return null;
if (isCancelled()) {
params[0].clearImage();
params[0].clearContext();
return null;
}
// By default, AsyncTask sets the worker thread to have background thread priority, so bump
// it back up so that we save a little quicker.
Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
Context context = params[0].context;
Bitmap image = params[0].image;
Resources r = context.getResources();
try {
// Create screenshot directory if it doesn't exist
mScreenshotDir.mkdirs();
// media provider uses seconds for DATE_MODIFIED and DATE_ADDED, but milliseconds
// for DATE_TAKEN
long dateSeconds = mImageTime / 1000;
// Save
boolean compressRet = true;
OutputStream out = new FileOutputStream(mImageFilePath);
if(PhoneStatusBar.LEUI_ENABLE) {
compressRet = image.compress(Bitmap.CompressFormat.JPEG, 100, out);
} else {
compressRet = image.compress(Bitmap.CompressFormat.PNG, 100, out);
}
out.flush();
out.close();
if(!compressRet){
//When storage is full screenshot image will compress failed, so we delete the file
File f = new File(mImageFilePath);
if(f.exists()){
f.delete();
Log.d(TAG,"screenshot " + mImageFilePath + " compress failed, so we delete it");
}
params[0].clearImage();
params[0].result = 1;
}else {
// Save the screenshot to the MediaStore
ContentValues values = new ContentValues();
ContentResolver resolver = context.getContentResolver();
values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath);
values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName);
values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName);
values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime);
values.put(MediaStore.Images.ImageColumns.DATE_ADDED, dateSeconds);
values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, dateSeconds);
if(PhoneStatusBar.LEUI_ENABLE) {
values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/jpeg");
} else {
values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
}
values.put(MediaStore.Images.ImageColumns.WIDTH, mImageWidth);
values.put(MediaStore.Images.ImageColumns.HEIGHT, mImageHeight);
values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length());
Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
// Create a share intent
String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
if(PhoneStatusBar.LEUI_ENABLE) {
sharingIntent.setType("image/jpeg");
} else {
sharingIntent.setType("image/png");
}
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, mImageFileName);
// Create a share action for the notification
final PendingIntent callback = PendingIntent.getBroadcast(context, 0,
new Intent(context, GlobalScreenshot.TargetChosenReceiver.class)
.putExtra(GlobalScreenshot.CANCEL_ID, mNotificationId),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
Intent chooserIntent = Intent.createChooser(sharingIntent, null,
callback.getIntentSender());
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NEW_TASK);
mNotificationBuilder.addAction(R.drawable.ic_screenshot_share,
r.getString(com.android.internal.R.string.share),
PendingIntent.getActivity(context, 0, chooserIntent,
PendingIntent.FLAG_CANCEL_CURRENT));
// Create a delete action for the notification
final PendingIntent deleteAction = PendingIntent.getBroadcast(context, 0,
new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
.putExtra(GlobalScreenshot.CANCEL_ID, mNotificationId)
.putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
mNotificationBuilder.addAction(R.drawable.ic_screenshot_delete,
r.getString(com.android.internal.R.string.delete), deleteAction);
params[0].imageUri = uri;
params[0].image = null;
params[0].result = 0;
}
} catch (Exception e) {
// IOException/UnsupportedOperationException may be thrown if external storage is not
// mounted
Log.e(TAG, "error in SaveImageInBackgroundData, exception:" + e);
params[0].clearImage();
params[0].result = 1;
}
// Recycle the bitmap data
if (image != null) {
image.recycle();
}
return params[0];
}
Related
I have an android application which updates itself from a server, if new version of the apk is present.
The problem is, it is now not working on devices running android 10 and higher. The root cause of the problem is that ACTION_VIEW is deprecated, and no longer supported since android 10. Here is the legacy code which is not working:
private void installapk(File file) {
Log.w(TAG, "Installing new version...");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
// Otherwise will throw exception, have to install it in new task
intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
So after searching for a while now, it seems the only option I have left is to use packagemanager class to do the job. I found this example, which compiles and runs without giving any error message, but it seems like it does nothing.
public static void install(Context context, String packageName, File file) {
InputStream in = null;
OutputStream out = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
PackageInstaller.Session session = null;
try {
in = new FileInputStream(file);
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
//
params.setAppPackageName(packageName);
// set params
int sessionId = packageInstaller.createSession(params);
session = packageInstaller.openSession(sessionId);
out = session.openWrite(file.getName(), 0, -1);
final byte[] buffer = new byte[65536];
int bytes_read;
while((bytes_read = in.read(buffer)) != -1){
out.write(buffer, 0, bytes_read);
}
session.fsync(out);
in.close();
out.close();
session.commit(createIntentSender(context, sessionId, ACTION_INSTALL_COMPLETE));
} catch (IOException e) {
Log.w(TAG, e.getMessage());
} finally {
;
}
}
}
private static IntentSender createIntentSender(Context context, int sessionId, String action) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, sessionId, new Intent(action), 0);
return pendingIntent.getIntentSender();
}
This code runs fine, but as I said, nothing happens as a result. What am I doing wrong?
I have a video that plays on my application from a server. I want to make it possible to share the video to WhatsApp when the shared button is clicked.
I understand that I have to download load the video to the device storage before sharing through Intent. Below is my code, when the shared button is click the progress bar keeps loading and nothing else happens, I'm also using FileProvider. How do I go about this?
The getVideoUrl() method below takes in the video url and returns the Uri (file path) after the video has been downloaded
private Uri getVideoUrl(String fileURL) {
Uri videoUri = null;
try {
File rootFile = new File(getCacheDir(), "share_video_" + System.currentTimeMillis() + ".mp4");
URL url = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.connect();
FileOutputStream f = new FileOutputStream(rootFile);
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
videoUri = FileProvider.getUriForFile(this,
getPackageName() + ".provider", rootFile);
f.close();
} catch (IOException e) {
Log.d("Error....", e.toString());
}
return videoUri; // returns the file path to the video from storage
}
method to share the video,which is called is onClick of the share button. Then I receive the resultCode in onActivityResult() and make the progressBar invisible and display a message that the video has been shared.
public void shareVideo(String videoUrl, String desc){
progressBar.setVisibility(View.VISIBLE);
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("*/*");
i.setPackage("com.whatsapp");
i.putExtra(Intent.EXTRA_TEXT, desc ); //to share text
i.putExtra(Intent.EXTRA_STREAM, getVideoUrl(videoUrl)); //to share video
i = Intent.createChooser(i, "Share video");
startActivityForResult(i, POSTED_VIDEO);
}
shareVideo() is now called in the shareButtonOnClickListner()
#Override
public void onClick(View v) {
String videoUrl = "https://linktoVideo.mp4"; //just an example link
String desc = "Shared Video;
switch (v.getId()) {
case R.id.post_image:
shareVideo(videoUrl, desc);
}
}
What am I doing wrongly?
I am trying to programmatically change a ringtone in API 23.
I have looked at a lot of examples on Stack Overflow and they all seem to "work" (i.e. not crash) but they do not "work" as in the mp3 doesn't become the ringtone - instead the ringtone becomes simply zero noise. So obviously /something/ happened. (no crash, now no ringtone noise)
I have split this off into a small side project to try to isolate it because it's driving me up the wall - I hope maybe you guys can see something I can't!
I have:
placed the mp3 in \res\raw
I have verified I can play the mp3 fine with this code
MediaPlayer mPlayer = MediaPlayer.create(me, R.raw.meepmeep);
mPlayer.start();
added <uses-permission android:name="android.permission.WRITE_SETTINGS"/> to the manifest
managed the api 22 permission scenario in java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.System.canWrite(this)) {
new AlertDialog.Builder(this)
.setMessage("Please Assign Meep Meep Write Permissions")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (Exception e) {
Log.e("MainActivity", "error starting permission intent", e);
}
}
})
.show();
return;
}
used a method to carefully fetch the mp3 path from the assets folder
public String LoadFile(String fileName, boolean loadFromRawFolder) throws IOException
{
InputStream iS;
if (loadFromRawFolder)
{
int rID = resources.getIdentifier("meep.example.com.meep:raw/"+fileName, null, null);
iS = resources.openRawResource(rID);
}
else
{
iS = resources.getAssets().open(fileName);
}
byte[] buffer = new byte[iS.available()];
iS.read(buffer);
ByteArrayOutputStream oS = new ByteArrayOutputStream();
oS.write(buffer);
oS.close();
iS.close();
return oS.toString();
}
tried to carefully copy the file to the local storage (as a desperate attempt to get it to work as well as tried to assign it from the raw assets lib
String path = "";
try {
LoadFile("meepmeep", true);
} catch (IOException e) {
//display an error toast message
Toast toast = Toast.makeText(me, "File: not found!", Toast.LENGTH_LONG);
toast.show();
}
//copy file to device
File newSoundFile = new File(path);
//Uri mUri = Uri.parse("android.resource://meep.example.com.meep/R.raw.meepmeep");
Uri mUri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
ContentResolver mCr = getContentResolver();
AssetFileDescriptor soundFile;
try {
soundFile= mCr.openAssetFileDescriptor(mUri, "r");
try {
byte[] readData = new byte[1024];
FileInputStream fis = soundFile.createInputStream();
FileOutputStream fos = new FileOutputStream(newSoundFile);
int i = fis.read(readData);
while (i != -1) {
fos.write(readData, 0, i);
i = fis.read(readData);
}
fos.close();
} catch (IOException io) {
}
} catch (FileNotFoundException e) {
soundFile=null;
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, newSoundFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "Meep Meep");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, newSoundFile.length());
values.put(MediaStore.Audio.Media.ARTIST, "RoadRunner");
//values.put(MediaStore.Audio.Media.DURATION, 230);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
Uri uri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
Uri newUri = mCr.insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(
me,
RingtoneManager.TYPE_RINGTONE,
newUri
);
}
catch (Throwable t){
setMessage("meepmeep error");
}
setMessage("meepmeep set");
}
but nothing seems to work. It always fails becuase either soundFile= mCr.openAssetFileDescriptor(mUri, "r"); returns null or if I decline to use that code block and try to change ringtone direct from \res\raw\ folder then it simply gives a blank sound for ringtone.
I am totally stuck for ideas?
I am trying to download multiple file using AsyncTask.
I start each download in one AsyncTask with progress bar in notification bar but i face many problems.
If i download 4 or 5 files at the same time the one or more files
interrupted without any reason.
If i download 4 or 5 images the one or more images corrupted.
this is the code i used.
private class DownloadFile extends AsyncTask<String, Integer, Long>
{
int nID = 0;
int nDownloadCounter = 0;
public DownloadFile(String sFileName, int nNotificationID) {
this.nID = nNotificationID;
this.NotificationName = sFileName;
this.nDownloadCounter = 0;
}
protected void onPreExecute(){
this.sDownloadPath = sFilePathWithSubDir;
notification = new Notification(R.drawable.app_icon, "Download File", System.currentTimeMillis());
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification);
Intent notificationIntent = new Intent();
File file = new File(this.sDownloadPath + this.NotificationName);
sMediaDataType = GSUtilities.sGetFileMIMEType(this.NotificationName);
notificationIntent.setAction(android.content.Intent.ACTION_VIEW);
notificationIntent.setDataAndType(Uri.fromFile(file), sMediaDataType);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
contentView.setTextViewText(R.id.status_percent, "0%");
contentView.setTextViewText(R.id.status_fileName, this.NotificationName);
contentView.setProgressBar(R.id.status_progress, 100, 0, false);
notification.contentView = contentView;
notification.contentIntent = contentIntent;
mNotificationManager.notify(nID, notification);
}
protected Long doInBackground(String... urls) {
long retData = 0;
OutputStream fosXSPDatabse = null;
InputStream inServerResponse = null;
URLConnection oURLConnection = null;
URL oURL = null;
try
{
oURL = new URL(oFileManager.sExpiryLink);
oURLConnection = oURL.openConnection();
if (!(oURLConnection instanceof HttpURLConnection))
throw new IOException("Not an HTTP connection");
oURLConnection.connect();
inServerResponse = new BufferedInputStream(oURL.openStream());
if (inServerResponse != null)
{
File fDirectory = new File(oFileManager.sAppFlesDirectory);
if (!fDirectory.exists())
{
if (!fDirectory.mkdir())
{}
}
fosXSPDatabse = new FileOutputStream(oFileManager.sAppFlesDirectory + "/" + oFileInfo.getFileName());
byte data[] = new byte[BUFFER_SIZE];
int nCount = 0;
long lTotalDownloaded = 0;
int nTotalSize = oURLConnection.getContentLength();
while ((nCount = inServerResponse.read(data)) != -1)
{
Log.d(String.valueOf(nID) + " - DoInBackground", String.valueOf(dNotificationbarProgress));
nDownloadCounter ++;
lTotalDownloaded += nCount;
dNotificationbarProgress = lTotalDownloaded * 100.0 / nTotalSize;
if (this.nDownloadCounter == 20 || dNotificationbarProgress == 100) {
publishProgress(Integer.parseInt(new DecimalFormat("#.##").format(dNotificationbarProgress).split("\\.")[0]));
nDownloadCounter = 0;
}
fosXSPDatabse.write(data, 0, nCount);
}
inServerResponse.close();
fosXSPDatabse.flush();
fosXSPDatabse.close();
}
}
catch (MalformedURLException e)
{}
catch (IOException e)
{}
catch (Exception e)
{}
finally
{
try
{
inServerResponse.close();
fosXSPDatabse.flush();
fosXSPDatabse.close();
}
catch (IOException e)
{}
}
return retData;
}
protected void onProgressUpdate(Integer... progress) {
try
{
Log.d(String.valueOf(nID),"onProgressUpdate");
notification.contentView.setProgressBar(R.id.status_progress, 100, progress[0], false);
notification.contentView.setTextViewText(R.id.status_fileName, this.NotificationName);
notification.contentView.setTextViewText(R.id.status_percent, String.valueOf(progress[0]) + "%");
Intent notificationIntent = new Intent();
File file = new File(this.sDownloadPath + this.NotificationName);
sMediaDataType = GSUtilities.sGetFileMIMEType(this.NotificationName);
notificationIntent.setAction(android.content.Intent.ACTION_VIEW);
notificationIntent.setDataAndType(Uri.fromFile(file), sMediaDataType);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
mNotificationManager.notify(this.nID, notification);
}
catch(Exception e)
{}
}
protected void onPostExecute(Long result) {
notification.contentView.setTextViewText(R.id.status_fileName, "Successfully installed " + this.NotificationName);
notification.contentView.setTextViewText(R.id.status_percent, "100%");
mNotificationManager.notify(this.nID, notification);
}
}
First, it's never a good idea to silently ignore Exceptions. You should at minumum log them to logcat. It think this is the problem.
Second, you're closing the streams multiple times.
Where are you calling the AsyncTask from?
If it's from an activity and the user navigates away from it, that might be terminated any time the OS wants to free up memory.
If it's from a service, that could be terminated too, but at least it is restarted later. If the service was started from a different process, such as a Sync Adapter, you should also post the PreExecute and PublishProgress and PostExecute code to the UI thread with the application looper handler as a message.
In adition, try limiting the number of concurrent downloads to max 3. Otherwise, an OutOfMemory might occur. You can do this with a BlockingQueue. If concurrency is not important, consider using an IntentService instead of an AsyncTask.
The Best way to handle download multiple files is to use the Service.
I am trying to use my download code that works perfectly fine in my other app, but it is acting very strange in this new app I am trying to make.
public class DownloadFile extends AsyncTask<Void, Integer, String> {
String SDCardRoot;
String mixtapeurl = "http://xxxxxx.com/xxxxxxxxxxxx/Mixtapes/NCredible/J.%20Cole%20-%20Cole%20World.zip";
NotificationManager notificationManager;
Notification notification2;
ProgressBar progressBar;
#Override
protected void onPreExecute() {
// configure the intent
Intent intent = new Intent();
final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
// configure the notification
notification2 = new Notification(R.drawable.download, "DOWNLOADING: " + mixtapeurl, System
.currentTimeMillis());
notification2.flags = notification2.flags | Notification.FLAG_ONGOING_EVENT;
notification2.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_progress);
notification2.contentIntent = pendingIntent;
notification2.contentView.setTextViewText(R.id.percentage, 0 + "%" );
notification2.contentView.setTextViewText(R.id.status_text, "DOWNLOADING: " + mixtapeurl);
notification2.contentView.setProgressBar(R.id.status_progress, 100, 0, false);
getApplicationContext();
notificationManager = (NotificationManager) getApplicationContext().getSystemService(
Context.NOTIFICATION_SERVICE);
notificationManager.notify(2, notification2);
}
#Override
protected String doInBackground(Void... params) {
try {
//set the download URL, a url that points to a file on the internet
//this is the file to be downloaded
URL url = new URL(mixtapeurl);
//create the new connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
//and connect!
urlConnection.connect();
//set the path where we want to save the file
//in this case, going to save it on the root directory of the
//sd card.
SDCardRoot = Environment.getExternalStorageDirectory() + "/download/";
//create a new file, specifying the path, and the filename
//which we want to save the file as.
File file = new File(SDCardRoot,mixtapeurl);
//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();
//variable to store total downloaded bytes
int downloadedSize = 0;
int myProgress;
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
int previousProgress = 0;
//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);
//publishProgress((int)(total*100/lenghtOfFile));
myProgress = (int) ((downloadedSize/(double)totalSize) * (double)100);
if ((myProgress) > 1 && (myProgress) > ((previousProgress ))) {
previousProgress= myProgress;
publishProgress(myProgress);
}
}
//close the output stream when done
fileOutput.close();
//catch some possible errors...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "success";}
#Override
protected void onProgressUpdate(Integer... progression) {
String percent;
percent = progression[0].toString();
notification2.contentView.setProgressBar(R.id.status_progress, 100, progression[0], false);
notification2.contentView.setTextViewText(R.id.percentage, percent + "%" );
notificationManager.notify(2, notification2);
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
Toast toast = Toast.makeText(getApplicationContext(), mixtapeurl + " downloaded to: " + SDCardRoot, Toast.LENGTH_LONG);
toast.show();
}
}
Here is how I implement it:
new DownloadFile().execute();
And what i get is "http://xxxxxx.com/xxxxxxxxxxxx/Mixtapes/NCredible/J.%20Cole%20-%20Cole%20World.zip download to null" for my toast right after I click the button and the file does not download at all.
This sounds like a very common issue: Forgot to set permission in manifest.
<uses-permission android:name="android.permission.INTERNET" />