Android webView与java代码互调API 16+

使用javascript调用android代码

1.使用webview对象的addJavascriptInterface方法

2.addJavascriptInterface方法有两个参数,第一个参数就是我们一般会实现一个自己的类,类里面提供我们要提供给javascript访问的方法;第二个参数是访问我们在obj中声明的方法时候所用到的js对象,调用模式为window.interfaceName.方法名()或者是javascript: interfaceName.方法名() ;,如myWebView.addJavascriptInterface(new JavaScriptinterface(this), "android");

3.编写JavaScriptinterface类,如有一个函数名为showToast()的方法

4.在html中调用时的形式:javascript:android.showToast()。
附上一个小例子:


import android.content.Context;
import android.widget.Toast;

public  class JavaScriptinterface {

     private Context mContext;

     /**  Instantiate the interface and set the context  */
     public JavaScriptinterface(Context c) {
        mContext = c;
    }

     /**  Show a toast from the web page  */
     public  void showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}



import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public  class MainActivity  extends Activity {
     /**  Called when the activity is first created.  */
     private WebView myWebView;

    @Override
     public  void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        myWebView = (WebView) findViewById(R.id.myWebView);
        myWebView.getSettings().setJavaScriptEnabled( true);
        myWebView.addJavascriptInterface( new JavaScriptinterface( this),
                "android");
        String htmlText = getFromAssets("test.html");
         // 把myWebView加载html
        myWebView.loadData(htmlText, "text/html", "utf-8");
        myWebView.setWebViewClient( new myWebViewClient());
        
    }

     //  此按键监听的是返回键,能够返回到上一个网页(通过网页的hostlistery)
     public  boolean onKeyDown( int keyCode, KeyEvent event) {
         if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
            myWebView.goBack();
             return  true;
        }
         return  super.onKeyDown(keyCode, event);
    }

     public String getFromAssets(String fileName) {
         try {
            InputStreamReader inputReader =  new InputStreamReader(
                    getResources().getAssets().open(fileName));

            BufferedReader bufReader =  new BufferedReader(inputReader);

            String line = "";
            String Result = "";

             while ((line = bufReader.readLine()) !=  null)
                Result += line;
             if (bufReader !=  null)
                bufReader.close();
             if (inputReader !=  null)
                inputReader.close();
             return Result;
        }  catch (Exception e) {
            e.printStackTrace();
        }
         return  null;
    }

     class myWebViewClient  extends WebViewClient {

        @Override
         public  boolean shouldOverrideUrlLoading(WebView view, String url) {
             //  TODO Auto-generated method stub
            view.loadUrl(url);
             return  true;
        }

    }
}



<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html  xmlns ="http://www.w3.org/1999/xhtml"  xml:lang ="zh-CN"  dir ="ltr" >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=UTF-8"   />

< script  type ="text/javascript" >   
function showAndroidToast(toast) {       
    javascript:android.showToast(toast);   
     }
</ script >

</ head >
< body >
< input  type ="button"  value ="Say hello"
    onClick
="showAndroidToast('Hello Android!')"   />
</ body >
</ html >



android的应用程序中,可以直接调用WebView 中的javascript 代码:


import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;

public  class MainActivity02  extends Activity {
     /**  Called when the activity is first created.  */
     private WebView webView; 
       private Button button; 
      @Override 
       public  void onCreate(Bundle savedInstanceState) { 
           super.onCreate(savedInstanceState); 
          setContentView(R.layout.main2); 
           
          webView=(WebView)  this.findViewById(R.id.webView); 
          button=(Button)  this.findViewById(R.id.button); 
           
          WebSettings setting=webView.getSettings(); 
           // 设置支持javascript 
          setting.setJavaScriptEnabled( true); 
             // 增加接口方法,让html页面调用   
          webView.addJavascriptInterface( new Object(){ 
               // 这里我定义了一个拨打的方法   
               public  void startPhone(String num){ 
                  Intent intent= new Intent(); 
                   
                  intent.setAction(Intent.ACTION_CALL); 
                  intent.setData(Uri.parse("tel:"+num)); 
                  startActivity(intent); 
              } 
          }, "demo"); 
           // 加载页面 
          webView.loadUrl("file:///android_asset/test2.html"); 
           
          button.setOnClickListener( new OnClickListener() { 
               
              @Override 
               public  void onClick(View v) { 
                   //  TODO Auto-generated method stub 
                  webView.loadUrl("javascript:show('activity传过来的数据')");  // 调用javascript函数
                   /*
                  * 通过webView.loadUrl("javascript:xxx")方式就可以调用当前网页中的名称
                  * 为xxx的javascript方法
                  
*/
              } 
          }); 
}

}  



