長押しリンクのURL取得

長押しリンクのURL取得

Webページのリンクを長押ししたら
リンクをクリップボードへコピー
とか
リンク先の保存などをするときに
長押しリンクのURL取得を利用する

WebViewを長押ししたときのイベントを取得するには
長押しを有効にして
長押しのイベントリスナーをセットする

長押しの有効には
WebViewクラスの
setLongClickable()

長押しイベントリスナーのセットには
WebViewクラスの
setOnLongClickListener()
を使う

まず、

implements OnLongClickListener

を追記

private WebView mWebView;

でアクセスしやすくする

次に、onCreate()の中で

mWebView = new WebView(this);
setContentView(mWebView);

これでビュー作成と配置

mWebView.setSettings().setJavascriptEnabled(true);

でJavascriptを使えるようにしておく

mWebView.setLongClickable(true);

で長押し有効に

mWebView.setOnLongClickListener(this);

で長押しリスナーセット

mWebView.setWebViewClient(new WebViewClient());
mWebView.loadUrl("http://www.google.co.jp/");

でWebページ表示

次に、HitTestResult からデータの取り出し

HitTestResultは
ユーザーがアクションを起こした対象の箇所の情報を保持するクラス

WebViewクラスの
getHitTestResult()
で取得できる

さらにそこから長押し対象を判定し、URLを取得する

@Override
public boolean onLongClick(View v){

if(v == mWebView){

//長押しした箇所の情報を取得
HitTestResult hittestresult = mWebView.getHitTestResult();

//長押し対象の判定
switch(hittestresult.getType()){

case hittestresult.SRC_ANCHOR_TYPE:
//長押しがアンカーリンクの処理
String url = hittestresult.getExtra();
Toast.makeText(this, "url: "+ url, Toast.LENGTH_SHORT).show();
break;
}
}
return false;
}

今回は、HitTestResult.SRC_ANCHOR_TYPEなので、HTMLのaタグのリンクを取得している

ほかにも
EDIT_TEXT_TYPE
EditTextの場合

EMAIL_TYPE
メールアドレスの場合

GEO_TYPE
地図情報の場合

IMAGE_TYPE
HTMLのimgタグの場合

PHONE_TYPE
電話番号の場合

SRC_IMAGE_ANCHOR_TYPE
HTMLのaタグで、imgタグを囲んでいる場合

UNKNOWN_TYPE
不明なターゲットの場合
これは、何もないところの長押しとか
通常のテキストの長押しの場合適用される

タイムラプス画像を動画へ変換

タイムラプス画像を動画へ変換

raspberry Pi で撮影した画像を動画変換するけど
処理に時間がかかるので
Ubuntu で行う

sudo apt-get install libav-tools 

で変換ツールをインストール

静止画から動画へ変換するには
avconvコマンドを使う

avconv -r 10 -i image-%04d.jpg -r 10 -vcodec libx264  -crf 29 -g 15 video.mp4

これを core i7 のCPUの Ubuntu でやったら
数秒で変換が終わった

なお変換したファイルは
Ubuntu なら VLC Media Player などで再生できる

avconv コマンドのオプションは
-r で一秒あたりのコマ数
通称フレームレートになる

今回は -r 10 にしたので
1秒間で10コマ進む

撮影するときに1分ごとに撮影しているので
10分を1秒で再生することになる

-i オプションでは変換するファイルの指定
-i image-%04d.jpg
としたので
image-0001.jpg から iamge-0061.jpg
までのファイルを指定している

Youtubeに timelapse で検索すると
いろいろでてくるので自分で挑戦して投稿するとおもしろいかもしれない

https://www.youtube.com/results?search_query=timelapse

で youtube の timelapse をみることができる

raspberry pi でタイムラプス撮影

raspberry pi でタイムラプス撮影

raspberry pi 専用カメラモジュールを使うことで
タイムラプス撮影を行える

今回使用した専用モジュールは
ラズベリーパイ カメラモジュール Camera Module for Raspberry Pi

なお、これだとカバーがないので、作成するか購入することになります

とりあえず
Raspberry Pi用カメラケース (Black)

を購入

タイムラプス撮影は
TVのCMとかで雲が流れる様子や一日の景色が
あっというまに変わっていくような映像のこと

よくみるのは朝日がでて
どんどん時間が流れて夜になるもの

これを行うには
一定間隔で撮影した写真を
つなぎ合わせて高速再生すればいい

