スワイプの検出

スワイプの検出

スワイプの検出は
MotionEventを定義すれば実装できる

まず、定数を宣言

private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;

private GestureDetector mGestureDetector;

次に、onCreate()の中でインスタンス取得

mGestureDetector = new GestureDetector(this, mOnGestureListener);

この
mOnGestureListenerは後で作成

次に、onTouchEvent()の実装

@Override
public boolean onTouchEvent(MotionEvent e){

return mGestureDetector.onTouchEvent(e);
}

そして、スワイプ動作の検出
これは、onFing()の中で処理すればいい

private final SimpleOnGestureListener mOnGestureListener = new SimpleOnGestureListener(){

@Override
public boolean onFing(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY){

try{

if(Math.abs(event1.getY() - event2.getY()) < SWIPE_MAX_OFF_PATH){
return false;
}
if(event1.getX() - event2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY){
Toast.makeText(MainActivity.this, "左スワイプ", Toast.LENGTH_SHORT).show();
}
else if(event2.getX() - event1.getX() > SWIPE_MIN_DISTANCE && Math.abs()velocityX > SWIPE_THRESHOLD_VELOCITY){

Toast.makeText(MainActivity.this, "右スワイプ", Toast.LENGTH_SHORT).show();
}
}catch(Exception e){
//nothing
}

}
return false;
}
};

このように、定数で座標を設定し、それに対する範囲の判定をすることで
スワイプのときの動作をすることができる

raspberry Pi設定

前回、raspberry Piのインストールができたので

今回はIpアドレスの確認とソフトウェアのインストール

まず、raspberry  PiをLANケーブルにつないだ状態で電源を入れる

すると、サーバーみたいな画面になるので

ユーザー名 piを入れ

パスワードを入れてログイン

IPアドレスを調べたいので

hostname -I

でIPを確認

もし、ネットワーク全体を調べたいのなら

ifconfig

で表示できる

ソフトウェアのインストールは

ubuntu と同じように

sudo apt-get install パッケージ名

でインストールできる

今回は、Linuxではおなじみのテキストエディタ vim をインストールするので

sudo apt-get install vim 

ちなみに、アップデートも ubuntuと同じように

sudo apt-get update

でパッケージリストを更新して

sudo apt-get upgrade

でパッケージ更新

ちなみに、アンインストールしたいときには

sudo apt-get autoremove パッケージ名

で依存するパッケージごと削除できる

単純に、指定したものだけ削除するなら

sudo apt-get remove パッケージ名

とすればいい

画面回転の検出

画面回転の検出

画面回転の検出は
Configurationクラスの
orientation変数を使う

値が
ORIENTATION_LANDSCAPEなら横

ORIENTATION_PORTRAITなら縦になる

判定はif()などで行う

例えば、縦、横に回転したときに
トーストで表示するのなら

if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
Toast.makeText(this, "横になったよ", Toast.LENGTH_SHORT).show();
}
else if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this,"縦になったよ", Toast.LENGTH_SHORT).show();
}

これで、縦、横の画面回転の検出ができる

タップ、ダブルタップの検出

タップ、ダブルタップの検出

タップやダブルタップの検出は
GestureDetectorと
onTouchEventを設定すれば実装できる

まず、

implements GestureDetector.OnGestureDetector, GestureDetector.OnDoubleTapListener

を追加

そして

GestureDetector mGestureDetector;

でメンバ変数宣言

次に、onCreate()の中で

mGestureDetector = new GestureDetector(this, this);

でGestureDetectorインスタンス作成

次に、タッチイベント実装

public boolean onTouchEvent(MotionEvent e){

//GestureDetector.onTouchEvent()でタッチイベントの判別、振り分けをする
mGestureDetector.onTouchEvent(e);

return false;
}

次に、シングルタップの実装
今回、はシングルタップならトーストで表示

@Override
public boolean onSingleTapUp(MotionEvent e){

Toast.makeText(this, 
"シングルタップだよ",Toast.LENGTH_SHORT).show();
return false;
}

そして、ダブルタップの処理
今回は、ダブルタップを検出したらトーストで表示

public boolean onDoubleTap(MotionEvent e){

Toast.makeText(this,"ダブルタップされたよ",Toast.LENGTH_SHORT).show();
return false;
}

タップの検出だけなら
ViewへonTouchListenerの設定だけでよい
しかし、ダブルタップとシングルタップを検出するのなら
GestureDetectorを使う

GestureDetectorは、
シングルタップ
ダブルタップ以外に、スワイプなども検出できる

ローダーの作成

ローダーの作成

ローダーを使うには、
FragmentActivityクラスのサブクラスを作成する