<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" > 
< html > 
< head > 
< meta  http-equiv ="Content-Type"  content ="text/html; charset=UTF-8" > 
< title >Insert title here </ title > 
< script  type ="text/javascript" > 
      function show(content){ 
         document.getElementById("countent").innerHTML= 
             "这是我的javascript调用. 这是:"+content; 
     } 
</ script > 
</ head > 
< body > 
   < table  align ="center" > 
      < tr >< td >姓名 </ td >< td >电话 </ td ></ tr > 
      < tr >< td >小明 </ td >< td >< a   href ="javascript:demo.startPhone(123)" >123 </ a ></ td ></ tr > 
      < tr >< td >小王 </ td >< td >< a   href ="javascript:demo.startPhone(456)" >456 </ a ></ td ></ tr > 
   </ table > 
   < id ="countent" >html原始数据 </ p > 
</ body > 
</ html >


android addJavascriptInterface 不能生效 解决办法


常见的客户端与H5的混合编程是使用scheme+、JS bridge、provider等。

在做Android 与 H5 客户端交互时,发现一个很诡异的错误。在一个4.2.2的 三星S3上,Android Javascript Bridge 会出现回调出错。

所有挂在Bridge对象下的函数均无法找到。于是一点点排查问题到底出现在哪。

其他手机H5混合编程消息回调正常,本以为是因为是旅行V3.0是基于Fragment引起的,即fragment下不能使用。后来经过排查发现不是这个问题。

发现就是手上的一台S3不行,其他基本都可以进行消息回调。

排查了一大圈,发现在Android SDK Target API Level 16+的情况下,使用以往的方式进行Native 与 H5进行混合编程均无法搞定。

解决办法:

 

  1. 推荐使用较高的Target SDK去编译【4.0+】.

2. 在Javascript Bridge对象下的所有回调方法使用 @JavascriptInterface 进行注解声明

3. 需要 import android.webkit.JavascriptInterface;

使用4.0+版本的Target SDK时,需要注意对回调方法进行注解声明!这种坑 很难发现,使用类似的混合编程技术的团队请关注这点~

 

设备ROM版本

开发环境 Target SDK

不用注解,消息是否能生效

<4.0

>4.0

Ok

<4.0

<4.0

Ok

>4.0

>4.0

NO

<4.0

>4.0

OK

 

public class J2NBridgeManager {

 

@JavascriptInterface

public void startNativeService(String schemeUrl) {

// js回调为空 则直接返回

if (TextUtils .isEmpty(schemeUrl)) {

return;

}

 

final TripURL mServiceUrl = Utils.getURIByUrlWithDecoded(schemeUrl);

// 执行本地一个service ,异步处理完后,回调js

mHandler.post( new Runnable() {

@Override

public void run() {

doService(mServiceUrl);

}

});

}

}

参考文章:

如何建立通信: http://stackoverflow.com/questions/13063222/web-view-addjavascriptinterface-issue

解决问题说明: http://stackoverflow.com/questions/16353430/appview-addjavascriptinterface-doen-not-work-on-api-17

2.微信android 5.0+版本的消息分享,无法通过scheme唤起 第三方客户端

之前我们会通过provider 在微信webview中JS检查手机是否安装旅行客户端,然后通过下面的方式进行逻辑分发:

通过scheme唤醒第三方客户端,在<5.0版本前均可以通过window.location.href = 'taobaotravel://h5_homepage';的自定义的scheme去实现,但是微信5.0版本后,貌似是在微信的webview中进行了url过滤,对应非信任的url进行了屏蔽,所以导致不能发起scheme去唤醒客户端。

关于URL白名单这个东西,目前仅仅为猜测,如果谁有微信的那边的朋友【微信研发团队是在广州】,可以帮忙确认下。

如果确认是微信加了白名单,目前通过微信5.0+webview唤醒我们的第三方app将变成死路。。。。

如果能通过商业合作的方式也是可取的

 

if(isMac) {
  if(getAvailabled()) {
  $('J_btn').innerHTML = '旅行启动中…';
   
  setTimeout(function() {
  if(window.location.href.match('promo-assit.php')) {
  window.location.href = 'taobaotravel://h5_homepage';
  $('J_btn').innerHTML = '启动旅行客户端';
  return;
  }
   
  window.location.href = 'taobaotravel://h5_webview?' + param;
  $('J_btn').innerHTML = '启动旅行客户端';
  }, 1300);
  } else {
  // 跳活动页面
  if(window.location.href.match('promo-assit.php')) {
  window.location.href = 'http://lv.taobao.com/';
  } else {
  window.location.href = fixUrl(jmpurl);
  }
  }
  }

转载至:

http://www.cnblogs.com/lee0oo0/archive/2012/08/01/2617953.html

http://blog.sina.com.cn/s/blog_4e1e357d0101gju8.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值