raspberry pi で使う raspistill コマンドは
1枚の写真を撮影するコマンドだけど
-tl オプションを使うことで
このタイムラプス撮影が可能になる

タイムラプス撮影をするには、以下のオプションを使う

-o
ファイル名を指定
%d をつけることで通し番号で保存できる
さらに %04d とすれば
4桁の通し番号で保存できる

-tl
撮影間隔の指定
単位はミリ秒となる
1秒なら 1000ミリ秒
1分なら 60000ミリ秒
となる

-t
撮影時間の指定
単位はミリ
これも
1秒なら 1000ミリ秒
1分なら 60000ミリ秒

もし 640 x 480 pixel で1分おきに1時間撮影するなら

raspistill -o image-%04d.jpg -tl 60000 -t 3600000 -w 640 -h 480 

ミリ秒変換は面倒に思えるけど
一度秒単位にして 1000 をかければ算出しやすくなる

もし1時間おきに1週間撮影するなら

raspistill -o image-%04d.jpg -tl 3600000 -t 604800000 -w 640 -h 480 

となる

これで撮影できたけど
これを動画に変換する必要がある

変換に必要なツールはインストールできるけど
raspberry pi ではCPUが非力なので変換には時間がかかる

このため別の Linux マシンで行うほうが効率的

今回は Ubuntu 12.04 LTS に
FileZilla で撮影したファイル
image-0001.jpg から
image-0061.jpg までを
ダウンロード

これを変換することにする
時間がかなりかかる処理になりそうなので
変換作業は後日

端末のバックキーで前に戻るには

端末のバックキーで前に戻るには

端末のバックキーを検出するには
ActivityクラスのonBackPressed()を
Overrideする

そして、このメソッドのスーパークラスは呼ばないこと
これでアプリを終了せずに任意の操作ができる

よくブラウザでもとるキーを押したりして使うことになる

@Override
public void onBackPressed(){

if(mWebView.canGoBack()){
//前のページへ戻る
  mWebView.goBack();
}
else{
//アプリ終了
  super.onBackPressed();
}
}

今回は、WebViewクラスの
onGoBack()で履歴があるか調べ
有るなら前のページへ戻り

履歴がないなら、アプリ終了している

raspberry pi で動画撮影

raspberry pi で動画撮影

Raspberry pi 専用カメラモジュールを使うことで
1080pk
1920 x 1020 ピクセル
で動画を撮影できる

今回も使用したのは
ラズベリーパイ カメラモジュール Camera Module for Raspberry Pi

USB接続のカメラでも動画撮影できるけど
こっちだと 320 x 240 ピクセルぐらいでカクカクになる

動画撮影には
raspivid コマンドを使う

-o オプションで保存したいファイル名を指定する

.h264 拡張子で保存すればH.264 形式の動画ファイルになる

そして -t オプションで撮影する時間をミリ秒単位で指定する
1秒は 1000ミリ秒なので
10秒撮影したいのなら
-t 10000
となる

構文としては

raspivid -o 保存したいファイル名.h264 -t 撮影したいミリ秒

となる

コマンドの例としては

raspivid -o video.h264 -t 10000

これで video.h264 ファイルが作成される

撮影した動画を raspberry pi で再生するには
omxplayer コマンドを使う

これは標準でインストールされているので
そのまま使える

omxplayer 再生したい動画ファイル名
で再生できる

今回なら

omxplayer video.h264 

なお、これはディスプレイにHDMIで接続してあれば
リモートでも表示することができる

今回はSSHで ubuntu からログインして再生したけど
問題なく再生できた

H.264 形式の場合
Raspberry Pi のGPUに
H.264 再生支援機能があるのでなめらかに再生できる

ただ、標準で動画撮影すると
高解像度なため、10秒程度で20MBになってしまう

このため -w で幅 -h で高さを指定して
解像度を調整する

もし 320 x 320 の解像度にするなら

raspivid -o video.h264 -t 10000 -w 320 -h 320

また -b オプションでビットレートの設定ができる

指定する単位はビットなので
10MBits/s
なら
-b 1000000

50KBits/s
なら
-b 50000
となる

例を書くと

raspivid -o video.h264 -t 10000 -w 320 -h 320 -b 50000

ただし、ディスプレイに表示されるのは変換前の状態なので
変換した状態で表示したいのなら
-e オプションをつけて実行

raspivid -o video.h264 -t 10000 -w 320 -h 320 -b 50000 -e

