/*
HueFargment02
Copyright (c) 2014 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.deviceplugin.hue.activity.fragment;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.philips.lighting.hue.sdk.PHAccessPoint;
import com.philips.lighting.hue.sdk.PHHueSDK;
import com.philips.lighting.hue.sdk.PHMessageType;
import com.philips.lighting.hue.sdk.PHSDKListener;
import com.philips.lighting.model.PHBridge;
import com.philips.lighting.model.PHHueError;
import com.philips.lighting.model.PHHueParsingError;
import org.deviceconnect.android.deviceplugin.hue.R;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* Hue設定画面(2)フラグメント.
*
*/
public class HueFragment02 extends Fragment implements OnClickListener {
/** アクセスポイント. */
private PHAccessPoint mAccessPoint;
/** ステータスを表示するTextView. */
private TextView mTextViewStatus;
/** Howtoを表示するTextView. */
private TextView mTextViewHowTo;
/** Button. */
private Button mButton;
/** ImageView. */
private ImageView mImageView;
/** ハンドラー用のCounter. */
private int mCount = 0;
/** ステータス. */
private HueState mHueStatus = HueState.INIT;
/** アニメーション用スレッド. */
private final ScheduledExecutorService mExecutor = Executors.newSingleThreadScheduledExecutor();
/** スレッドキャンセル用オブジェクト. */
private ScheduledFuture<?> mFuture;
/**
* Hue接続状態.
*/
private enum HueState {
/** 未認証. */
INIT,
/** 未接続. */
NO_CONNECT,
/** 認証失敗. */
AUTHENTICATE_FAILED,
/** 認証済み. */
AUTHENTICATE_SUCCESS
}
/**
* hueブリッジのNotificationを受け取るためのリスナー.
*/
private PHSDKListener mListener = new PHSDKListener() {
@Override
public void onAuthenticationRequired(final PHAccessPoint accessPoint) {
mHueStatus = HueState.INIT;
PHHueSDK hueSDK = PHHueSDK.getInstance();
hueSDK.startPushlinkAuthentication(accessPoint);
authenticateHueBridge();
}
@Override
public void onAccessPointsFound(final List<PHAccessPoint> accessPoint) {
}
@Override
public void onCacheUpdated(final List<Integer> list, final PHBridge bridge) {
}
@Override
public void onBridgeConnected(final PHBridge phBridge, final String s) {
mHueStatus = HueState.AUTHENTICATE_SUCCESS;
successAuthorization();
}
@Override
public void onConnectionLost(final PHAccessPoint accessPoint) {
}
@Override
public void onConnectionResumed(final PHBridge bridge) {
}
@Override
public void onError(final int code, final String message) {
if (code == PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) {
failAuthorization();
} else if (code == PHHueError.NO_CONNECTION || code == PHHueError.BRIDGE_NOT_RESPONDING) {
showNotConnection();
}
}
@Override
public void onParsingErrors(final List<PHHueParsingError> errors) {
}
};
/**
* HueFragment02を返す.
*
* @param accessPoint Access Point
* @return HueFragment02
*/
public static HueFragment02 newInstance(final PHAccessPoint accessPoint) {
HueFragment02 fragment = new HueFragment02();
fragment.setPHAccessPoint(accessPoint);
return fragment;
}
@Override
public View onCreateView(final LayoutInflater inflater,
final ViewGroup container, final Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.hue_fragment_02, container, false);
// Macアドレスを画面に反映.
TextView macTextView = (TextView) rootView.findViewById(R.id.text_mac);
macTextView.setText(mAccessPoint.getMacAddress());
// IPアドレスを画面に反映.
TextView ipTextView = (TextView) rootView.findViewById(R.id.text_ip);
ipTextView.setText(mAccessPoint.getIpAddress());
// 現在の状態を表示.
mTextViewStatus = (TextView) rootView.findViewById(R.id.textStatus);
// 作業方法を表示.
mTextViewHowTo = (TextView) rootView.findViewById(R.id.textHowto);
// ボタン.
mButton = (Button) rootView.findViewById(R.id.btnBridgeTouroku);
mButton.setOnClickListener(this);
mButton.setVisibility(View.GONE);
// 画像を表示.
mImageView = (ImageView) rootView.findViewById(R.id.iv01);
return rootView;
}
@Override
public void onResume() {
super.onResume();
// ステータスを初期状態(INIT)に設定.
mHueStatus = HueState.INIT;
// Hueのインスタンスを取得.
PHHueSDK hueSDK = PHHueSDK.getInstance();
// HueブリッジからのCallbackを受け取るためのリスナーを登録.
hueSDK.getNotificationManager().registerSDKListener(mListener);
// Hueブリッジへの認証開始
startAuthenticate();
}
@Override
public void onPause() {
PHHueSDK hueSDK = PHHueSDK.getInstance();
hueSDK.stopPushlinkAuthentication();
hueSDK.getNotificationManager().unregisterSDKListener(mListener);
stopAnimation();
super.onPause();
}
@Override
public void onClick(final View v) {
if (mHueStatus == HueState.AUTHENTICATE_SUCCESS) {
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.setCustomAnimations(R.anim.fragment_slide_right_enter, R.anim.fragment_slide_left_exit,
R.anim.fragment_slide_left_enter, R.anim.fragment_slide_right_exit);
transaction.replace(R.id.fragment_frame, HueFragment03.newInstance(mAccessPoint));
transaction.commit();
} else {
mButton.setVisibility(View.INVISIBLE);
startAuthenticate();
}
}
private void setPHAccessPoint(final PHAccessPoint accessPoint) {
mAccessPoint = accessPoint;
}
/**
* Hueブリッジのボタン押下アニメーションを開始します.
*/
private synchronized void startAnimation() {
if (mFuture != null) {
mFuture.cancel(false);
}
mFuture = mExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
switch (mHueStatus) {
case INIT:
nextImage();
break;
default:
case NO_CONNECT:
case AUTHENTICATE_FAILED:
case AUTHENTICATE_SUCCESS:
stopAnimation();
break;
}
}
}, 1, 1, TimeUnit.SECONDS);
}
/**
* Hueブリッジのボタン押下アニメーションを停止します.
*/
private synchronized void stopAnimation() {
if (mFuture != null) {
mFuture.cancel(false);
mFuture = null;
}
}
/**
* 指定されたRunnableをUIスレッド上で実行します.
* @param run 実行するRunnable
*/
private void runOnUiThread(final Runnable run) {
final Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(run);
}
}
/**
* 次の画像を表示します.
*/
private void nextImage() {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mCount == 0) {
mImageView.setImageResource(R.drawable.img01);
} else {
mImageView.setImageResource(R.drawable.img02);
}
mCount++;
mCount %= 2;
}
});
}
/**
* 認証成功を表示します.
*/
private void successAuthorization() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextViewStatus.setText(R.string.frag02_authsuccess);
mTextViewHowTo.setText(R.string.frag02_authsuccess_howto);
mImageView.setImageResource(R.drawable.img05);
mButton.setText(R.string.frag02_authsuccess_btn);
mButton.setVisibility(View.VISIBLE);
String message = getString(R.string.frag02_connected);
Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
}
});
}
/**
* 認証失敗を表示します.
*/
private void failAuthorization() {
runOnUiThread(new Runnable() {
@Override
public void run() {
stopAnimation();
mTextViewStatus.setText(R.string.frag02_failed);
mTextViewHowTo.setText("");
mImageView.setImageResource(R.drawable.img01);
mButton.setText(R.string.frag02_retry_btn);
mButton.setVisibility(View.VISIBLE);
}
});
}
/**
* Hueブリッジの認証を行います.
* <p>
* ユーザにHueブリッジのボタンを押下してもらう必要があります。
* </p>
*/
private void startAuthenticate() {
PHHueSDK hueSDK = PHHueSDK.getInstance();
if (!hueSDK.isAccessPointConnected(mAccessPoint)) {
hueSDK.connect(mAccessPoint);
authenticateHueBridge();
} else {
mHueStatus = HueState.AUTHENTICATE_SUCCESS;
successAuthorization();
}
}
/**
* Hueブリッジへの誘導を行う文言を表示します.
*/
private void authenticateHueBridge() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextViewStatus.setText(R.string.frag02_init);
mTextViewHowTo.setText(R.string.frag02_init_howto);
mButton.setText(R.string.frag02_retry_btn);
mButton.setVisibility(View.INVISIBLE);
startAnimation();
}
});
}
/**
* Hueブリッジからレスポンスがなかった場合のエラーダイアログを表示します.
*/
private void showNotConnection() {
runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(getActivity())
.setTitle(R.string.frag02_failed)
.setMessage(R.string.hue_dialog_no_connect)
.setPositiveButton(R.string.hue_dialog_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
moveFirstFragment();
}
})
.setCancelable(false)
.show();
}
});
}
/**
* 最初のフラグメントに移動します.
*/
private void moveFirstFragment() {
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.setCustomAnimations(R.anim.fragment_slide_right_enter, R.anim.fragment_slide_left_exit,
R.anim.fragment_slide_left_enter, R.anim.fragment_slide_right_exit);
transaction.replace(R.id.fragment_frame, new HueFragment01());
transaction.commit();
}
}