スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【Android開発】いろいろなBroadcast②

引き続き、AndroidのBroadcastに関して、おさらーい。

前回Context.sendOrderedBroadcast()について書いた。今回はContext.sendStickyBroadcast()について書いていく。

sendStickyBroadcast()

sendStickyBroadcast()でブロードキャストすることで、スティッキーなBradcast Intentを送ることができる。スティッキーなBradcast Intentは配信が終了した後も存在し続け、配信が終了した後に登録されたBroadcastReceiverにも配信されるIntentなのだ。スティッキーとは、粘着性という意味だ(と思う)。このBradcast Intentは、removeStickyBroadcast()を呼ぶまで存続し続ける。システムが配信するStickyなBroadcastでは、たとえばACTION_BATTERY_CHANGEDで利用している。スティッキーなBradcast Intentなので、前回のバッテリーの状態が保存されているので、BroadcastReceiverを登録した瞬間にバッテリーの状態を取得できるのだ。

当初、このスティッキーBroadcastを知らない私は、なぜ、ACTION_BATTERY_CHANGEDを受けるフィルターを持つBroadcastReceiverが即座にバッテリーの状態を受信できるのか不思議だったが、スティッキーBroadcast Intentを知って納得がいった。

これに関連した話だが、ContextクラスのregisterReceiver()メソッドの定義は
public abstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter)
となる。この戻り値のIntentは、実はfilterに合致したスティッキーなIntentであり、該当するIntentがない場合はnullとなる。
登録したBroadcastReceiverのIntentFilterがスティッキーなIntentに合致すれば、そのIntentが、戻り値として即座にかえてくるということである。該当するスティッキーなIntentが複数ある場合は、そのうちの一つだけが戻り値として戻る。どのIntentが戻るかはアプリからは制御できない。スティッキーなIntentをその場で取得したいだけなら、第一引数のreceiverをnullにして呼び出せばよいのだ。

【Android開発】いろいろなBroadcast①

AndroidのBroadcastに関して、改めておさらい。

たいていの場合、BroadcastReceiverにBroadcast Intentを送る場合、Context.sendBroadcast()を使うが、そのほかにも、Context.sendOrderedBroadcast()Context.sendStickyBroadcast()などがある。

とりあえず、ここでは、Context.sendOrderedBroadcast()について説明する。

sendOrderedBroadcast()

sendOrderedBroadcastを使うと、このメソッドで配信したBroadcast Intentが、受信可能なBroadcastReceiverに順番に配信されるようになる。配信される順番は、Intent Filterに設定されるプライオリティで決まる。

コード上では、以下のようにIntent Filterに設定する。
myReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter("MY_ACTION");
intentFilter.setPriority(10);
registerReceiver(myReceiver, intentFilter);

AndrooidManifest.xmlファイルのBroadcastReceiverのプライオリティをセットする場合は、android:priority属性を使用する。





ここではそれぞれに10と100をプライオリティとして設定しているが、初期設定0から1000までの値を設定でき、大きい値ほど高い優先度を持つ。この設定によって、より優先度の高いBroadcastReceiverから配信されていく。優先度が同じものがある場合は、順番はランダムになるようだ。

また重要な特徴として、このメソッドでのBroadcastでは、レシーバ側で配信の中断を行うことができる。また各レシーバでの処理結果などを最終的に配信元で受け取ることができるのだ。

以下のような感じで、各レシーバ側のsetResultCode()、setResultExtras()、setResultData()でデータをセットできる。これらのメソッドを使って値を設定すると、そのレシーバの前に呼ばれているレシーバでセットした値は上書きされる(Bundleの場合は、keyが同じであれば)
 @Override
public void onReceive(Context context, Intent intent)
{
setResultCode(getResultCode());

Bundle extras = getResultExtras(true);
extras.putString("key", "value");
setResultExtras(extras);
}

Context.sendOrderedBroadcast()は2種類あり、結果を受け取れるのは、以下のメソッドである。
public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)

最終的にセットされたデータを取得するには、第3引数のresultReceiverに指定したBroadcastReceiverのOnReceiveメソッド内で、getResultCode()、getResultExtras()、getResultData()を使うことになる。

また、abortBroadcast()を呼び出せば、以降のBroadcastReceiverに配信されなくなる。この場合でも、最終的な結果は受け取れる。

次回はContext.sendStickyBroadcast()に書こうと思う。

iOSでボタンの同時押しを禁止する方法

iOSのアプリを開発しているときにハマったので、書いておく。

iOSってデフォルトでボタンの同時押しが可能なのね。知らなかったのでハマったよ…。いろいろボタンを同時押しして、テストしてみたら、おかしな動きをしてしまう箇所が結構あったよ。とほほ…

で、要はボタン(View)のタップなどのイベントを同時に発生させたくないわけだ。

ボタンの単純なシングルタップイベントの場合

タップイベントに対する同時発生を抑制するのは簡単だ。以下のように、ボタンに対して、UIViewのexclusiveTouchプロパティに「YES」を設定するばいい。

button.exclusiveTouch = YES;

このようにすれば、他のボタンを押している間、このボタンは反応しなくなる。

