LoginSignup
19
19

More than 5 years have passed since last update.

[Android] native→webviewへ大きめのデータを渡す

Last updated at Posted at 2013-07-06

webviewへデータを渡すには

String url = "javascript:setImg(data)";
wv.loadUrl(url);

のような形がお約束。
ではこれでどのくらいのデータが渡せるか。
渡し方から想像できるようにURLとしての長さの制限(256)を受けます。
つまり関数名やあたまのjavascript:を考えると200ちょっと。

普通はこれで足りるんですが、画像データをbase64形式で渡したかったんです。

で、考えたのはjavascriptの関数を読んで、またnativeを呼び返して、と繰り返していけば40kのデータでも200回繰り返せば渡せるな、と。
そんなにnative-webviewの連続呼び出しがスムーズに行くのかって疑問があるので検証。

まずはbase64のデータを配列にしてコマ切れに。base64にするときにNO_WRAP指定すると改行が無くせます。
URLに改行入ってくると面倒なので先に。

Base64.encodeToString(bytearray, Base64.NO_WRAP);

private String[] imagedata;
private int maxDataLength=100;
private void callbackPhoto(String image64) {
    int datalength = image64.length();
    imagedata=new String[(int) Math.ceil((double)datalength/(double)maxDataLength)];
    for(int i=0;i<imagedata.length;i++){
        int start =maxDataLength*i;
        int limit =Math.min(start+maxDataLength,datalength);
                imagedata[i] = image64.substring(start,limit);
    }
    wv.loadUrl("javascript:setImg(1,\""+imagedata[0]+"\")");
}

javascriptにはいくつめのデータかと、細切れにしたデータを渡してます。

次にjavascript。今回はcount=0のデータがくると最後のデータと判別してます。

base64data="";
function setImg (count,data) {
    base64data+=data;
    if(count==0){
        setImage(base64data);
     }else{
        AndroidApp.getNextImgData(count+1);
    }
}

受け取ったらnativeのgetNextImgDataを呼んで次のデータを待つ。
setImage は後で呼びます。

handler用意して、

Handler mHandler = new Handler();

interfaceでうけとる。スレッドのアレがあるのでhandlerで呼んで

@JavascriptInterface
public void getNextImgData(final int count){
    mHandler.post(new Runnable() {
        public void run() {
            callbackPhoto2Next(count);
        }
    });
}

次のデータを渡す。最後だったら0を一つ目のパラメータに。

private void callbackPhoto2Next(int count) {
    int id=count;
    if(imagedata.length==count){
        id=0;
    }
    String url = "javascript:setImg("+id+",\""+imagedata[count-1]+"\")";
    wv.loadUrl(url);
}

全部渡しきったらあとはJSでcanvasに表示。

function setImage (result) {
    c = document.getElementById("canvas");
    ctx = c.getContext("2d");
    img = new Image();
    img.onload = function(){
        ctx.drawImage(img, 0,0,img.width, img.height, 0,0,img.width, img.height);
    };
    img.src = "data:image/jpeg;base64,"+result;
}

こんなに何度もやり取りしたら遅いだろうと思ったら、30kのデータで0.15s。十分実用範囲。

19
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
19