2014年3月30日日曜日

SwipeRefreshLayoutを使ってSwipe更新を実装する

Layoutの作成

レイアウトはandroid.support.v4.widget.SwipeRefreshLayoutを使用します。
コンテンツはSwipeRefreshLayoutの子Viewとして記述します。

1
2
3
4
5
6
7
8
9
10
11
12
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_refresh_widget"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
     
    <!-- some full screen pullable view that will be the offsetable content -->
 
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/content"/>
</android.support.v4.widget.SwipeRefreshLayout>


Swipeによる更新

Swipeによる更新は次のように行います。
1. 更新開始タイミングをハンドルするために、setOnRefreshListenerメソッドにリスナーをセット
2. onRefresh()で更新開始をハンドリング
3. 更新処理が終わったら、setRefreshing(false)をコールする


1
2
3
4
5
6
7
@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.sample_swipe_refresh_widget);
 mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_widget);
 mSwipeRefreshLayout.setOnRefreshListener(this);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public void onRefresh() {
 refresh();
}
 
private void refresh() {
 Message msg = mHander.obtainMessage(0, this);
 mHander.sendMessageDelayed(msg, 1000);
}
 
private static Handler mHander = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  SwipeRefreshLayoutActivity activity = (SwipeRefreshLayoutActivity) msg.obj;
  activity.mSwipeRefreshLayout.setRefreshing(false);
 }
};

2014年3月3日月曜日

GeoFenceの解除

GeoFenceの解除は次のような手順で行います。

1. LocationClientクラスのconnectメソッドをコールして、Location Serviceに接続
2. 接続完了後、removeGeofencesメソッドをコールして、GeoFenceを解除
3. 解除結果はOnRemoveGeofencesResultListenerリスナーで受け取る

removeGeofencesメソッドは2種類あり、GeoFenceのIDを指定(リクエストID)するメソッドとPendingIntentを指定するメソッドがあります。

1
2
3
4
5
public void removeGeofences(List<String> geofenceRequestIds,
                            LocationClient.OnRemoveGeofencesResultListener listener)
 
public void removeGeofences(PendingIntent pendingIntent,
                            LocationClient.OnRemoveGeofencesResultListener listener)


次はGeoFenceのIDを指定(リクエストID)して解除を行うプログラムです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public void onConnected(Bundle bundle) {
    super.onConnected(bundle);
 
    Bundle fragmentBundle = getArguments();
    ArrayList<GeoFenceData> list = fragmentBundle.getParcelableArrayList(GEOFENCE_DATA);
 
    List<String> idList = new ArrayList<String>();
    for (GeoFenceData data : list) {
        idList.add(data.getId());
    }
 
    getLocationClient().removeGeofences(idList, mOnRemoveGeofencesResultListener);
 
}


指定するクラスにより、OnRemoveGeofencesResultListenerリスナーの呼ばれるメソッドが異なります。

メソッド内容
onRemoveGeofencesByPendingIntentResultGeoFenceのID指定による削除用
onRemoveGeofencesByRequestIdsResultPendingIntent指定による削除用


