Can't implement javascript in android webview - javascript
I have an android webapp and its using a different format from the other webview clients I've been using. However, it doesn't execute javascript which is needed for the file upload button. The default chrome browser can handle the uploads but the previous webview clients cannot, Thats why I chose to use this project.
I will give you the whole MainAvivity.java file.
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.NotificationCompat;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.webkit.CookieManager;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
//Permission variables
static boolean ASWP_JSCRIPT = true; //enable JavaScript for webview
static boolean ASWP_FUPLOAD = true; //upload file from webview
static boolean ASWP_CAMUPLOAD = true; //enable upload from camera for photos
static boolean ASWP_MULFILE = false; //upload multiple files in webview
static boolean ASWP_LOCATION = true; //track GPS locations
static boolean ASWP_RATINGS = true; //show ratings dialog; auto configured, edit method get_rating() for customizations
static boolean ASWP_PBAR = true; //show progress bar in app
static boolean ASWP_ZOOM = false; //zoom in webview
static boolean ASWP_SFORM = false; //save form cache and auto-fill information
static boolean ASWP_OFFLINE = true; //whether the loading webpages are offline or online
static boolean ASWP_EXTURL = true; //open external url with default browser instead of app webview
//Configuration variables
private static String ASWV_URL = "http://example.com"; //complete URL of your website or webpage
private static String ASWV_F_TYPE = "*/*"; //to upload any file type using "*/*"; check file type references for more
public static String ASWV_HOST = aswm_host(ASWV_URL);
//Careful with these variable names if altering
WebView asw_view;
ProgressBar asw_progress;
TextView asw_loading_text;
NotificationManager asw_notification;
Notification asw_notification_new;
private String asw_cam_message;
private ValueCallback<Uri> asw_file_message;
private ValueCallback<Uri[]> asw_file_path;
private final static int asw_file_req = 1;
private final static int loc_perm = 1;
private final static int file_perm = 2;
private SecureRandom random = new SecureRandom();
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (Build.VERSION.SDK_INT >= 21) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary));
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (requestCode == asw_file_req) {
if (null == asw_file_path) {
return;
}
if (intent == null) {
if (asw_cam_message != null) {
results = new Uri[]{Uri.parse(asw_cam_message)};
}
} else {
String dataString = intent.getDataString();
if (dataString != null) {
results = new Uri[]{ Uri.parse(dataString) };
}
}
}
}
asw_file_path.onReceiveValue(results);
asw_file_path = null;
} else {
if (requestCode == asw_file_req) {
if (null == asw_file_message) return;
Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
asw_file_message.onReceiveValue(result);
asw_file_message = null;
}
}
}
#SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ASWP_PBAR) {
asw_progress = (ProgressBar) findViewById(R.id.msw_progress);
} else {
findViewById(R.id.msw_progress).setVisibility(View.GONE);
}
asw_loading_text = (TextView) findViewById(R.id.msw_loading_text);
Handler handler = new Handler();
//Launching app rating request
if (ASWP_RATINGS) {
handler.postDelayed(new Runnable() { public void run() { get_rating(); }}, 1000 * 60); //running request after few moments
}
//Getting basic device information
get_info();
//Getting GPS location of device if given permission
get_location();
asw_view = (WebView) findViewById(R.id.msw_view);
//Webview settings; defaults are customized for best performance
WebSettings webSettings = asw_view.getSettings();
if(!ASWP_OFFLINE){
webSettings.setJavaScriptEnabled(ASWP_JSCRIPT);
}
webSettings.setSaveFormData(ASWP_SFORM);
webSettings.setSupportZoom(ASWP_ZOOM);
webSettings.setGeolocationEnabled(ASWP_LOCATION);
webSettings.setAllowFileAccess(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setUseWideViewPort(true);
webSettings.setDomStorageEnabled(true);
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
if (Build.VERSION.SDK_INT >= 21) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
asw_view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
} else if (Build.VERSION.SDK_INT >= 19) {
asw_view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 19) {
asw_view.requestFocus();
asw_view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
asw_view.setVerticalScrollBarEnabled(false);
asw_view.setWebViewClient(new Callback());
//Rendering the default URL
aswm_view(ASWV_URL, false);
asw_view.setWebChromeClient(new WebChromeClient() {
//Handling input[type="file"] requests for android API 16+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
if(ASWP_FUPLOAD) {
asw_file_message = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(ASWV_F_TYPE);
startActivityForResult(Intent.createChooser(i, "File Chooser"), asw_file_req);
}
}
//Handling input[type="file"] requests for android API 21+
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,WebChromeClient.FileChooserParams fileChooserParams){
get_file();
if(ASWP_FUPLOAD) {
if (asw_file_path != null) {
asw_file_path.onReceiveValue(null);
}
asw_file_path = filePathCallback;
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType(ASWV_F_TYPE);
Intent[] intentArray;
if (ASWP_CAMUPLOAD) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = create_image();
takePictureIntent.putExtra("PhotoPath", asw_cam_message);
} catch (IOException ex) {
Log.e(TAG, "Image file creation failed", ex);
}
if (photoFile != null) {
asw_cam_message = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "File Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, asw_file_req);
}
return true;
}
//Getting webview rendering progress
#Override
public void onProgressChanged(WebView view, int p) {
if (ASWP_PBAR) {
asw_progress.setProgress(p);
if (p == 100) {
asw_progress.setProgress(0);
}
}
}
});
if (getIntent().getData() != null) {
String path = getIntent().getDataString();
/*
If you want to check or use specific directories or schemes or hosts
Uri data = getIntent().getData();
String scheme = data.getScheme();
String host = data.getHost();
List<String> pr = data.getPathSegments();
String param1 = pr.get(0);
*/
aswm_view(path, false);
}
}
#Override
public void onResume() {
super.onResume();
//Coloring the "recent apps" tab header; doing it onResume, as an insurance
if (Build.VERSION.SDK_INT >= 23) {
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
ActivityManager.TaskDescription taskDesc = null;
taskDesc = new ActivityManager.TaskDescription(getString(R.string.app_name), bm, getColor(R.color.colorPrimary));
MainActivity.this.setTaskDescription(taskDesc);
}
get_location();
}
//Setting activity layout visibility
private class Callback extends WebViewClient {
public void onPageStarted(WebView view, String url, Bitmap favicon) {
get_location();
}
public void onPageFinished(WebView view, String url) {
findViewById(R.id.msw_welcome).setVisibility(View.GONE);
findViewById(R.id.msw_view).setVisibility(View.VISIBLE);
}
//For android below API 23
#SuppressWarnings("deprecation")
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), "Something Went Wrong!", Toast.LENGTH_SHORT).show();
aswm_view("file:///android_res/raw/error.html", false);
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
Toast.makeText(getApplicationContext(), "Something Went Wrong!", Toast.LENGTH_SHORT).show();
aswm_view("file:///android_res/raw/error.html", false);
}
//Overriding webview URLs
#SuppressWarnings("deprecation")
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return url_actions(view, url);
}
//Overriding webview URLs for API 23+ [suggested by github.com/JakePou]
#TargetApi(Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return url_actions(view, request.getUrl().toString());
}
}
//Random ID creation function to help get fresh cache every-time webview reloaded
public String random_id() {
return new BigInteger(130, random).toString(32);
}
//Opening URLs inside webview with request
void aswm_view(String url, Boolean tab) {
if (tab) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
} else {
asw_view.loadUrl(url+"?rid="+random_id());
}
}
//Actions based on shouldOverrideUrlLoading
public boolean url_actions(WebView view, String url){
boolean a = true;
//Show toast error if not connected to the network
if (!ASWP_OFFLINE && !DetectConnection.isInternetAvailable(MainActivity.this)) {
Toast.makeText(getApplicationContext(), "Please check your Network Connection!", Toast.LENGTH_SHORT).show();
//Use this in a hyperlink to redirect back to default URL :: href="refresh:android"
} else if (url.startsWith("refresh:")) {
aswm_view(ASWV_URL, false);
//Use this in a hyperlink to launch default phone dialer for specific number :: href="tel:+919876543210"
} else if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
//Use this to open your apps page on google play store app :: href="rate:android"
} else if (url.startsWith("rate:")) {
final String app_package = getPackageName(); //requesting app package name from Context or Activity object
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + app_package)));
} catch (ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + app_package)));
}
//Sharing content from your webview to external apps :: href="share:URL" and remember to place the URL you want to share after share:___
} else if (url.startsWith("share:")) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, view.getTitle());
intent.putExtra(Intent.EXTRA_TEXT, view.getTitle()+"\nVisit: "+(Uri.parse(url).toString()).replace("share:",""));
startActivity(Intent.createChooser(intent, "Share with your Friends"));
//Use this in a hyperlink to exit your app :: href="exit:android"
} else if (url.startsWith("exit:")) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
//Opening external URLs in android default web browser
} else if (ASWP_EXTURL && aswm_host(ASWV_URL)!=ASWV_HOST) {
aswm_view(url,true);
} else {
a = false;
}
return a;
}
//Getting host name
public static String aswm_host(String url){
if (url == null || url.length() == 0) {
return "";
}
int dslash = url.indexOf("//");
if (dslash == -1) {
dslash = 0;
} else {
dslash += 2;
}
int end = url.indexOf('/', dslash);
end = end >= 0 ? end : url.length();
int port = url.indexOf(':', dslash);
end = (port > 0 && port < end) ? port : end;
Log.w("URL Host: ",url.substring(dslash, end));
return url.substring(dslash, end);
}
//Getting device basic information
public void get_info(){
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.setCookie(ASWV_URL, "DEVICE=android");
cookieManager.setCookie(ASWV_URL, "DEV_API=" + Build.VERSION.SDK_INT);
}
//Checking permission for storage and camera for writing and uploading images
public void get_file(){
String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
//Checking for storage permission to write images for upload
if (ASWP_FUPLOAD && ASWP_CAMUPLOAD && !check_permission(2) && !check_permission(3)) {
ActivityCompat.requestPermissions(MainActivity.this, perms, file_perm);
//Checking for WRITE_EXTERNAL_STORAGE permission
} else if (ASWP_FUPLOAD && !check_permission(2)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, file_perm);
//Checking for CAMERA permissions
} else if (ASWP_CAMUPLOAD && !check_permission(3)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, file_perm);
}
}
//Using cookies to update user locations
public void get_location(){
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
if(ASWP_LOCATION) {
//Checking for location permissions
if (Build.VERSION.SDK_INT >= 23 && !check_permission(1)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, loc_perm);
show_notification(2, 2);
} else {
GPSTrack gps;
gps = new GPSTrack(MainActivity.this);
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
if (gps.canGetLocation()) {
if (latitude != 0 || longitude != 0) {
cookieManager.setCookie(ASWV_URL, "lat=" + latitude);
cookieManager.setCookie(ASWV_URL, "long=" + longitude);
//Log.w("New Updated Location:", latitude + "," + longitude); //enable to test dummy latitude and longitude
} else {
Log.w("New Updated Location:", "NULL");
}
} else {
show_notification(1, 1);
Log.w("New Updated Location:", "FAIL");
}
}
}
}
//Checking if particular permission is given or not
public boolean check_permission(int permission){
switch(permission){
case 1:
return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
case 2:
return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
case 3:
return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
}
return false;
}
//Creating image file for upload
private File create_image() throws IOException {
#SuppressLint("SimpleDateFormat")
String file_name = new SimpleDateFormat("yyyy_mm_ss").format(new Date());
String new_name = "file_"+file_name+"_";
File sd_directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(new_name, ".jpg", sd_directory);
}
//Launching app rating dialoge [developed by github.com/hotchemi]
public void get_rating() {
if (DetectConnection.isInternetAvailable(MainActivity.this)) {
AppRate.with(this)
.setStoreType(StoreType.GOOGLEPLAY) //default is Google Play, other option is Amazon App Store
.setInstallDays(3) //after how many days would you like to show the dialoge
.setLaunchTimes(10) //overall request launch times being ignored
.setRemindInterval(2) //reminding users to rate after days interval
.setTitle(R.string.rate_dialog_title)
.setMessage(R.string.rate_dialog_message)
.setTextLater(R.string.rate_dialog_cancel)
.setTextNever(R.string.rate_dialog_no)
.setTextRateNow(R.string.rate_dialog_ok)
.monitor();
AppRate.showRateDialogIfMeetsConditions(this);
}
//for more customizations, edit AppRate and DialogOptions
}
//Creating custom notifications with IDs
public void show_notification(int type, int id) {
long when = System.currentTimeMillis();
asw_notification = (NotificationManager) MainActivity.this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent i = new Intent();
if (type == 1) {
i.setClass(MainActivity.this, MainActivity.class);
} else if (type == 2) {
i.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
} else {
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + MainActivity.this.getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
}
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = (NotificationCompat.Builder) new NotificationCompat.Builder(MainActivity.this);
switch(type){
case 1:
builder.setTicker(getString(R.string.app_name));
builder.setContentTitle(getString(R.string.loc_fail));
builder.setContentText(getString(R.string.loc_fail_text));
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.loc_fail_more)));
builder.setVibrate(new long[]{350,350,350,350,350});
builder.setSmallIcon(R.mipmap.ic_launcher);
break;
case 2:
builder.setTicker(getString(R.string.app_name));
builder.setContentTitle(getString(R.string.app_name));
builder.setContentText(getString(R.string.loc_perm_text));
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.loc_perm_more)));
builder.setVibrate(new long[]{350, 700, 350, 700, 350});
builder.setSound(alarmSound);
builder.setSmallIcon(R.mipmap.ic_launcher);
break;
}
builder.setOngoing(false);
builder.setAutoCancel(true);
builder.setContentIntent(pendingIntent);
builder.setWhen(when);
builder.setContentIntent(pendingIntent);
asw_notification_new = builder.getNotification();
asw_notification.notify(id, asw_notification_new);
}
//Checking if users allowed the requested permissions or not
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults){
switch (requestCode){
case 1: {
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
get_location();
}else{
show_notification(2, 2);
Toast.makeText(MainActivity.this, R.string.loc_req, Toast.LENGTH_LONG).show();
}
}
}
}
//Action on back key tap/click
#Override
public boolean onKeyDown(int keyCode, #NonNull KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (asw_view.canGoBack()) {
asw_view.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
protected void onSaveInstanceState(Bundle outState ){
super.onSaveInstanceState(outState);
asw_view.saveState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
asw_view.restoreState(savedInstanceState);
}
}
This is a full solution for all android versions, I had a hard time with this too.
public class MyWb extends Activity {
/** Called when the activity is first created. */
WebView web;
ProgressBar progressBar;
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE=1;
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if(requestCode==FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage) return;
Uri result = intent == null || resultCode != RESULT_OK ? null
: intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
web = (WebView) findViewById(R.id.webview01);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
web = new WebView(this);
web.getSettings().setJavaScriptEnabled(true);
web.loadUrl("http://www.script-tutorials.com/demos/199/index.html");
web.setWebViewClient(new myWebClient());
web.setWebChromeClient(new WebChromeClient()
{
//The undocumented magic method override
//Eclipse will swear at you if you try to put #Override here
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
MyWb.this.startActivityForResult(Intent.createChooser(i,"File Chooser"), FILECHOOSER_RESULTCODE);
}
// For Android 3.0+
public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MyWb.this.startActivityForResult(
Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE);
}
//For Android 4.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
MyWb.this.startActivityForResult( Intent.createChooser( i, "File Chooser" ), MyWb.FILECHOOSER_RESULTCODE );
}
});
setContentView(web);
}
public class myWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
}
}
//flipscreen not loading again
#Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
// To handle "Back" key press event for WebView to go back to previous screen.
/*#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
web.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}*/
}
Also I want to add that the "upload page" like the one in this example, wont work on < 4 versions, since it has an image preview feature, if you want to make it work use a simple php upload without preview.
Update:
Please find the solution for lollipop devices here and thanks for gauntface
Update 2:
Found complete solution for all android devices including marshmallow here see its github project for more.
Related
android studio webview to use javascript for the link
this question is how to apply java script by link to webview https://dl.dropboxusercontent.com/s/lmibwymtkebspij/background.js after the page is fully loaded the background should turn green here is a sample code for loading the page webView = findViewById(R.id.Web); webView.getSettings().setJavaScriptEnabled(true); webView.setWebChromeClient(new MyWebChromeClient()); thank you in advance
maybe someone will come in handy load the text of the script into the script variable using get request to link the address of the script like this: #SuppressLint("StaticFieldLeak") class ProgressTask extends AsyncTask<String, Void, String> { #Override public String doInBackground(String... path) { try { content = getContent(path[0]); } catch (IOException ex) { content = ex.getMessage(); } return content; } #Override public void onPostExecute(String content) { scriptbg = content; Log.d("debug", scriptbg); } public String getContent(String path) throws IOException { BufferedReader reader = null; try { URL url = new URL(path); HttpsURLConnection c = (HttpsURLConnection) url.openConnection(); c.setRequestMethod("GET"); c.setReadTimeout(10000); c.connect(); reader = new BufferedReader(new InputStreamReader(c.getInputStream())); StringBuilder buf = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { buf.append(line + "\n"); } return (buf.toString()); } finally { if (reader != null) { reader.close(); } } } then we apply the script to our webView when the page is fully loaded like this: public void onPageFinished(WebView view, String url) { webView.loadUrl("javascript:" + Script); Log.d("debug", "finish"); }
how to send base64 string in android?
I am trying to make hydrid application in which there is a "button" on HTML page .whenever I click on that button i want to call android code function (which is working fine when I called test function from javascript) .Now I want to capture image on button click I take help from below url. Capture Image from Camera and Display in Activity I do like this package com.example.myapp.myapplication; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.util.Base64; import android.util.Log; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.widget.Toast; import java.io.ByteArrayOutputStream; public class MainActivity extends AppCompatActivity { private static final int CAMERA_REQUEST = 1888; private static final int MY_CAMERA_PERMISSION_CODE = 100; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); WebView webView = (WebView) findViewById(R.id.webview); // webView.loadUrl("http://1.5.20.97:3671"); webView.loadUrl("http://15.16.74.160:6019"); JavaScriptInterface jsInterface = new JavaScriptInterface(this); webView.getSettings().setJavaScriptEnabled(true); webView.setWebChromeClient(new WebChromeClient()); webView.addJavascriptInterface(jsInterface, "JSInterface"); } #Override public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == MY_CAMERA_PERMISSION_CODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show(); Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent, CAMERA_REQUEST); } else { Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show(); } } } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) { Bitmap photo = (Bitmap) data.getExtras().get("data"); // Log.d("My map",photo,""); } } public void checkTest(){ if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE); } else { Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent, CAMERA_REQUEST); } } } class JavaScriptInterface { private MainActivity activity; public JavaScriptInterface(MainActivity activity) { this.activity = activity; } #JavascriptInterface public void test() { this.activity.checkTest(); } #JavascriptInterface public String bitMapToBase64() { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); //add support for jpg and more. bitMap.compress(Bitmap.CompressFormat.PNG, 50, byteArrayOutputStream); byte[] byteArray = byteArrayOutputStream .toByteArray(); String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT); return encoded; } } I am getting import error I am trying to call a android function which open camera and capture image and return to javascript. on javascript I am calling function like this console.log(window.JSInterface.test())
So to go back to your webView when you capture the image from camera, change your onActivityResult method to this protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) { photo = (Bitmap) data.getExtras().get("data"); if (webView != null) webView.loadUrl("http://125.16.74.160:30019"); } } Also you should declare you bitmap as a global static variable like this public static Bitmap photo; Then bitMapToBase64 become like this #JavascriptInterface public String bitMapToBase64() { if (MainActivity.photo != null) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); //add support for jpg and more. MainActivity.photo.compress(Bitmap.CompressFormat.PNG, 50, byteArrayOutputStream); byte[] byteArray = byteArrayOutputStream .toByteArray(); String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT); return encoded; } return "null image"; } In the javascript side you check if bitMapToBase64 function has a return value different than "null image" you convert the base64 image to a blob or image object and show it in a div for example. Here is an example how to convert your base64 string to an image object and append it to your body var image = new Image(); image.src = 'data:image/png;base64,iVBORw0K...'; document.body.appendChild(image);
Can't fetch dynamically changed HTML content(by JavaScript) in android using AsyncTask.
I'm using python script to dynamically change the content of my web-page. The link of the web page is: [HERE] The web page contains table which has two columns: 1) Values between 1 to 5. 2) And the time when it is uploaded on the page. It is displayed dynamically by the JavaScript on the page. See the source of the page opening the link above. Now I'm creating a android application which displays the values in the text view by fetching that page and parsing the HTML. But the page source only contains JavaScript code. So whenever I fetch the HTML, it only displays the JavaScript even if it contains more than one rows with values. My question is how to fetch those values dynamically? I'm using AsyncTask and scheduling it every 10 seconds. My code is: public class MainActivity extends AppCompatActivity { TextView et ; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et = (TextView) findViewById(R.id.editText); DownloadWebPageTask task = new DownloadWebPageTask(); task.execute(new String[]{"https://rasppiclient.herokuapp.com/"}); callAsynchronousTask(); } public void callAsynchronousTask() { final Handler handler = new Handler(); Timer timer = new Timer(); TimerTask doAsynchronousTask = new TimerTask() { #Override public void run() { handler.post(new Runnable() { public void run() { try { DownloadWebPageTask performBackgroundTask = new DownloadWebPageTask(); // PerformBackgroundTask this class is the class that extends AsynchTask performBackgroundTask.execute(new String[]{"https://rasppiclient.herokuapp.com/"}); } catch (Exception e) { // TODO Auto-generated catch block } } }); } }; timer.schedule(doAsynchronousTask, 0, 10000); //execute in every 50000 ms } public class DownloadWebPageTask extends AsyncTask<String, Void, String> { #Override protected String doInBackground(String... urls) { String response = ""; for (String url : urls) { DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); try { HttpResponse execute = client.execute(httpGet); InputStream content = execute.getEntity().getContent(); BufferedReader buffer = new BufferedReader(new InputStreamReader(content)); String s = ""; while ((s = buffer.readLine()) != null) { response += s; } } catch (Exception e) { } } return response; } #Override protected void onPostExecute(String s) { super.onPostExecute(s); Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show(); } }}
This does not work with DefaultHttpClient. What you could to is the evaluate the javascript and then get the content with AndroidJSCore. JSContext context = new JSContext(); context.evaluateScript(yourJsString); context.property("getWhatYouWantHere"); An example from the github looks like this JSContext context = new JSContext(); context.evaluateScript("a = 10"); JSValue newAValue = context.property("a"); System.out.println(df.format(newAValue.toNumber())); // 10.0 String script = "function factorial(x) { var f = 1; for(; x > 1; x--) f *= x; return f; }\n" + "var fact_a = factorial(a);\n"; context.evaluateScript(script); JSValue fact_a = context.property("fact_a"); System.out.println(df.format(fact_a.toNumber())); // 3628800.0
How to make Phonegap's (Cordova) File API work like File API in normal browser
Is there a way to make Phonegap's File API work just like same API works in browser? I need same behavior as in browser: Tap on "Open file" button -> "Select File" dialog ->... -> Opening the file with FileReader Object. Thank you!!! UPDATE: I've found some solution. It opens File Dialog and it returns the name of the JS File Object. But when i pass that JS File Object to FileReader from PhoneGap - it doesn't open (onload listener never fires). What i do wrong? Here's my Java: package org.apache.cordova.example; import android.os.Bundle; import org.apache.cordova.api.CordovaInterface; import android.content.Intent; import android.net.Uri; import android.webkit.ValueCallback; import org.apache.cordova.CordovaChromeClient; import org.apache.cordova.CordovaWebView; import org.apache.cordova.DroidGap; public class cordovaExample extends DroidGap { private ValueCallback<Uri> mUploadMessage; private final static int FILECHOOSER_RESULTCODE = 1; #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.loadUrl("file:///android_asset/www/index.html"); this.appView.setWebChromeClient(new FileAttachmentChromeClient(this, this.appView)); } #Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == FILECHOOSER_RESULTCODE) { if (null == mUploadMessage) return; Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData(); mUploadMessage.onReceiveValue(result); mUploadMessage = null; } } // openFileChooser is an overridable method in WebChromeClient which isn't // included in the SDK's Android stub code public class FileAttachmentChromeClient extends CordovaChromeClient { public FileAttachmentChromeClient(CordovaInterface ctx, CordovaWebView app) { super(ctx, app); } public void openFileChooser(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("*/*"); cordovaExample.this.startActivityForResult(Intent.createChooser(i, "Choose type of attachment"), FILECHOOSER_RESULTCODE); } } } And what i do with JavaScript: var SelectedFile; var FReader; document.getElementById('fileBox').addEventListener('change', fileChosen); function fileChosen(evnt) { SelectedFile = evnt.target.files[0]; FReader = new FileReader(); FReader.readAsDataURL(SelectedFile); FReader.onload = function(loadevnt){ .... } //never happens }
Well the problem is most mobile browsers do not support the file dialog. IIRC iOS 6 is the first mobile browser to support this functionality. I did write some code in my Corinthian project, not under active development, that does monkey patch this functionality. First you'd need to write an Android plugin to start an intent to provide the file dialog. I'm using OI File Manager. package org.apache.cordova; import org.apache.cordova.api.CallbackContext; import org.apache.cordova.api.CordovaPlugin; import org.apache.cordova.api.LOG; import org.apache.cordova.api.PluginResult; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; /** * This class exposes methods in DroidGap that can be called from JavaScript. */ public class App extends CordovaPlugin { /** * Executes the request and returns PluginResult. * * #param action The action to execute. * #param args JSONArry of arguments for the plugin. * #param callbackContext The callback context from which we were invoked. * #return A PluginResult object with a status and message. */ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { PluginResult.Status status = PluginResult.Status.OK; String result = ""; try { if (action.equals("clearCache")) { this.clearCache(); } else if (action.equals("show")) { // This gets called from JavaScript onCordovaReady to show the webview. // I recommend we change the name of the Message as spinner/stop is not // indicative of what this actually does (shows the webview). cordova.getActivity().runOnUiThread(new Runnable() { public void run() { webView.postMessage("spinner", "stop"); } }); } else if (action.equals("loadUrl")) { this.loadUrl(args.getString(0), args.optJSONObject(1)); } else if (action.equals("cancelLoadUrl")) { this.cancelLoadUrl(); } else if (action.equals("clearHistory")) { this.clearHistory(); } else if (action.equals("backHistory")) { this.backHistory(); } else if (action.equals("overrideButton")) { this.overrideButton(args.getString(0), args.getBoolean(1)); } else if (action.equals("overrideBackbutton")) { this.overrideBackbutton(args.getBoolean(0)); } else if (action.equals("exitApp")) { this.exitApp(); } callbackContext.sendPluginResult(new PluginResult(status, result)); return true; } catch (JSONException e) { callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION)); return false; } } //-------------------------------------------------------------------------- // LOCAL METHODS //-------------------------------------------------------------------------- /** * Clear the resource cache. */ public void clearCache() { this.webView.clearCache(true); } /** * Load the url into the webview. * * #param url * #param props Properties that can be passed in to the DroidGap activity (i.e. loadingDialog, wait, ...) * #throws JSONException */ public void loadUrl(String url, JSONObject props) throws JSONException { LOG.d("App", "App.loadUrl("+url+","+props+")"); int wait = 0; boolean openExternal = false; boolean clearHistory = false; // If there are properties, then set them on the Activity HashMap<String, Object> params = new HashMap<String, Object>(); if (props != null) { JSONArray keys = props.names(); for (int i = 0; i < keys.length(); i++) { String key = keys.getString(i); if (key.equals("wait")) { wait = props.getInt(key); } else if (key.equalsIgnoreCase("openexternal")) { openExternal = props.getBoolean(key); } else if (key.equalsIgnoreCase("clearhistory")) { clearHistory = props.getBoolean(key); } else { Object value = props.get(key); if (value == null) { } else if (value.getClass().equals(String.class)) { params.put(key, (String)value); } else if (value.getClass().equals(Boolean.class)) { params.put(key, (Boolean)value); } else if (value.getClass().equals(Integer.class)) { params.put(key, (Integer)value); } } } } // If wait property, then delay loading if (wait > 0) { try { synchronized(this) { this.wait(wait); } } catch (InterruptedException e) { e.printStackTrace(); } } this.webView.showWebPage(url, openExternal, clearHistory, params); } /** * Cancel loadUrl before it has been loaded (Only works on a CordovaInterface class) */ #Deprecated public void cancelLoadUrl() { this.cordova.cancelLoadUrl(); } /** * Clear page history for the app. */ public void clearHistory() { this.webView.clearHistory(); } /** * Go to previous page displayed. * This is the same as pressing the backbutton on Android device. */ public void backHistory() { cordova.getActivity().runOnUiThread(new Runnable() { public void run() { webView.backHistory(); } }); } /** * Override the default behavior of the Android back button. * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired. * * #param override T=override, F=cancel override */ public void overrideBackbutton(boolean override) { LOG.i("App", "WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!"); webView.bindButton(override); } /** * Override the default behavior of the Android volume buttons. * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired. * * #param button volumeup, volumedown * #param override T=override, F=cancel override */ public void overrideButton(String button, boolean override) { LOG.i("DroidGap", "WARNING: Volume Button Default Behaviour will be overridden. The volume event will be fired!"); webView.bindButton(button, override); } /** * Return whether the Android back button is overridden by the user. * * #return boolean */ public boolean isBackbuttonOverridden() { return webView.isBackButtonBound(); } /** * Exit the Android application. */ public void exitApp() { this.webView.postMessage("exit", null); } } package com.simonmacdonald.corinthian; import org.apache.cordova.api.Plugin; import org.apache.cordova.api.PluginResult; import org.json.JSONArray; import org.json.JSONObject; import android.app.Activity; import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.util.Log; public class FileDialog extends Plugin { private static final int PICK_FILE_RESULT_CODE = 8974; private static final int PICK_DIRECTORY_RESULT_CODE = 8975; private static final String LOG_TAG = "FileDialog"; public String callbackId; /** * Executes the request and returns PluginResult. * * #param action The action to execute. * #param args JSONArry of arguments for the plugin. * #param callbackId The callback id used when calling back into JavaScript. * #return A PluginResult object with a status and message. */ #Override public PluginResult execute(String action, JSONArray args, String callbackId) { this.callbackId = callbackId; JSONObject options = args.optJSONObject(0); if (action.equals("pickFile")) { showDialog(options, PICK_FILE_RESULT_CODE); } else if (action.equals("pickFolder")) { showDialog(options, PICK_DIRECTORY_RESULT_CODE); } else { return new PluginResult(PluginResult.Status.INVALID_ACTION); } PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT); r.setKeepCallback(true); return r; } private void showDialog(JSONObject options, int type) { Intent intent; if (type == PICK_FILE_RESULT_CODE) { intent = new Intent("org.openintents.action.PICK_FILE"); } else { intent = new Intent("org.openintents.action.PICK_DIRECTORY"); } if (options != null) { String title = options.optString("title"); if (title != null) { intent.putExtra("org.openintents.extra.TITLE", title); } String button = options.optString("button"); if (button != null) { intent.putExtra("org.openintents.extra.BUTTON_TEXT", button); } } //intent.setData(Uri.fromFile(new File("/"))); try { this.cordova.startActivityForResult((Plugin)this,intent,PICK_FILE_RESULT_CODE); } catch (ActivityNotFoundException e) { showDownloadDialog(); } } private void showDownloadDialog() { final Context context = this.cordova.getContext(); Runnable runnable = new Runnable() { public void run() { AlertDialog.Builder dialog = new AlertDialog.Builder(context); dialog.setTitle("Install File Manager?"); dialog.setMessage("This requires the free OI File Manager app. Would you like to install it now?"); dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dlg, int i) { dlg.dismiss(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:org.openintents.filemanager") ); try { context.startActivity(intent); } catch (ActivityNotFoundException e) { // We don't have the market app installed, so download it directly. Intent in = new Intent(Intent.ACTION_VIEW); in.setData(Uri.parse("http://openintents.googlecode.com/files/FileManager-1.2.apk")); context.startActivity(in); } } }); dialog.setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dlg, int i) { dlg.dismiss(); } }); dialog.create(); dialog.show(); } }; this.cordova.getActivity().runOnUiThread(runnable); } #Override public void onActivityResult(int reqCode, int resultCode, Intent data) { //super.onActivityResult(reqCode, resultCode, data); //Log.d(LOG_TAG, "Data is " + data.getData().toString()); Log.d(LOG_TAG, "we are in on activity result"); switch (reqCode) { case PICK_FILE_RESULT_CODE: case PICK_DIRECTORY_RESULT_CODE: { if (resultCode==Activity.RESULT_OK && data!=null && data.getData()!=null) { String filePath = "file://" + data.getData().getPath(); Log.d(LOG_TAG, "The data is = " + filePath); Log.d(LOG_TAG, "Calling succes with callback id = " + this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, filePath), this.callbackId); } break; } } } } Then you'd need to write your JavaScript interface: FileDialog: { pickFile: function(successCallback, errorCallback, options) { var win = typeof successCallback !== 'function' ? null : function(f) { window.resolveLocalFileSystemURI(f, function(fileEntry) { successCallback(fileEntry); }, fail); }; cordova.exec(win, errorCallback, "FileDialog", "pickFile", [options]); }, pickFolder: function(successCallback, errorCallback, options) { var win = typeof successCallback !== 'function' ? null : function(d) { window.resolveLocalFileSystemURI(d, function(dirEntry) { successCallback(dirEntry); }, fail); }; cordova.exec(win, errorCallback, "FileDialog", "pickFolder", [options]); }, patch: function() { var inputs = document.getElementsByTagName("input"); for (var i=0; i < inputs.length; i++) { if (inputs[i].getAttribute('type') == 'file'){ var me = inputs[i]; inputs[i].addEventListener("click", function() { corinthian.FileDialog.pickFile(function(fileEntry) { me.value = fileEntry.fullPath; }); }); } } } } and finally monkey patch by calling FileDialog.patch(); once you have received the deviceready event in PhoneGap. Hope this helps...
Android to Javascript Calling issue
I have a android method which one is called from Javascript for getting the selected filepath info from phone gallery. Now i want to send the filepath name to the javascript method but if i return the filepath name from the android function then it will always return the last filepath info not the current one (May be its for callback!) or if i call any javascript method to send the file info after getting the file path then its show on debug console like that: 05-04 22:07:50.274: ERROR/Web Console(331): ReferenceError: Can't find variable: SetImageFileName at undefined:1 And here is my Code what i have done... public class Hello extends Activity { /** Called when the activity is first created. */ WebView webview; private ProgressDialog progressBar; private static final int SELECT_PICTURE = 1; private static final int PICK_IMAGE = 1; private String selectedImagePath; private String filemanagerstring; private long siteId; #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); webview = (WebView) findViewById(R.id.webview); webview.addJavascriptInterface(new JavaScriptInterface(this), "Android"); webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY); webview.setWebViewClient(new HelloWebViewClient()); WebSettings webSettings = webview.getSettings(); webSettings.setSavePassword(false); webSettings.setSaveFormData(false); webSettings.setJavaScriptEnabled(true); webSettings.setSupportZoom(false); webview.loadUrl(getString(R.string.ApplicationWebURL)); } public String getPath(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(uri, projection, null, null, null); if (cursor != null) { // HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL // THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } else return null; } #Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ if (resultCode == RESULT_OK) { if (requestCode == SELECT_PICTURE) { Uri selectedImageUri = data.getData(); String filePath = null; try { // OI FILE Manager filemanagerstring = selectedImageUri.getPath(); // MEDIA GALLERY selectedImagePath = getPath(selectedImageUri); selectedFileName=getFileName(selectedImagePath); if (selectedImagePath != null) { filePath = selectedImagePath; } else if (filemanagerstring != null) { filePath = filemanagerstring; } else { Toast.makeText(getApplicationContext(), "Unknown path", Toast.LENGTH_LONG).show(); Log.e("Bitmap", "Unknown path"); } } catch (Exception e) { Toast.makeText(getApplicationContext(), "Internal error", Toast.LENGTH_LONG).show(); Log.e(e.getClass().getName(), e.getMessage(), e); } } } } final class JavaScriptInterface { Context mContext; JavaScriptInterface(Context c) { mContext = c; } /** Show a toast from the web page */ public String ShowPhoneGallery(long sId) { try { siteId=sId; Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"),PICK_IMAGE); } catch (Exception e) { Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show(); Log.e(e.getClass().getName(), e.getMessage(), e); } //Calling Javascript to return the value webview.loadUrl("javascript:SetImageFileName('"+ selectedImagePath +"')"); return selectedImagePath; } } } I s there anybody who can help me on this issue ...
Looks to me like you need to put this line webview.loadUrl("javascript:SetImageFileName('"+ selectedImagePath +"')"); in a different method which is then called from onActivityResult once your user has selected the picture