Posted at

Androidで動くBASIC!でcanvasのデータをファイルに保存( BASIC プログラミング )

※この記事はBASIC!利用者以外には意味が無い内容です。ご注意ください。

BASIC!は、Androidで動くBASIC インタープリタです。詳しくは以下をどうぞ。

BASIC!にはHTMLモードというモードがWebViewでHTMLを表示して画面UIを実装できます。JavaScriptやCSSも使えるのでJSライブラリやjQueryプラグイン等も使えて便利です。

但し、以下の困る点もあります。


  • JavaScriptからローカルのファイルアクセスが基本的にできない

今回はファイルをダウンロードする場合で出来ない例とその回避策を記載します。


1.出来ない例

良くある例としてcanvasからダウンロードする例です。


index.html

<button id="btn">ダウンロード</button>

<canvas id="canvas" width="500" height="500"></canvas>


index.js

function saveCanvas(){

let canvas = document.getElementById("canvas");

let link = document.createElement("a");
link.href = canvas.toDataURL("image/png");
link.download = "noname.png";
link.click();
}

var btn = document.getElementById("btn");
btn.addEventListener( "click" , saveCanvas , false );


一般のブラウザーでは、上記のようにすれば「ダウンロード」ボタンを押せばダウンロードできると思います。

しかしBASIC!ではダウンロードボタンを押しても何も起こりません。


2.回避策

HTMLは特に変更しません。 JavaScriptを以下の通り変更します。


index.js

function saveCanvas(){

let canvas = document.getElementById("canvas");
Android.dataLink(canvas.toDataURL());
}

var btn = document.getElementById("btn");
btn.addEventListener( "click" , saveCanvas , false );


Android.dataLink(変数)はBASIC!のみに存在する特殊な命令で実行されると変数の内容をBASIC!のネィティブプログラム(=BASICプログラム)に連携します。

BASIC!のプログラムは以下になります。


test.bas

console.title "HTMLモード"

! HTMLファイルを画面に表示
HTML.OPEN
HTML.LOAD.URL "index.html"

xnextUserAction:

! loop until data$ is not ""

DO
HTML.GET.DATALINK data$
UNTIL data$ <> ""

type$ = LEFT$(data$, 4)

data$ = MID$(data$,5)

SW.BEGIN type$

! Back Key を押した時
SW.CASE "BAK:"
print "BACK key: " + data$
popup "終了します",0,0,0
pause 2000
HTML.CLOSE
exit
SW.BREAK

! Android.datalinkでデータが来た時
SW.CASE "DAT:"
popup "透過型png生成",0,0,1
! datauri文字列の先頭部分を削除
motox$=replace$(data$,"data:image/png;base64,","")

! datauri文字列をデコード
ccc$=decode$("base64","ISO-8859-1",motox$)
popup "デコード完了",0,0,1

xfset:
! ファイル名指定ダイアログ表示
Input "保存ファイル名を指定",kkaf$,"hozon.png",iscanceled

! ダイアログをキャンセルされた時
if iscanceled=1 then
goto xfset
endif

! デコード済データをバイナリーで書き出し
byte.open w,flb,kkaf$
byte.write.buffer flb,ccc$
byte.close flb

popup kkaf$+"を作成完了",0,0,1

endif
SW.BREAK

! その他の時
SW.DEFAULT
PRINT "Unexpected data type:", type$ + data$
popup "終了します",0,0,0
pause 2000
exit

SW.END

goto xnextUserAction

end


簡単ですが説明は以下です。



  • SW.CASE "DAT:のSW文ブロックでAndroid.datalinkでHTML側から送られてきた変数(canvasのBASE64データ)を処理します。

  • datauri文字列をカットして残りの部分を"base64","ISO-8859-1"でデコードしています。

  • 後はバイナリーで保存するだけです


3.おわりに

多分、この情報が必要な方はいないとは思いますが特にネット上に情報も無いので書いておこうと思いました。

以 上