ローダーとは、ActivityやFragmentで
非同期にデータをロードする仕組みのこと
データを監視して、コンテンツが変化したら新しい結果を返す
WebでAjaxとかやってるとイメージしやすい

今回は、非同期でブックマーク履歴を読み込んで表示

ブックマークの取得には権限が必要
この権限は
READ_HISTORY_BOOKMARKS
になるので、
AndroidManifest.xmlへ権限を追記する

<uses-permission 
android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>

を追加

次に、レイアウトファイルの作成

<RelativeLayout
xmlns:android="http://schemes.android.com/apk/res/android"
xmlns:tools="http://schemes.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true">
</ListView>

</RelativeLayout>

次に、FragmentActivityクラスのサブクラスを作成し
LoaderCallbacksインターフェースを実装する

onCreate()をOverrideして
ListViewクラスを生成し
Adapterの指定とローダーの初期化をする

それから、LoaderCallbacksインターフェースの実装となる

これには
onCreateLoader()
onLoadFinished()
onLoadReset()
を使う

まずは、メンバ変数の定義

private SimpleCursorAdapter adapter;

次に、onCreate()のOverride

@Override
protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);
setContentView(R.layout.main);

adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
null,
new String[]{Browser.BookmarkColumns.TITLE},
new int[] {android.R.id.text}
,0);

ListView listview = (ListView)findViewById(R.id.list);
listview.setAdapter(adapter);

getSupportLoaderManager().initLoader(0,savedInstanceState,this);
}

次に、onCreateLoader()の実装

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args){

return new CursorLoader(this,Browser.BOOKMARKS_URI,null,null,null,null );
}

そして、onLoadFinished()の実装

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor){
adapter.SwapCursor(cursor);
}

そして、onLoadReset()の実装

@Override
public void onLoadReset(Loader<Cursor> loader){
adapter.setCursor(null);
}

今回、LoaderCallbacksインターフェースの
onCreateLoader()では
Browser.BOOKMARKS_URIで
ブックマークのURIを指定してるけど
電話帳などの
ContentProviderのURIの指定もできる

DialogFragmentの作成

DialogFragmentの作成

DialogFragmentクラスを使ってダイアログを作成するには
FragmentActivityのサブクラスを作成する

まず、Javaで、FragmentActivityクラスのサブクラスを作成

onCreate()の中で
MyDialogFragmentクラスの生成、表示を実装

extends FragmentActivity

で継承しておく

次に、onCreate()の追加部分

//DialogFragment表示
FragmentManager manager = getSupportFragmentManager();

MyDialogFragment dialog = (MyDialogFragment)manager.findFragmentByTag("tag");

if(dialog == null){

dialog = new MyDialogFragment();
Bundle args = new Bundle();
args.putString("message","Message");

dialog.setArguments(args);
dialog.show(manager, "tag");
}

次に、DialogFragmentのサブクラス作成

onCreateDialog()へダイアログの生成

onClick()へ
ok キャンセルボタンを押したときの処理を実装

このクラスでは

extends DialogFragment implements DialogInterface.OnClickListener

で継承しておく

まずは、onCreateDialog()の実装

@Override
public void onCreateDialog(Bundle savedInstanceState){

//値の取得
String message = getArguments().getString("message");

return new AlertDialog.Builder(getActivity()).

//タイトル設定
setTitle("Title")

//メッセージ設定
.setMessage(message)

//okボタンの設定
.setPositiveButton("ok",this)

//cancelボタンの設定
.setNegativeButton("cancel",this)

.create();
}

そして、ボタンクリックしたときの設定
switchで分岐させれるので、okとcancelの処理を
onClick()の中へかける

@Override
public void onClick(DialogInstance dialog, int which){

switch(which){

//okボタンクリックの場合
case AlertDialog.BUTTON_POSITIVE:
Toast.makeText(getActivity(), "ok", Toast.LENGTH_SHORT).show();
break;

//cancelボタンクリックの場合
case AlertDialog.BUTTON_NEGATIVE:
Toast.makeText(getActivity(), "cancel",Toast.LENGTH_SHORT).show();
break;
}
}

FragmentDialogに対して
setArguments()を使って値を渡しているのは
コンストラクタで値を渡すと
ダイアログが生成されるタイミングで値が破棄されることがあるから

Fragmentの作成

Fragmentの作成

Fragmentを使った画面の作成は
FragmentActivityのサブクラスを作成してから
Fragmentの生成、追加をする

Fragmentは、Activityへ配置する部品で
複数のFragmentの配置ができる