raspberry pi のカメラモジュールでエフェクト機能実験

raspberry pi のカメラモジュールでエフェクト機能実験

前回カメラモジュールを購入したので
引き続きカメラ機能を実験

使用したのは
ラズベリーパイ カメラモジュール Camera Module for Raspberry Pi

本体は
Raspberry Pi Type B 512MB
を使用

raspistill コマンドを使うことでデジカメみたいに写真をとれる

raspistillコマンドは、さまざまなオプションがあり
目的に応じて様々な撮影条件を設定できる

ユニークなものとしてはエフェクト機能

エフェクトモードは20種類あり
-ifx オプションに続けてエフェクトモードを指定することで設定できる

エフェクトモードを水彩画みたいにして撮影するなら

 raspistill -o image.jpg -ifx watercolour

とする

なお、リモートでログインしているとその端末では見れないけど
HDMIケーブルとかでディスプレイに接続しておけば
プレビューをみることができる

HDMIケーブルについては
Amazon で安いのがあったので、これを利用

なお
raspistillコマンドには
露出モードを設定する -ex オプション
ホワイトバランスを設定する -awb オプション
測光モードを設定する -mm オプション
の設定が可能となっている

Webページの進捗状況の取得

Webページの進捗状況の取得

進捗状況がわからないと
フリーズしたと思われる

進捗状況の取得には
WebChromeClientクラスの
onProgressChangedハンドラを使う 

このメソッドをoverrideすることで進捗状況を取得できる

Webview..setWebChromeClient(new WebChromeClient(){

@Override
public void onProgressChanged(Webview view, int newProgress){
super.onProgressChanged(view, newProgress);

//行う処理

}
});

onProgressChanged()の引数は
WebView viewが
WebChromeClient()をセットしているWebView

int newProgressがWebページの進捗状況を表す0~100の数値
これは、パーセンテージを意味する

これで、進捗状況が取得できたので
画面に表示する

表示方法は2種類あり
進捗バーを使うか
進捗インジケータ、これは回転するアイコン
を使うことになる

まず、進捗バーの場合
この場合、レイアウトファイルに
ProgressBarを追加する


[/java]

次に表示する進捗インジケータの準備

進捗インジケータの表示には
ActivityクラスのsetProgressBardeterminateVisibility()を使う

このメソッドを使うには
Activityクラスの
setContentView()を使う前に
ActivityクラスのrequestWindowFeature()を使う必要がある

もし、それより後に実行すると
RuntimeException requestFeature() must be called before adding content
という例外が発生する

タイトルバーに進捗インジケータを表示するなら

@Override
public void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

//タイトルバーへ進捗インジケータ表示
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

setContentView(R.layout.main);
}

というように、レイアウトファイル読み込みの前に記述する

そして、進捗インジケータや進捗バーは
ページ読み込み開始の時点では表示するけど
読み込んだら非表示にしておく

この方がWebページを広く使えるし見やすい
この表示、非表示を実現するには
WebViewClientの
onPageStartedハンドラと
onPageFinishedハンドラを使う

mWebView.setWebChromeClient(new WebChromeClient(){

@Override
public void onProgressChanged(WebView view, int newProgress){

super.lnProgressChanged(view, newProgress);

//進捗状況の取得
mProgressBar.setProgress(newProgress);
}
});

mWebView.setWebViewClient(new WebViewClient(){

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon){
super.onPageStarted(view, url, favicon);

//ProgressBarの表示
mProgressBar.setVisibility(View.VISIBLE);

//進捗インジケータ表示
setProgressBarIndeterminateVisibility(true);

}


@Override
public void onPageFinished(WebView view, String url){
super.onPageFinished(view,url);

//ProgressBar非表示に
mProgressBar.setVisibility(View.GONE);
//進捗インジケータを非表示に
setProgressBar.IndeterminateVisibility(false);
}
});

ページ履歴の前後へ移動するには

ページ履歴の前後へ移動するには

WebViewは、ページ内のリンクをクリックすると次のページへ遷移する

遷移履歴をたどり、戻るなら
goBack()

進むなら
goForward()
を使う

履歴の取得には
WebViewクラスのcopyBackForwardList()を使う

webview.copyBackForwardList();
WebBackForwardList bfList = webview.copyBackForwardList();
WebHistoryItem item = bfList.getCurrentItem();
String title = item.getTitle();
String url = item
getUrl();