Eclipse上で、AndroidのJUnitテスト

今更ながら、EclipseでAndroidのプログラムをユニットテストする方法。

テストターゲットのAndroidプロジェクトを作成

まず、いつもどおり、Androidのプロジェクトを作成する。本記事では、

プロジェクト名:AndroidUnitTestTarget
パッケージ名:com.hoge.target

とした。そして以下のように、「MainActivity」というエントリーのアクティビティを作成する。

MainActivity.java

package com.hoge.target;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TextView result = (TextView) findViewById(R.id.resultText);

result.setText("result:" + plus(1, 2));
}


public int plus(int a, int b){
return a + b;
}

}

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:id="@+id/resultText"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</RelativeLayout>

テストのAndroidプロジェクトを作成

次に、テスト実行用のプロジェクトを作成する。

新規>その他>Android>Androidテスト・プロジェクトを選択
android_unit_test00.png
次へをクリック
プロジェクト名をAndroidUnitTestTargetTestとする
android_unit_test01.png

「Select Test Target」のダイアログで、テスト対象のプロジェクトとして先ほど作成した「AndroidUnitTestTarget」を選択。

作成されたプロジェクトのsrcフォルダ内に

com.hoge.target.test

というパッケージが追加されているので、その中に以下のテストケースのクラスを追加する。

TestMain.java

package com.hoge.target.test;

import android.test.ActivityInstrumentationTestCase2;
import android.widget.TextView;

import com.hoge.target.MainActivity;
import com.hoge.target.R;


public class TestMain extends ActivityInstrumentationTestCase2<MainActivity> {

private MainActivity mActivity;
private TextView mResutTextView;

public TestMain() {
super(MainActivity.class);
}

@Override
protected void setUp() throws Exception {
super.setUp();

// アクティビティを取得
mActivity = getActivity();
mResutTextView = (TextView) mActivity.findViewById(R.id.resultText);
}

public void testResut() {
assertEquals(5, mActivity.plus(2, 3));
}

public void testResutText(){
assertEquals(mResutTextView.getText(), "result:3");
}

}

あとは、プロジェクトを右クリック>実行>Android JUnit Test

で、実行。

Eclipse上の「JUnit」のタブに、実行結果が出る。

実行:2/2 エラー:0 失敗:0

全テストを通過すると、緑色のバーが表示される。

android_unit_test02.png


エラーやテストに失敗した場合は、バーが赤色になる。

テーマ : android
ジャンル : コンピュータ

JCIFSを使ってWindows共有フォルダをandroidから参照する

案件で、Windowsの共有ファイルをAndroidから読み書きする必要が出てきたので、実現方法を調べてみた。

どうやら、JCIFSというライブラリを使えば簡単にWindowsの共有ファイルにアクセスできることがわかった。

CIFSとは

そもそもJCIFSの「CIFS(Common Internet File System)」ってのは、もともとWindowsのファイル共有サービスで利用されているプロトコル「SMB」を拡張して、Windows以外のOSやアプリケーションソフトでも利用できるようにものだそうだ。知らんかったわ…、勉強になりやす。


JCIFSを使ってみる

JCIFSのライブラリはhttp://jcifs.samba.org/からダウンロードできる。
jcifs00.png

今回は、上記サイトからjcifs-1.3.17.zipをダウンロードした。ダウンロードしたZipファイルを解凍した中にある「jcifs-1.3.17.jar」をEclipseのAndroidプロジェクトのlibフォルダにをコピー。

とりあえず、今回は、Windowsの共有ファイルを読むところまでを書いてみた。
public void loadShareFile() {

SmbFile dir;
String host = "host name";
String user = "user name";
String password = "pass";

try {
//最後にバックスラッシュが必要
String path = "smb://" + user + ":" + password + "@" + host + "/test/";
dir = new SmbFile(path);

//ファイル一覧セット
SmbFile[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {

//ファイルパスを取得
String filePath = files[i].getPath();
Log.i(TAG, "File name: " + filePath);

//ファイル取得
SmbFileInputStream sfis = new SmbFileInputStream(filePath);
BufferedReader br = new BufferedReader(new InputStreamReader(sfis, "sjis"));

String str;
while ((str = br.readLine()) != null) {
Log.i(TAG, "data: " + str);
}

br.close();
sfis.close();
}

} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.toString());
}
}

必要なパーミッションは
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.ADD_SYSTEM_SERVICE

クローズや例外処理の部分が適当なのは勘弁してね。上の例では、「test」という共有フォルダ内のテキストファイルの内容をすべて表示している。指定するパスの最後にバックスラッシュが必要なところに気をつけたい。
プロフィール

basarafire

Author:basarafire
IT関連会社で情報処理の基礎やプログラミング(主にC・Java)を教えています。最近はAndroidの教育や開発なども行ったりしています。

basarafireの開発したアプリに関する内容はこちらから
http://basarafire.jugem.jp/

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
お気に入り
[プレスブログ]価値あるブログに換金可能なポイントを差し上げます。 アクセストレードレビュー
提携
ゲーム
QRコード
QR
リンク
RSSリンクの表示
お気に入り商品
カウンター
おすすめAndroid書籍
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。