Fragmentは自分自身のライフサイクルを持つため
イベント処理、Activityの実行中でも追加、削除が可能

Fragmentのライフサイクルは
Activityのライフサイクルと連動しているので
Activityが休止状態になると
Fragmentも休止状態になる

また、Activityが破棄されるとFragmentも破棄される

まずは、FragmentActivityのサブクラスの作成

public class Fragment extends FragmentActivity implements onClickListener{

}

次に、FragmentのレイアウトファイルをXMLで作成

<LinearLayout
 xmlns:android="http://schemes.android.com/apk/res/android"

android:id="@+id/myfragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</LinearLayout>

次に、JavaでFragmentのためのサブクラスを作成する
これには、レイアウトファイルをロードして生成する

extends Fragment

でFragmentを使えるようにする

今回は、動的にViewを追加する

@Override
public View onCreateView(LayoutInflater inflater , ViewGroup container, Bundle savedInstanceState){

return inflater.Inflate(R.layout.fragment, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState){

super.onViewCreate(view, savedInstanceState);

TextView text = (TextView)findViewById(R.id.text);
text.setGravity(Gravity.CENTER);
text.setText(getArguments().getString(“value”));
}

[/java]

次に、Fragmentを動的に追加する
onClick()をOverrideして
追加ボタンを押したタイミングで
Fragmentクラスを追加、更新する

@Override
public void onClick(View v){

FragmentManager manager = getSupportFragmentManager();
Fragment fragment = manager.findFragmentById(R.id.parent);

if(R.id.btn_add_code == v.getId() || R.id.btn_add_xml == v.getId()){

if(fragment == null){

FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.parent, getMyFragment(v.getId(), true), "MyFragment");

transaction.commit();

}else{
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.parent, getMyFragment(v.getId(), false));
transaction.commit();

}
}else if(R.id.btn_remove == v.getId() && fragment. != null){
FragmentTransaction transaction = manager.beginTransaction();
transaction.remove(fragment);
transaction.commit();
}
}

Fragmentの追加、更新には
FragmentManagerクラスの
beginTransaction()を使うことで
トランザクションを開始する

そして、次に追加、更新、削除した後に
commit()で、トランザクションをコミットする

FragmentManagerクラスの
findFragmentById()で
生成済みのFragmentが取得できないのなら
add()で、Fragmentを追加すればいい

Fragmentが生成済みなら
replace()でFragmentを更新できる

ActivityとServiceの連携

ActivityとServiceの連携

Activityと
Android Interface Definition Language
(AIDL)
を使ったサービスで連携できる

実装するには、まずAIDLインターフェースを定義する

srcフォルダの直下へ
拡張子 .aidlファイル作成

ソースは

package net.developapp.activityservice;

interface ActivityService{
int addString(String value);
String getString();
}

次に、サービス作成

ここではonBind()の実装
.Stubインターフェースの実装をする

@Override
public void onBind(Intent arg0){
return mBinder;
}

//AIDL Binder実装
private ActivityService.Stub Binder = new ActivityService.Stub(){

@Override
public int addString(String value) throws RemoteException{
mStringList.add(value);
return mStringList.size();
}

@Override
public String[] getString() throws RemoteException{

return mStringList.toArray(new String[mStringList.size()]);
}

};
[/java]

そして、Activityの実装
ここでは
ServiceConnectionの実装
Serviceのbind/unbindを実装をする

まず

extends ListActivity

でListActivityを使えるようにする

private ActivityService mService;

//メンバ変数宣言
private savedConnection

//ServiceConnection実装 mServiceConnection = new ServiceConnection(){
public void onServiceConnected(ComponentName name, IBinder ibinder){

//ActivityServiceのインターフェース取得
mService = ActivityService.Stub.asInterface(ibinder);

//一覧内容更新
reloadList();
}

public void onServiceDisconnected(ComponentName name){
mService = null;
}
};

次に、onCreate()へ追記
ボタンを押したときの処理をする

findViewById(R.id.buttonadd).setOnClickListener(
new OnClickListener(){

@Override
public void onClick(View v){

EditText editString = (EditText)findViewById(R.id.editText);
if(mService != null){
try{
mService.addString(editText.getText().toString());
reloadList();

}catch(RemoteException e){
e.printStackTrace();
}
}

}
}

);

//ServiceのBind
Intent service = new Intent(this, ServiceActivity.class);
bindService(service, mServiceConnection, BIND_AUTO_CREATE);

次に、onDestroy()の実装

protected void onDestroy(){
super.onDestroy();

//Bind解除
unbindService(mServiceConnection);
}

そして、ユーザー関数reloadList()の実装

