Downloading images with webview - android

I m displaying a gallery from a mobile website in webview . How can i download those images from webview ? Are there any extra settings for webview ?

This solved my problem
` `#Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
boolean shouldOverride = false;
// We only want to handle requests for image files, everything else the webview
// can handle normally
if (url.endsWith(".jpg")) {
shouldOverride = true;
Uri source = Uri.parse(url);
// Make a new request pointing to the mp3 url
DownloadManager.Request request = new DownloadManager.Request(source);
// Use the same file name for the destination
File destinationFile = new File (destinationDir, source.getLastPathSegment());
request.setDestinationUri(Uri.fromFile(destinationFile));
// Add it to the manager
manager.enqueue(request);
}
return shouldOverride;
}``
make sure to add permissions for download manager, SD read, SD write!

I think the best way to do it is to parse the html code of the page and get the images url.

Just load the URL of the image with the webview.

webview.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.contains("http://m.dudamobile.com/?source=DM_DIRECT") ){
DownloadManager dm = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Request request = new Request(
Uri.parse(url));
enqueue = dm.enqueue(request);
return true;
}
else
{
view.loadUrl(url);
return true;
}
}}
//register your broadcast reciever of Download manager in the activity
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
Query query = new Query();
query.setFilterById(enqueue);
try{
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c
.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c
.getInt(columnIndex)) {
// ImageView view = (ImageView) findViewById(R.id.imageView1);
String uriString = c
.getString(c
.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
mNotificationManager.notify(1, notification);
// view.setImageURI(Uri.parse(url1));
/* Intent i = new Intent();
i.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS);
startActivity(i);*/
}
}
}catch(NullPointerException e)
{
Toast.makeText(getApplicationContext(),"Item not downloadable :( ", Toast.LENGTH_LONG).show();
}
}
}
};
registerReceiver(receiver, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
`

Related

Get total bytes return -1 on Android Download Manager

I am creating a progress bar to show percentage download apk in Android download manager but DownloadManager.COLUMN_TOTAL_SIZE_BYTES always returns -1 and when download finished, it returns the file size.
String url = Config.GET_APK+ finalApk;
final DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.addRequestHeader("Authorization", token);
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, finalApk);
Log.d("PATH1", String.valueOf(Environment.DIRECTORY_DOWNLOADS + "/" + finalApk));
// get download service and enqueue file
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downId = manager.enqueue(request);
Log.d("DOWNLOADID", String.valueOf(downId));
download.show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
new Thread(new Runnable() {
#Override
public void run() {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downId);
Cursor c = manager.query(q);
c.moveToFirst();
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
download.dismiss();
}
final int bytes_download = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
final int bytes_total = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
Log.d("bytes_total", String.valueOf(bytes_total));
runOnUiThread(new Runnable() {
#Override
public void run() {
final double dl_prog = ((bytes_download * 100.0) / bytes_total);
download.setProgress((int) dl_prog);
}
});
c.close();
}
}
}).start();
}
},1000);
I already tried solution in this using post delayed + in download manager total size bytes doc and it says it will return -1 until download begins then it will return the download size.
in my case the server was not sending the content length of the file, I checked it with a simple
URL url = new URL("URL");
url.openConnection().getContentLength();
and even here the content length was -1.
After fixing it on the server side, the DownloadManager was returning the correct COLUMN_TOTAL_SIZE_BYTES

onReceive does'n work properly

I have a download manager that downloads an image on clicking a button. with help of broadcast receivers I will do this.
below is my code:
public void myDownloadManager(){
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(enqueue);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
// download finished successfully
Log.e("count downloads", "counting");
db.insertDownloadsRows(image_id);
}
}
}
}
};
getActivity().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
public void downloadImage(){
myDownloadManager();
dm = (DownloadManager) getActivity().getSystemService(getActivity().DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("some uri"));
request.setDestinationInExternalPublicDir("some directory", name);
enqueue = dm.enqueue(request);
}
and downloadImage() is called in button's onClickListener. when I tap the button for the first time, the image will be downloaded once and the Log message shown up once, for the second time when I tap the button, the image will be downloaded once but the Log message shown up twice, and this happens as much as I tap button. why is it this way? how should it be fixed?
That happens because you are registering the receiver multiple times without unregistering it, so you have to do one of two things:
even register the receiver only once like within your onCreate() method for example (which is absolutely the better solution):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.videoview);
myDownloadManager();
}
public void downloadImage(){
dm = (DownloadManager) getActivity().getSystemService(getActivity().DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("some uri"));
request.setDestinationInExternalPublicDir("some directory", name);
enqueue = dm.enqueue(request);
}
OR call unregister receiver each time you finish dealing with the downloading file:
public void downloadImage(){
// Un-registering the receiver
unregisterReceiver(receiver);
myDownloadManager();
dm = (DownloadManager) getActivity().getSystemService(getActivity().DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("some uri"));
request.setDestinationInExternalPublicDir("some directory", name);
enqueue = dm.enqueue(request);
}

Android update app across app restarts using DownloadManager (avoid downloading multiple times)

Iam trying to update my app by downloading the apk using download manager. I have registered broadcast receiver to listen to DownloadManager.ACTION_DOWNLOAD_COMPLETE in MainActivity and open the apk in onReceive method.
Following is the code:
public class MainActivity extends CordovaActivity {
private long downloadReference;
private DownloadManager downloadManager;
private IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(downloadReceiver, intentFilter);
}
public void updateApp(String url) {
//start downloading the file using the download manager
downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
request.setAllowedOverRoaming(false);
request.setDestinationInExternalFilesDir(MainActivity.this, Environment.DIRECTORY_DOWNLOADS, "myapk.apk");
downloadReference = downloadManager.enqueue(request);
}
#Override
public void onDestroy() {
//unregister your receivers
this.unregisterReceiver(downloadReceiver);
super.onDestroy();
}
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//check if the broadcast message is for our Enqueued download
long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (downloadReference == referenceId) {
//start the installation of the latest version
Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.setDataAndType(downloadManager.getUriForDownloadedFile(downloadReference),
"application/vnd.android.package-archive");
installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(installIntent);
}
}
};
}
updateApp(url) is called on click of a button in UI.
Now after clicking the button, the download starts. Lets say the app is closed (receiver is unregistered) after initiating the download, I have problem with two scenarios when the app is started again.
The previous download completes after my app is restarted -
downloadReference is lost and when my receiver receives the broadcast, the referenceId wont be same as downloadReference, so installIntent is never started. So
I have to click on Update button again and initiate the download. Is
there a way to avoid this problem?
The previous download completes before my app is restarted - There is no way of knowing that my previous download is complete in
the newly started activity. Again I have to click the button and reinitiate the download. Is there a way to enable sticky
broadcast for download manager?
For this, you have to store the download reference in your preference. Then you can query the DownloadManager using DownloadManager.Query() which will return a cursor holding all the download requests posted to DownloadManager by your app. Then you can match the downloadReference id and then check the status of your download. If it's complete then you can get the path from DownloadManager.COLUMN_LOCAL_FILENAME.
private void updateDownloadStatus(long downloadReference) {
DownloadManager.Query query = new DownloadManager.Query();
// if you have stored the downloadReference. Else you have to loop through the cursor.
query.setFilterById(downloadReference);
Cursor cursor = null;
try {
cursor = DOWNLOAD_MANAGER.query(query);
if (cursor == null || !cursor.moveToFirst()) {
// restart download
return;
}
float bytesDownloaded =
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
float bytesTotal =
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int downloadStatus = cursor.getInt(columnIndex);
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int failureStatus = cursor.getInt(columnReason);
int filePathInt = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
String filePath = cursor.getString(filePathInt);
switch (downloadStatus) {
case DownloadManager.STATUS_FAILED:
case DownloadManager.ERROR_FILE_ERROR:
// restart download
break;
case DownloadManager.STATUS_SUCCESSFUL:
if (filePath != null) {
//got the file
} else {
//restart
}
break;
case DownloadManager.STATUS_PENDING:
case DownloadManager.STATUS_RUNNING:
case DownloadManager.STATUS_PAUSED:
/// wait till download finishes
break;
}
} catch (Exception e) {
Log.e("Error","message" + e.getMessage(), e);
} finally {
if (cursor != null) {
cursor.close();
}
}
}

Download manager not callback when the URL is HTTPS

Here is how I download the file, it works on http but when I use https, it does not callback, thanks for helping.
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(Constant.request_imageFolder + item.user_id + "/" + item.record_url));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
//request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
}
request.setDestinationUri(Uri.fromFile(tmp_record));
enqueue = mgr.enqueue(request);
The oncomplete code, which is not call when I use https
onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
Query query = new Query();
query.setFilterById(enqueue);
if (query != null) {
Cursor c = mgr.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String mediaType = c.getString(c.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
if (mediaType.equals("image/jpeg")) {
pDialog.dismiss();
share.performClick();
} else if (mediaType.equals("video/mp4")) {
pDialog.dismiss();
play();
}
}
}
}
}
}
};
I tried to debug but the error detection message is at the callback so there is no hints about the root of problem , only knowing that it is caused by https. How can I fix it? thanks for helping?

How to receive status of download manager intent until download success or failed

Here's my problem.
I'm trying to download file from my server using download manager intent via Asynctask.
in my doInBackground of asynctask class, i was call download manager intent, and doinBackground will return boolean value when download finish (Success or Failed).
Here's my code
protected Boolean doInBackground(String... f_url) {
boolean flag = true;
boolean downloading =true;
try{
DownloadManager mManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Request mRqRequest = new Request(
Uri.parse("http://"+model.getDownloadURL()));
long idDownLoad=mManager.enqueue(mRqRequest);
DownloadManager.Query query = null;
query = new DownloadManager.Query();
Cursor c = null;
if(query!=null) {
query.setFilterByStatus(DownloadManager.STATUS_FAILED|DownloadManager.STATUS_PAUSED|DownloadManager.STATUS_SUCCESSFUL|
DownloadManager.STATUS_RUNNING|DownloadManager.STATUS_PENDING);
} else {
return flag;
}
c = mManager.query(query);
if(c.moveToFirst()) {
int status =c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
while (downloading)
{ Log.i ("FLAG","Downloading");
if (status==DownloadManager.STATUS_SUCCESSFUL)
{ Log.i ("FLAG","done");
downloading = false;
flag=true;
break;
}
if (status==DownloadManager.STATUS_FAILED)
{Log.i ("FLAG","Fail");
downloading = false;
flag=false;
break;
}
c.moveToFirst();
}
}
return flag;
}
catch (Exception e)
{
flag = false;
return flag;
}
}
But DownloadManager status never jump on DownloadManager.STATUS_SUCCESSFUL or DownloadManager.STATUS_FAILED.
There's no need for the AsyncTask or the synchronous query. DownloadManager is already asynchronous. You should register a BroadcastReceiver for ACTION_DOWNLOAD_COMPLETE so that you get notified when the download completes (or fails).
There's a very good example at http://blog.vogella.com/2011/06/14/android-downloadmanager-example
You have to requery the download manager. The cursor stays the same even if the data changes. Try like this:
protected Boolean doInBackground(String... f_url) {
boolean flag = true;
boolean downloading =true;
try{
DownloadManager mManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Request mRqRequest = new Request(
Uri.parse("http://"+model.getDownloadURL()));
long idDownLoad=mManager.enqueue(mRqRequest);
DownloadManager.Query query = null;
query = new DownloadManager.Query();
Cursor c = null;
if(query!=null) {
query.setFilterByStatus(DownloadManager.STATUS_FAILED|DownloadManager.STATUS_PAUSED|DownloadManager.STATUS_SUCCESSFUL|DownloadManager.STATUS_RUNNING|DownloadManager.STATUS_PENDING);
} else {
return flag;
}
while (downloading) {
c = mManager.query(query);
if(c.moveToFirst()) {
Log.i ("FLAG","Downloading");
int status =c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status==DownloadManager.STATUS_SUCCESSFUL) {
Log.i ("FLAG","done");
downloading = false;
flag=true;
break;
}
if (status==DownloadManager.STATUS_FAILED) {
Log.i ("FLAG","Fail");
downloading = false;
flag=false;
break;
}
}
}
return flag;
}catch (Exception e) {
flag = false;
return flag;
}
}
Download Manager download files in asynchronous manner. So no need to put download manager inside an Asyntask.
You can use Receiver for get the status of download manager if download complete.
public class CheckDownloadComplete extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
{
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0));
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor cursor = manager.query(query);
if (cursor.moveToFirst()) {
if (cursor.getCount() > 0) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
Long download_id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID,0);
// status contain Download Status
// download_id contain current download reference id
if (status == DownloadManager.STATUS_SUCCESSFUL)
{
String file = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
//file contains downloaded file name
// do your stuff here on download success
}
}
}
cursor.close();
}
}
}
Dont forget to add your receiver in Manifest
<receiver
android:name=".CheckDownloadComplete"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>

Categories

Resources