さらに、今見ているページ以外の前後の履歴の削除も可能
これは、 clearHistory()を使う

webview.clearHistory();

というように使う

残念なことに1つ前とかのように特定ページのみの削除ということはできない

AndroidでWebコンテンツの表示

AndroidでWebコンテンツの表示

Webコンテンツを表示するには
WebViewクラスのloadUri()を使う

まず、

private WebView mWebView;

でメンバ変数にする

次に、onCreate()の中で

mWebView = new WebView(this);
setContentView(mWebView);

でWebViewが使えるようにする

ただし、このままだとJavascriptが無効なので

mWebView.getSettings().setJavascriptEnabled(true);

でJavascriptを有効にする
そのぶんセキュリティーは落ちるので注意

あとは、表示するWebページを設定

mWebView.setWebViewClient(new WebViewClient());
mWebView.loadUri("http://www.google.co.jp");

あと、WebViewを扱うときには、終了したら破棄する処理も必要

[@Override]
public void onDestroy(){

super.onDestroy();

mWebView.stopLoading();
ViewGroup webParent = (ViewGroup)mWebView.getParent();

if(webParent != null){

webParent.removeView(mWebView);
}
mWebView.destroy();
}
[/java]

これは、AndroidのWebViewは
Javaプログラムだけでなく
ネイティブのCのコードも使っているかららしい

このため、WebViewを明示的に破棄しないと
メモリの解放ができない

このため、Activity.onDestroyハンドラでWebViewクラスの
destroy()を呼んでいる

また、このときに
removeView()でActivityから切り離してから
destroy()を呼ぶこと

これをやらないと
Error: WebViewdestroy() called while still attached
とエラーが発生する

アプリ内でYouTube再生

アプリ内でYouTube再生

Androidアプリ内でYouTubeを再生するには
VideoViewを使う
もしくは
Android YouTube Player API
を使う

Android YouTube Player APIを使う場合
Google Map のAPIを使うときみたいに
Google APIs ConsoleでAPIを使えるようにしておく必要がある

そして、
Simple API Accessの keyをメモしておく

ここまでできたら
Android YouTube Player APIをダウンロードする

これをダウンロードしたら解凍して
libsから
YouTubeAndroidPlayerApi.jar

プロジェクトへ追加する

Eclipseを使っているなら
libs以下へ配置すれび自動認識される

ここまでできたら
レイアウトファイルへ
YouTubeを再生するためのViewを追加する

<com.google.android.youtube.player.YouTubePlayerView
android:id="@+id/youtube"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

次に、Javaでの操作だけど
YouTubeを再生するためには
YouTubeBaseActivityを継承し
OnInitializedListenerを実装する必要がある

さらに
レイアウトファイルで追加したYouTubePlayerViewインスタンスへ
API key の設定も必要になる

まずは、継承から

extends YouTubeBaseActivity implements OnInitializedListener

を追加

次に、API キーなどを変数へ格納

private static final String DEVELOPER_KEY ="取得したAPIキー";
private static final int RECOVERY_DIALOG_REQUEST = 1;

次に、onCreate()の中で
YouTubePlayerViewへDeveloperキーを設定

YouTubePlayerView youtubeView = (YoutubePlayerView)findViewById(R.id.youtube);

youtubeView.Initialize(DEVELOPER_KEY, this);

次に、初期化失敗のときの処理

@Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult errorReason){

//初期化失敗の処理
if(error.Reason.isUserRecoverableError()){
//エラー回避可能ならダイアログで表示
errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST).show();

}else{
//エラー回避不可能ならトーストで表示
String errorMessage = String.format(getString(R.string.error_player),
errorReason.toString());
Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT).show();
}
}

そして、初期化成功のときの処理

@Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player, boolean wasRestored){

//YouTubeの動画Idを設定
if(!wasRestored){
player.cueVideo("再生したい動画のID");
}
}

また、YouTubeにアクセスするということで
AndroidManifest.xmlへ
インターネットにアクセスする権限を追加する

<uses-permission android:name="android.permission.INTERNET"/>

このように、YouTubePlayerViewを使うことで
動画再生のためのボタンやフルスクリーン機能なども自動で実装される

このあたりの制御には
YouTubePlayerViewクラスに実装されているメソッドを使う

APIや制御方法などは、Google Map APIに近い

あと、YouTubeの動画IDは
YouTubeのURLの中の
https://www.youtube.com/watch?v=
の後の部分になる