private void reloadList(){
try{
//ActivityServiceから文字列のリスト取得
String[] list = mService.getString();

//文字列のリストをListViewへ設定
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R..layout.sample_list_item_1, list);
setListAdapter(adapter);

}catch(RemoteException e){
e.printStackTrace();
}
}

Android Interface Definition Language 通称
AIDLの使いどころは
別アプリから共通処理としてServiceを呼び出したいとき

また、サーバーみたいに同時に複数の呼び出しがあるので
AIDLインターフェースは
完全にスレッドセーフで実装すること

Raspberry Pi 起動ディスク作成 とインストール

Raspberry Pi 起動ディスク作成

作成に使用したのは Windows ではなく
Ubuntu 12.04 LTS 64bit

必要なものと参考書籍は Amazon で購入

なお、raspberry Pi はケースがなかったのでセットのものを購入

なお Raspberry Pi へのインストールメディアは
SDカードを使う

Raspberry Pi を簡単にインストールできる
OSのインストーラーNOOBSをダウンロードする

URLは
http://www.raspberrypi.org/downloads/

ネットワークインストールか
圧縮ファイルかを選べるけど
圧縮ファイルのほうがネットワークエラーを気にしなくてもいいので
こちらを選択

ダウンロードは Torrent か zip ファイルが選べるので
zip を選択

要領は 1.4GBあるため時間の余裕のあるときに行うのがベスト

次にダウンロードしたディレクトリで

mkdir Raspberry_Pi
cp NOOBS_v1_3_0.zip Raspberry_Pi/
cd Raspberry_Pi/
 unzip NOOBS_v1_3_9.zip 

圧縮ファイルを展開するので、わかりやすいようにディレクトリをつくると作業しやすい

次に SD カードへ書き込む