次はonRemoveGeofencesByRequestIdsResultメソッドで結果を受け取るプログラムです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private OnRemoveGeofencesResultListener mOnRemoveGeofencesResultListener = new OnRemoveGeofencesResultListener() {
 
    @Override
    public void onRemoveGeofencesByPendingIntentResult(int statusCode,
            PendingIntent pendingIntent) {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    public void onRemoveGeofencesByRequestIdsResult(int statusCode, String[] geofenceRequestIds) {
        switch (statusCode) {
            case LocationStatusCodes.SUCCESS:
                Toast.makeText(getActivity(), "LocationStatusCodes.SUCCESS", Toast.LENGTH_LONG)
                        .show();
                break;
            case LocationStatusCodes.GEOFENCE_NOT_AVAILABLE:
            case LocationStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
            case LocationStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
            case LocationStatusCodes.ERROR:
                break;
            default:
                break;
        }
        mLocationClient.disconnect();
        mOnGeoFenceRemoverInterface.onGeoFenceRemoved();
    }
 
};

2014年3月2日日曜日

GeoFenceの登録

GeoFenceの登録は次のような手順で行います。

1. LocationClientクラスのconnectメソッドをコールして、Location Serviceに接続
2. 接続完了後、addGeofencesメソッドをコールして、GeoFenceを登録
3. 登録結果をOnAddGeofencesResultListenerリスナーのonAddGeofencesResultメソッドで受け取る


GeoFenceのデータを生成する

addGeofencesメソッドの引数にセットするGeoFenceデータを生成します。データ生成はGeofence.Builderクラスを使用します。(※GeoFenceDataクラスはアプリケーション内に定義したデータクラス)

1
2
3
4
5
6
7
8
9
10
11
static public Geofence toGeofence(GeoFenceData data) {
    Builder builder = new Geofence.Builder();
 
    builder.setRequestId(data.getId());
    builder.setTransitionTypes(data.getTransition());
    builder.setCircularRegion(data.getLatitude(), data.getLongitude(),
            data.getRadius());
    builder.setExpirationDuration(data.getExpiration());
 
    return builder.build();
}

Geofence.Builderクラスには次のようなセッターがあります。

表1.1: Geofence.Builderクラスの主なセットモジュール

メソッド内容
setCircularRegionGeoFenceの領域を指定
setExpirationDuration有効期間を指定(自動的に削除されるまでの時間)、自動削除をしない場合はNEVER_EXPIREを指定
setLoiteringDelayGeoFence指定領域に入ってから留まると判定するまでの時間(ms)を指定
setNotificationResponsivenessGeoFenceから通知を受ける際の応答性
setRequestIdGeoFenceのIDを指定
setTransitionTypestransition typesの指定

表1.2: Geofence.Builderクラスの主なセットモジュール

メソッド内容
GEOFENCE_TRANSITION_DWELL GeoFence指定領域に入って留まる
GEOFENCE_TRANSITION_ENTER GeoFence指定領域に入る
GEOFENCE_TRANSITION_EXIT GeoFence指定領域から出る

GEOFENCE_TRANSITION_DWELLをセットする場合、GeoFence指定領域に入ってから留まると判定するまでの時間を、setLoiteringDelayメソッドで指定する必要があります。



GeoFenceの登録をする

LocationClientクラスのconnectメソッドをコールし、Location Service接続後、LocationClientクラスのaddGeofencesメソッドを使用してGeoFenceを登録します。

1
2
3
4
5
6
7
8
9
10
11
12
public void onConnected(Bundle bundle) {
    super.onConnected(bundle);
 
    Intent intent = new Intent(getActivity(), ReceiveTransitionsIntentService.class);
    mPendingIntent = PendingIntent.getService(
            getActivity(),
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);
 
    getLocationClient().addGeofences(mGeofences, mPendingIntent, mOnAddGeofencesResultListener);
}

第2引数に、GeoFence指定領域に対しトランザクションが発生した場合に発行するPendingIntentをセットします。第3引数に、登録結果を受け取るOnAddGeofencesResultListenerリスナークラスをセットします。



登録の結果を受け取る

OnAddGeofencesResultListenerリスナークラスの例です。登録結果はstatusCodeから判定できます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private OnAddGeofencesResultListener mOnAddGeofencesResultListener = new OnAddGeofencesResultListener() {
 
    @Override
    public void onAddGeofencesResult(int statusCode, String[] geofenceRequestIds) {
        switch (statusCode) {
            case LocationStatusCodes.SUCCESS:
                break;
            case LocationStatusCodes.GEOFENCE_NOT_AVAILABLE:
            case LocationStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
            case LocationStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
            case LocationStatusCodes.ERROR:
                break;
            default:
                break;
        }
        mLocationClient.disconnect();
    }
 
};


GeoFenceの通知

LocationClientクラスのaddGeofencesメソッドをコールする際、PendingIntentをセットしました。このPendingIntentをアプリケーションで受け取ります。次はIntentServiceで受け取る例です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class ReceiveTransitionsIntentService extends IntentService {
 
    public ReceiveTransitionsIntentService(String name) {
        super(name);
    }
 
    @Override
    protected void onHandleIntent(Intent intent) {
        if (LocationClient.hasError(intent)) {
 
            int errorCode = LocationClient.getErrorCode(intent);
            android.util.Log.e("ReceiveTransitionsIntentService",
                    "Location Services error: " +
                            Integer.toString(errorCode));
        } else {
            int transitionType =
                    LocationClient.getGeofenceTransition(intent);
            List<Geofence> geofences = LocationClient.getTriggeringGeofences(intent);
 
            switch (transitionType) {
                case Geofence.GEOFENCE_TRANSITION_ENTER:
                    break;
                case Geofence.GEOFENCE_TRANSITION_EXIT:
                    break;
                default:
                    break;
 
            }
 
        }
 
    }
}