So I am stuck on a issue with my webapp that runs inside a webview from android studio.
I want download like pdf file to be downloaded and opend in the native app on the phone. This work fine by using the download manager from android studio.
How ever I also have links that start with "mailto:" and "tel:" those links give me an error when I don't override the method "shouldOverrideUrlLoading" where I can check what kind of url it is. And then open the propper inten.
So when I combine the 2 the downloadmanager and the custom NavigationHandler that extends the WebViewClient, it doesn't work as expected.
For a better understanding of what is happening.
When I hit a button with a pdf file it downloads the file gives a toast message and opens the file with the native app on the phone. This is without overriding the "shouldOverrideURLLoading" and without my class that extends the WebViewClient.
When I also use my own NavigationHandler witch extends from WebViewClient,
my urls with "mailto:" and "tel:" open with native apps on the phone.
When I now hit a button with a pdf file it is opend in a browser to be downloaded. Witch I don't want. I have tried numerous things to solf the problem but until now without succes.
I run a website app inside of a WebViewClient.
P.S. sorry for the shitty code but it's new to me and haven't find my way jet in coding in Android Studio.
My NavigationHandler class
package nl.firejob.selector;
import android.content.Intent;
import android.net.Uri;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class NavigationHandler extends WebViewClient {
private static final String TEL_PREFIX = "tel:";
private static final String MAILTO_PREFIX = "mailto:";
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if ( url.startsWith( TEL_PREFIX ) ) {
// This is a tel link, which should be opened with the native thing.
Intent tel = new Intent( Intent.ACTION_DIAL, Uri.parse( url ) );
view.getContext().startActivity( tel );
return true;
} else if ( url.startsWith( MAILTO_PREFIX ) ) {
// This is a mail link, which should be opened with the other native thing.
Intent mail = new Intent(Intent.ACTION_SENDTO);
mail.setType("message/rfc822");
mail.setData(Uri.parse( url ));
view.getContext().startActivity( mail );
return true;
} else if ( Uri.parse(url).getHost().startsWith("myurl.com") ) {
// This is what we want to show in the app, so let the WebView handle it.
return false;
}
// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse( url ) );
view.getContext().startActivity( intent );
return true;
}
}
My MainActivity Class
package nl.firejob.selector;
import android.Manifest;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.DownloadListener;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Toast;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private WebView mWebView;
private DownloadManager dm;
private Long myDownloadReference;
private BroadcastReceiver receiveDownloadComplete;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webView);
// Allow webview to use javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// Stop local links/redirects from opening in browser instead of WebView
mWebView.setWebViewClient(new NavigationHandler() {
#Override
public void onPageFinished(WebView view, String url) {
// Show the webview
findViewById(R.id.webView).setVisibility(View.VISIBLE);
// Hide splashscreen objects
findViewById(R.id.imageLogo).setVisibility(View.GONE);
findViewById(R.id.textLogo).setVisibility(View.GONE);
}
});
mWebView.setDownloadListener(new DownloadListener() {
#Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
if( haveStoragePermission()) {
Log.i("download url",url);
//for downloading directly through download manager
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.allowScanningByMediaScanner();
request.setVisibleInDownloadsUi(true);
request.setDescription("Doorvoerboek").setTitle("doorvoerboek.pdf");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "doorvoerboek.pdf");
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
myDownloadReference = dm.enqueue(request);
IntentFilter intentFilter = new IntentFilter( dm.ACTION_DOWNLOAD_COMPLETE);
receiveDownloadComplete = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (myDownloadReference == reference) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(reference);
Cursor cursor = dm.query(query);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursor.getInt(columnIndex);
int fileNameIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TITLE);
String saveFilePath = cursor.getString(fileNameIndex);
Log.i("filename",saveFilePath);
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int reason = cursor.getInt(columnReason);
switch (status){
case DownloadManager.STATUS_SUCCESSFUL:
Toast.makeText(MainActivity.this, "Download Complete", Toast.LENGTH_LONG).show();
Log.i("dir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() );
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() +"/doorvoerboek.pdf");
Intent intentView = new Intent(Intent.ACTION_VIEW);
intentView.setDataAndType(Uri.fromFile(file),"application/pdf");
intentView.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intentView);
break;
}
}
}
};
registerReceiver(receiveDownloadComplete,intentFilter);
}
}
});
mWebView.loadUrl("http://myurl.com/");
}
public boolean haveStoragePermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.e("Permission error","You have permission");
return true;
} else {
Log.e("Permission error","You have asked for permission");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //you dont need to worry about these stuff below api level 23
Log.e("Permission error","You already have the permission");
return true;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
//if Back key pressed and webview can navigate to previous page
mWebView.goBack();
// go back to previous page
return true;
}
else
{
finish();
// finish the activity
}
return super.onKeyDown(keyCode, event);
}
}
This code downloads any file.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webview = (WebView) findViewById(R.id.webView);
spinner = (ProgressBar) findViewById(R.id.progressBar1);
webview.setWebViewClient(new CustomWebViewClient());
webview.getSettings().setUseWideViewPort(true);
webview.getSettings().setLoadWithOverviewMode(true);
webview.getSettings().setBuiltInZoomControls(true);
webview.getSettings().setDisplayZoomControls(false);
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setDomStorageEnabled(true);
webview.setOverScrollMode(WebView.OVER_SCROLL_NEVER);
webview.loadUrl("http://www.website.com");
//Download file code stackoverflow.com
webview.setDownloadListener(new DownloadListener() {
#Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), "downloading",
Toast.LENGTH_LONG).show();
}
});
// Download section of code
} // Close of onCreate
// mailto code stackoverflow.com
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if( url.startsWith("http:") || url.startsWith("https:") ) {
return false;
}
// Otherwise allow the OS to handle it
else if (url.startsWith("tel:")) {
Intent tel = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(tel);
return true;
}
else if (url.startsWith("mailto:")) {
String body = "Enter your Question, Enquiry or Feedback below:\n\n";
Intent mail = new Intent(Intent.ACTION_SEND);
Intent intent = mail.setType("application/octet-stream");
MailTo recipient = MailTo.parse(url);
mail.putExtra(Intent.EXTRA_EMAIL, new String[]{recipient.getTo()});
mail.putExtra(Intent.EXTRA_SUBJECT, "Contact");
mail.putExtra(Intent.EXTRA_TEXT, body);
startActivity(mail);
return true;
}
return true;
}
}
// mailto section of code
Related
I want to use youtubeExtractor for android app and I found library like
compile 'com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT'
There is a sample code in github I copied it. After I open app, it closes at the same time. There isn't an error in phone and also Logcat. Only there is
W/System: ClassLoader referenced unknown path: /data/app/oz.videos-1/lib/arm64 on logcat. I am not sure this is a error or not. Any suggestion? Thanks in advance.
import android.app.Activity;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.SparseArray;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import at.huber.youtubeExtractor.VideoMeta;
import at.huber.youtubeExtractor.YouTubeExtractor;
import at.huber.youtubeExtractor.YtFile;
public class MainActivity extends Activity
{
private static String youtubeLink;
private LinearLayout mainLayout;
private ProgressBar mainProgressBar;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainLayout = (LinearLayout) findViewById(R.id.main_layout);
mainProgressBar = (ProgressBar) findViewById(R.id.prgrBar);
// Check how it was started and if we can get the youtube link
if (savedInstanceState == null && Intent.ACTION_SEND.equals(getIntent().getAction())
&& getIntent().getType() != null && "text/plain".equals(getIntent().getType()))
{
String ytLink = getIntent().getStringExtra(Intent.EXTRA_TEXT);
if (ytLink != null
&& (ytLink.contains("://youtu.be/") || ytLink.contains("youtube.com/watch?v=")))
{
youtubeLink = ytLink;
// We have a valid link
getYoutubeDownloadUrl(youtubeLink);
}
else
{
Toast.makeText(this, R.string.error_no_yt_link, Toast.LENGTH_LONG).show();
finish();
}
} else if (savedInstanceState != null && youtubeLink != null) {
getYoutubeDownloadUrl(youtubeLink);
} else {
finish();
}
}
private void getYoutubeDownloadUrl(String youtubeLink)
{
new YouTubeExtractor(this)
{
#Override
public void onExtractionComplete(SparseArray<YtFile> ytFiles, VideoMeta vMeta) {
mainProgressBar.setVisibility(View.GONE);
if (ytFiles == null) {
// Something went wrong we got no urls. Always check this.
finish();
return;
}
// Iterate over itags
for (int i = 0, itag; i < ytFiles.size(); i++) {
itag = ytFiles.keyAt(i);
// ytFile represents one file with its url and meta data
YtFile ytFile = ytFiles.get(itag);
// Just add videos in a decent format => height -1 = audio
if (ytFile.getFormat().getHeight() == -1 || ytFile.getFormat().getHeight() >= 360) {
addButtonToMainLayout(vMeta.getTitle(), ytFile);
}
}
}
}.extract(youtubeLink, true, false);
}
private void addButtonToMainLayout(final String videoTitle, final YtFile ytfile)
{
// Display some buttons and let the user choose the format
String btnText = (ytfile.getFormat().getHeight() == -1) ? "Audio " +
ytfile.getFormat().getAudioBitrate() + " kbit/s" :
ytfile.getFormat().getHeight() + "p";
btnText += (ytfile.getFormat().isDashContainer()) ? " dash" : "";
Button btn = new Button(this);
btn.setText(btnText);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String filename;
if (videoTitle.length() > 55) {
filename = videoTitle.substring(0, 55) + "." + ytfile.getFormat().getExt();
} else {
filename = videoTitle + "." + ytfile.getFormat().getExt();
}
filename = filename.replaceAll("\\\\|>|<|\"|\\||\\*|\\?|%|:|#|/", "");
downloadFromUrl(ytfile.getUrl(), videoTitle, filename);
finish();
}
});
mainLayout.addView(btn);
}
private void downloadFromUrl(String youtubeDlUrl, String downloadTitle, String fileName)
{
Uri uri = Uri.parse(youtubeDlUrl);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setTitle(downloadTitle);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
}
Please try to implement the version 2.0.0 of the library:
implementation 'com.github.HaarigerHarald:android-youtubeExtractor:v2.0.0'
May be your savedInstanceState == null, and then finish() method called.
Try call getYoutubeDownloadUrl() with youtube link after mainProgressBar = (ProgressBar) findViewById(R.id.prgrBar);
When I try to download an image from web view
Download starts but the image isn't saved in gallery .. " I don't know where"
and when I delete the cache of download manager it disappears what is the problem with the code?
package com.example.misrcomp.myapplication;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DownloadManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.DownloadListener;
import android.webkit.URLUtil;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static int SPLASH_TIME_OUT = 10;
public android.widget.ProgressBar ProgressBar;
#Override
public void onCreateContextMenu(ContextMenu contextMenu,View view,ContextMenu.ContextMenuInfo contextMenuInfo){
super.onCreateContextMenu(contextMenu, view, contextMenuInfo);
final WebView.HitTestResult webViewHitTestResult = mWebView.getHitTestResult();
if (webViewHitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE ||
webViewHitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
contextMenu.setHeaderTitle("Download Image From Below");
contextMenu.add(0, 1, 0, "Save - Download Image")
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
String DownloadImageURL = webViewHitTestResult.getExtra();
if(URLUtil.isValidUrl(DownloadImageURL)){
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadImageURL));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadManager.enqueue(request);
Toast.makeText(MainActivity.this,"Image Downloaded Successfully.",Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(MainActivity.this,"Sorry.. Something Went Wrong.",Toast.LENGTH_LONG).show();
}
return false;
}
});
}
}
private Context mContext;
private Activity mActivity;
private LinearLayout mRootLayout;
private WebView mWebView;
private static final int MY_PERMISSION_REQUEST_CODE = 123;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this,"By:Hisham Raafat",Toast.LENGTH_SHORT).show();
}
},SPLASH_TIME_OUT);
ProgressBar = (ProgressBar) findViewById(R.id.prg);
// Get the application context
mContext = getApplicationContext();
mActivity = MainActivity.this;
// Get the widget reference from xml layout
mRootLayout = findViewById(R.id.root_layout);
mWebView = findViewById(R.id.web_view);
// Check permission for write external storage
checkPermission();
// The target url to surf using web view
String url = "http://nekashatspacetoon.yoo7.com/h29-h";
registerForContextMenu(mWebView);
// Load the url in web view
mWebView.loadUrl(url);
mWebView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageStarted(WebView view,String url,Bitmap favicon) {
ProgressBar.setVisibility(View.VISIBLE);
}
#Override
public void onPageFinished(WebView view,String url) {
ProgressBar.setVisibility(view.GONE);
setTitle(view.getTitle());
}
}
);
// Enable java script on web view
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setDownloadListener(new DownloadListener() {
#Override
public void onDownloadStart(String url, String userAgent, String contentDescription,
String mimetype, long contentLength) {
/*
DownloadManager.Request
This class contains all the information necessary to request a new download.
The URI is the only required parameter. Note that the default download
destination is a shared volume where the system might delete your file
if it needs to reclaim space for system use. If this is a problem,
use a location on external storage (see setDestinationUri(Uri).
*/
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
/*
void allowScanningByMediaScanner ()
If the file to be downloaded is to be scanned by MediaScanner, this method
should be called before enqueue(Request) is called.
*/
request.allowScanningByMediaScanner();
/*
DownloadManager.Request setNotificationVisibility (int visibility)
Control whether a system notification is posted by the download manager
while this download is running or when it is completed. If enabled, the
download manager posts notifications about downloads through the system
NotificationManager. By default, a notification is shown only
when the download is in progress.
It can take the following values: VISIBILITY_HIDDEN, VISIBILITY_VISIBLE,
VISIBILITY_VISIBLE_NOTIFY_COMPLETED.
If set to VISIBILITY_HIDDEN, this requires the permission
android.permission.DOWNLOAD_WITHOUT_NOTIFICATION.
Parameters
visibility int : the visibility setting value
Returns
DownloadManager.Request this object
*/
request.setNotificationVisibility(
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
/*
DownloadManager
The download manager is a system service that handles long-running HTTP
downloads. Clients may request that a URI be downloaded to a particular
destination file. The download manager will conduct the download in the
background, taking care of HTTP interactions and retrying downloads
after failures or across connectivity changes and system reboots.
*/
/*
String guessFileName (String url, String contentDisposition, String mimeType)
Guesses canonical filename that a download would have, using the URL
and contentDisposition. File extension, if not defined,
is added based on the mimetype
Parameters
url String : Url to the content
contentDisposition String : Content-Disposition HTTP header or null
mimeType String : Mime-type of the content or null
Returns
String : suggested filename
*/
String fileName = URLUtil.guessFileName(url,contentDescription,mimetype);
/*
DownloadManager.Request setDestinationInExternalPublicDir
(String dirType, String subPath)
Set the local destination for the downloaded file to a path within
the public external storage directory (as returned by
getExternalStoragePublicDirectory(String)).
The downloaded file is not scanned by MediaScanner. But it can be made
scannable by calling allowScanningByMediaScanner().
Parameters
dirType String : the directory type to pass to
getExternalStoragePublicDirectory(String)
subPath String : the path within the external directory, including
the destination filename
Returns
DownloadManager.Request this object
Throws
IllegalStateException : If the external storage directory cannot be
found or created.
*/
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,fileName);
DownloadManager dManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
/*
long enqueue (DownloadManager.Request request)
Enqueue a new download. The download will start automatically once the
download manager is ready to execute it and connectivity is available.
Parameters
request DownloadManager.Request : the parameters specifying this download
Returns
long : an ID for the download, unique across the system. This ID is used
to make future calls related to this download.
*/
dManager.enqueue(request);
}
});
}
protected void checkPermission(){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
// show an alert dialog
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setMessage("Write external storage permission is required.");
builder.setTitle("Please grant permission");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCompat.requestPermissions(
mActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSION_REQUEST_CODE
);
}
});
builder.setNeutralButton("Cancel",null);
AlertDialog dialog = builder.create();
dialog.show();
}else {
// Request permission
ActivityCompat.requestPermissions(
mActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSION_REQUEST_CODE
);
}
}else {
// Permission already granted
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){
switch(requestCode){
case MY_PERMISSION_REQUEST_CODE:{
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
// Permission granted
}else {
// Permission denied
}
}
}
}
#Override
public void onBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
}
Just type this in onMenuItemClick under String DownloadImageURL:
mWebView.setDownloadListener(new DownloadListener() {
#Override
public void onDownloadStart(String url, String userAgent, String contentDescription,
String mimetype, long contentLength) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadImageURL));
request.setNotificationVisibility(
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,fileName);
DownloadManager dManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dManager.enqueue(request);
}
});
}
We have created a web app which will be loaded in android WebView. It offers image uploading feature to end user. I have implemented all the necessary methods to provide file uploading feature. We are uploading files to AWS S3 server. It works well on most of the phones. I am facing a weird issue while uploading image from Samsung GT-P1300 7 inch tab(Jelly Bean - 4.1.2).
If you upload image stored on external storage through Media Store content provider. Server receives an empty object of size 0 bytes.
For ex, content://media/external/images/media/3064
Wherein if you upload an image from some other content provider. It works without any issue. For ex, content://com.sec.android.gallery3d.provider/picasa/item/6228047309682110642
Here are more details of issue I am facing.
Below path works! File gets uploaded through WebView.
Image URI : content://com.sec.android.gallery3d.provider/picasa/item/6228047309682110642
Authority: com.sec.android.gallery3d.provider
Below path doesn't work! Server gets empty file object.
Image URI : content://media/external/images/media/3064
Authority: media
Here is code I have implemented until now.
WebViewActivity.Java
package com.mine.activities;
import android.annotation.TargetApi;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import com.mine.R;
import com.mine.utility.AppConstants;
import java.io.File;
import java.net.CookieHandler;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
public class WebViewActivity extends AppCompatActivity {
private WebView webView = null;
private ProgressBar progressBar;
private ValueCallback<Uri> mFileUploadCallbackFirst;
private ValueCallback<Uri[]> mFileUploadCallbackSecond;
private File uploadedFile = null;
private final static int FILECHOOSER_RESULTCODE=51426;
public static final int INPUT_FILE_REQUEST_CODE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
progressBar = (ProgressBar) findViewById(R.id.pb_load_page);
webView = (WebView) findViewById(R.id.webview);
webView.setListener(this, this);
setUpWebViewDefaults(webView);
webView.loadUrl("http://some.server.com/page");
}
/**
* Convenience method to set some generic defaults for a
* given WebView
*
* #param webView
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setUpWebViewDefaults(WebView webView) {
WebSettings settings = webView.getSettings();
// Enable Javascript
settings.setJavaScriptEnabled(true);
// Use WideViewport and Zoom out if there is no viewport defined
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
settings.setAllowFileAccess(true);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
}
// Enable pinch to zoom without the zoom buttons
settings.setBuiltInZoomControls(true);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
// Hide the zoom controls for HONEYCOMB+
settings.setDisplayZoomControls(false);
}
// Enable Caching
enableHTML5AppCache(webView);
webView.setWebChromeClient(new WebChromeClient() {
// file upload callback (Android 2.2 (API level 8) -- Android 2.3 (API level 10)) (hidden method)
#SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, null);
}
// file upload callback (Android 3.0 (API level 11) -- Android 4.0 (API level 15)) (hidden method)
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
openFileChooser(uploadMsg, acceptType, null);
}
// file upload callback (Android 4.1 (API level 16) -- Android 4.3 (API level 18)) (hidden method)
#SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileInput(uploadMsg, null);
}
// file upload callback (Android 5.0 (API level 21) -- current) (public method)
#SuppressWarnings("all")
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
openFileInput(null, filePathCallback);
return true;
}
#Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
progressBar.setProgress(newProgress);
}
});
}
#SuppressLint("NewApi")
protected void openFileInput(final ValueCallback<Uri> fileUploadCallbackFirst, final ValueCallback<Uri[]> fileUploadCallbackSecond) {
if (mFileUploadCallbackFirst != null) {
mFileUploadCallbackFirst.onReceiveValue(null);
}
mFileUploadCallbackFirst = fileUploadCallbackFirst;
if (mFileUploadCallbackSecond != null) {
mFileUploadCallbackSecond.onReceiveValue(null);
}
mFileUploadCallbackSecond = fileUploadCallbackSecond;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(mUploadableImageFileTypes);
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
private void enableHTML5AppCache(WebView webView) {
webView.getSettings().setDomStorageEnabled(true);
// Set cache size to 8 mb by default. should be more than enough
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
webView.getSettings().setAppCacheMaxSize(1024 * 1024 * 8);
}
webView.getSettings().setAppCachePath(getCacheDir().getAbsolutePath());
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
}
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (requestCode == FILECHOOSER_RESULTCODE) {
if (resultCode == Activity.RESULT_OK) {
if (intent != null) {
if (mFileUploadCallbackFirst != null) {
mFileUploadCallbackFirst.onReceiveValue(intent.getData());
mFileUploadCallbackFirst = null;
}
else if (mFileUploadCallbackSecond != null) {
Uri[] dataUris;
try {
dataUris = new Uri[] { Uri.parse(intent.getDataString()) };
}
catch (Exception e) {
dataUris = null;
}
mFileUploadCallbackSecond.onReceiveValue(dataUris);
mFileUploadCallbackSecond = null;
}
}
}
else {
if (mFileUploadCallbackFirst != null) {
mFileUploadCallbackFirst.onReceiveValue(null);
mFileUploadCallbackFirst = null;
}
else if (mFileUploadCallbackSecond != null) {
mFileUploadCallbackSecond.onReceiveValue(null);
mFileUploadCallbackSecond = null;
}
}
}
}
}
activity_web_view.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.djinie.vendormobileapp.VendorMobileActivity">
<ProgressBar
android:id="#+id/pb_load_page"
style="#style/CustomProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:max="100"
android:progress="10"/>
<WebView
android:id="#+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/pb_load_page" />
</RelativeLayout>
Any help would be appreciated. Please let me know if you need more information.
How can I download files using Android downloader? (The downloader that WebBrowser is using that too).
I tried something like this :
Intent i = new Intent(Intent.ACTION_VIEW , Uri.parse("MyUrl"));
startActivity(i);
Any better way?
Edit
I am using Android 2.2
Here you go.
import android.app.Activity;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.app.DownloadManager.Request;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class DownloadManagerActivity extends Activity {
private long enqueue;
private DownloadManager dm;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
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);
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));
view.setImageURI(Uri.parse(uriString));
}
}
}
}
};
registerReceiver(receiver, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
public void onClick(View view) {
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Request request = new Request(
Uri.parse("url for file to download"));
enqueue = dm.enqueue(request);
}
public void showDownload(View view) {
Intent i = new Intent();
i.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS);
startActivity(i);
}
}
Don't forget to add android.permission.internet in manifest.
If you want to download it onto the user's SD card from an URL, you can just open it in the phone's default internet browser.
String url = "https://appharbor.com/assets/images/stackoverflow-logo.png";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
(Code from this question)
The android browser will then start and the file (in this case an image) will be downloaded.
You need to use HttpUrlConnection to do this on Android 2.2 and below. There is a very detailed tutorial on the internet that shows you how to do this (with a progress dialog box too).
Remember you must use an AsyncTask or a Thread to ensure that you do not block the UI thread during the actual download!
Yes, you cant perform network operation in the main thread. You can look up to this repository to download file.
I have developed a web app that displays a list of pdf documents hosted on a web server. This app is embedded in a webview app for android however when I load the app on my phone, selection of a pdf link does nothing. What am I doing wrong? Thanks
Heres the java code:
package com.hellowebview;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class HellowebviewActivity extends Activity {
/** Called when the activity is first created. */
private WebView mWebView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("http://aipnz.webs.com");
mWebView.setWebViewClient(new HelloWebViewClient());
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
}
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView webview, String url)
{
webview.loadUrl(url);
return true;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack())
{
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
If you want to load pdf you can use Google docs to load it.
String googleDocs = "https://docs.google.com/viewer?url=";
String pdf_url = "http://kronox.org/documentacion/Hello.Android.new.pdf";
webView.loadUrl(googleDocs + pdf_url);
NOTE: You need android.permission.INTERNET in Manifest file
Just create an Intent in your shouldOverrideUrlLoading method:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if ( urlIsPDF(url)){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
try{
view.getContext().startActivity(intent);
} catch (ActivityNotFoundException e) {
//user does not have a pdf viewer installed
}
} else {
webview.loadUrl(url);
}
return true;
}
And then whenever a user clicks a PDF link in a page within your webview, the file will open in an external PDF app.
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.endsWith(".pdf")) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
try {
view.getContext().startActivity(intent);
} catch (ActivityNotFoundException e) {
//user does not have a pdf viewer installed
}
} else {
webView.loadUrl(url);
}
return true;
}
}
This is the solution I use:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.endsWith(".pdf")){
String pdfUrl = googleDocs + url;
view.loadUrl(pdfUrl);
} else {
view.loadUrl(url);
}
return true;
}
with
private final String googleDocs = "https://docs.google.com/viewer?url=";
You have to override shouldOverrideUrlLoading method in WebClient. I use this approach with combination of intent and Google Docs as a backup:
/* You might want to move this string definition somewhere else */
final String googleDocs = "https://docs.google.com/viewer?url=";
WebView webView = new WebView(getContext());
//webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if (url.endsWith(".pdf")) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
/* Check if there is any application capable to process PDF file. */
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
/* If not, show PDF in Google Docs instead. */
view.loadUrl(googleDocs + url);
}
} else {
webView.loadUrl(url);
}
return true;
}
});
You might need to change passing the context and accessing startActivity method, but other than that it should run as it is.
Also note that since API 24, there are 2 shouldOverrideUrlLoading methods you can override. As it is stated here from #CommonsWare, it is OK to override deprecated method.
use loadurl another overloaded methods...and write internet permission
Sharing this answer as I tried all the above solutions but did not work for me, this is Kotlin code (not javascript)
myWebView.setWebViewClient(object:WebViewClient() {
override fun shouldOverrideUrlLoading(view:WebView, url:String):Boolean {
if (url.endsWith(".pdf"))
{
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(android.net.Uri.parse(url), "application/pdf")
try
{
view.getContext().startActivity(intent)
}
catch (e:ActivityNotFoundException) {
//user does not have a pdf viewer installed
}
}
else
{
myWebView.loadUrl(url)
}
return true
}
})