cp -rp ../Raspberry_Pi/* /media/9016-4EF8/

../ とすれば1つ上のディレクトリになる
• は全部という意味

media のところはSDカードなので
これは環境により異なる

Raspberry Pi のインストールするときには
本体以外に
キーボード
マウス
ディスプレイ
HDMIケーブル
MicroUSB ケーブルが必要になる

今回、デスクトップ Ubuntu 14.04 LTS で使っている
有線のマウスとキーボードを使い
HDMIについては AppleTV で使っていたものを使用

電源となる MicroUSB については
Android の Nexus 7 で使っているものを使用

電源をいれるときの注意点として
最初にSDカードをさした状ED態で電源をいれること

とはいっても電源ボタンはなく
MicroUSB をさすと電源がONになる

面倒なのは電源OFFが抜くのはダメということ
ちゃんとシャットダウンしないと壊れる

電源をいれると、OSインストール画面がでる
今回は
Raspbian [RECOMMEND]
を選択

そしてinstall をクリックすると確認ダイアログがでるので yes を選択

これでインストールされる
注意点としては
Raspberry Pi 本体にインストールするのではなく
SDカードにインストールしているということ

USBとかCDブートのLinux を体験しているとわけりやすい

このため別のOSを起動したいのなら
SDカードを差し替えればいい

インストールが完了したら再起動

再起動するとセットアップオプションが起動する

ちなみに、この画面ではキーボードしか使えない
しかもメニューは全部英語

まず最初に一番上の
Expand Filesystem
について

これはSDカードの領域拡張
これをやらないとどれだけ大きいSDカードを使っても
要領が数百MBしか使えない

これはNOOBSでインストールしたならデフォルトで実行されているので、やらなくていい

次に
Advanced Option について
これを選んで Overscan を設定すると画面の表示を変更できる
デフォルトは Enable
Disable にするとフルスクリーン表示になる
これは画面の大きさにより設定を変える

もし大画面のモニターなら デフォルト設定でOK
画面が小さいなら Disable にすると改善されるかも

次に
Internationallsation Options の
Change Keyboard Layout
でキーボードの種類を設定

私の場合一般的な windows キーボード形式なので
keyboard model では
Gerneric 105-key (intl)PC

keyboard layout では
Other を選択

Country of origin for the keyboard では
Japanese を選択

これで日本語キーボードを使えるようになるので
再び keyboard layout で
Japanese (DADG 109A)を選択

key to function as AltGrでは
The default for the keyboard layout
を選択

Compose key では
No compose key を選択

次の画面で
ctrl + Alt + Backspace でデスクトップを終了する設定をするか聞かれるので
yes を選択

これでキーボード設定ができたので
次にパスワードの変更

Raspberry pi の
ユーザは pi なので
このパスワードを変更するには
Change User Password
で設定する

入力したパスワードは表示されないけど
設定は反映されている

次に言語の設定
これは
Internationallsation Options の
Change Locale で設定

デフォルトは
en_GB_UTF-8

日本語にするには
ja_JP .EUC-JP EUC-JP
ja_JP .UTF-8 UTF-8
のところでスペースを押してチェックをつけ
OKをおす

次にデフォルト言語設定だけど
初期段階では日本語フォントがないので
選ぶと文字化けする
なので、ここでは en_FB/UTF-8 を選択

これで初期段階の言語設定は完了

続いて時間の調整
タイムゾーンを設定するので
Internationallsation Options の
Change Timezone を選択

Asia > Tokyo で設定

とりあえず初期設定はこれで終わりなので
Finish を選択する

これで設定が完了する

設定そのものは
あとでログインして

sudo raspi-config

で再度設定できる

次にログイン方法

ログインするときには
ユーザ名 pi
そして設定したパスワードでログインできる

今回はすでにログイン済みなので
そのまま終了処理を行う

Raspberry Pi の起動は MicroUSB へさすだけだけど
終了はコマンドなどでしっかり行う必要がある

終了コマンドは

sudo shutdown -h now

という Linux ではおなじみのコマンド

終了したかどうかを調べるには
Raspberry Pi 本体の
PWR のLEDが点滅していないのならOK

赤く光っているのは通電しているのを示しているので
MicroUSB がささっている間はずっとついている

これは問題ないので気にせず電源OFFでOK

Activity同士での連携

Activity同士での連携

Activity同士の連携は
startActivityForResult()

OverrideしたonActivityResult()で行う

startActivityForResult()で起動先のActivityを開始すれば
onActivityResult()で処理結果を受け取れる

処理結果は、起動先のActivityを終了したタイミングで呼び出される

まず、起動元Activityを実装する
ここで、startActivityForResult.によるActivityの開始
起動先のActivityから処理結果を受け取るonActivityResult()を実装する

まず、リクエストコードは定数宣言しておく

private static final int REQUEST_CODE = 1;

次に、ボタンを押してActivity連携したいので
onClick()をOverrideする

@Override
public void onClick(View v){
//呼び出す画面Intent作成
final Intent intent = new Intent(MainActivity.this, SendActivity.class);

//Intentのキーに文字列設定
EditText inputString = (EditText)findViewById(R.id.input);
String value = inputString.getText().toString();
input.putExtra("key_name",value);

//戻り値を取得できる呼び出し方法でActivity開始
startActivityForResult(intent, REQUEST_CODE);

}

次に、onActivityResult()のOverride

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){

super.onActivityResult(requestCode,resultCode,data);

//startActivityForResult()実行時の引数に指定したRequestCodeを比較する
if(requestCode == REQUEST_CODE){

//Activity終了時のフラグ判定
if(resultCode == RESULT.OK){

//戻り値として設定された key_nameの値を取得
String value = data.getStringExtra("key_name");

EditText result = (EditText)findViewById(R.id.result);
result.setText(value);
}
}
}

これで、元はできたので起動先のActivityを実装

起動先のActivityでは
Intent経由でパラメーターを受け取る

起動元のActivityへ処理結果を返すので
setResult()を使う

まずは、Intentで渡されたデータがあるか判定
!= nullなら中身ありなので、文字列を取得

Intent intent = getIntent();
if(intent != null){

//渡された文字列を取得
String sendvalue = intent.getStringExtra("key_name");
EditText getString = (EditText)findViewById(R.id.inputString);
getString.setText(sendvalue);
}

そして、起動元へ結果を送る処理の実装

findViewById(R.id.backActivity)setOnClickListener(
new  onClickListener(){

@Override
public void onClick(View v){

EditText result = (EditText)findViewById(R.id.result);

//戻り値に文字列が設定されている場合、戻り値を設定
if(result.getText().length() > 0){

//戻り値のためのIntent作成
Intent data = new Intent();

//戻り値設定
data.putExtra("key_name",data.getText().toString());

//成功とさて設定
setResult(RESULT_OK, data);
}
//Activityの終了
finish();
}
});

Activityから別のActivityへパラメーターを渡すには
Intentにパラメーターを設定する

Intentは仲介役みたいなかんじ

Intentを受け取るには
getIntent()で受け取れる

なお、別のActivityを呼び出して、そこの結果を受け取りたいのなら
startActivityForResult()を使う

startActivityForResult()を使うことで
呼び出したActivityが終了したときに
onActivityResult()が呼ばれるので
setResult()で設定したIntentを戻り値として取得できる

注意点としては
startActivityForResult()は
onRestart()より前に呼ばれるので
処理のタイミングに注意すること