package org.deviceconnect.android.localoauth.fragment;
import java.util.ArrayList;
import java.util.List;
import org.deviceconnect.android.R;
import org.deviceconnect.android.localoauth.LocalOAuth2Main;
import org.deviceconnect.android.localoauth.ScopeUtil;
import org.deviceconnect.android.localoauth.oauthserver.db.SQLiteClient;
import org.deviceconnect.android.localoauth.oauthserver.db.SQLiteToken;
import org.restlet.ext.oauth.PackageInfoOAuth;
import org.restlet.ext.oauth.internal.Scope;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
/**
* アクセストークン一覧を表示するFragment.
* @author NTT DOCOMO, INC.
*/
public class AccessTokenListFragment extends Fragment {
/** リストビュー用アダプタ. */
private AccessTokenListAdapter mListAdapter;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
mListAdapter = new AccessTokenListAdapter(getActivity(), 0, loadTokens());
View view = inflater.inflate(R.layout.access_token_list_fragment, container, false);
ListView listView = (ListView) view.findViewById(R.id.listView);
listView.setAdapter(mListAdapter);
View commentView = view.findViewById(R.id.noTokenView);
if (mListAdapter.getCount() == 0) {
commentView.setVisibility(View.VISIBLE);
} else {
commentView.setVisibility(View.GONE);
}
return view;
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
menu.clear();
// ActionBarの全削除ボタンを追加
final MenuItem menuItem = menu.add(R.string.delete_all);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(final MenuItem item) {
if (item.getTitle().equals(menuItem.getTitle())) {
deleteAllTokenProc();
}
return true;
}
});
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
if (android.R.id.home == item.getItemId()) {
getActivity().finish();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* アクセストークンを全て削除する処理.
*/
private void deleteAllTokenProc() {
String strTitle = getString(R.string.access_token_delete_all_title);
String strGuidance = getString(R.string.access_token_delete_guidance);
String strPositive = getString(R.string.access_token_delete_positive);
String strNegative = getString(R.string.access_token_delete_negative);
/* 削除確認ダイアログ */
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(strTitle)
.setMessage(strGuidance)
.setPositiveButton(strPositive, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
mListAdapter.deleteAll();
}
})
.setNegativeButton(strNegative, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
}
})
.setCancelable(true);
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
/**
* アクセストークン読み込み.
* @return アクセストークンのリスト
*/
private List<SQLiteToken> loadTokens() {
ArrayList<SQLiteToken> tokenList = new ArrayList<SQLiteToken>();
SQLiteToken[] tokens = LocalOAuth2Main.getAccessTokens();
if (tokens != null) {
for (SQLiteToken token : tokens) {
tokenList.add(token);
}
}
return tokenList;
}
/**
* トークンデータがありませんのViewの表示・非表示を設定する.
*/
private void setVisibleCommentView() {
View commentView = getView().findViewById(R.id.noTokenView);
if (mListAdapter.getCount() == 0) {
commentView.setVisibility(View.VISIBLE);
} else {
commentView.setVisibility(View.GONE);
}
}
/**
* アクセストークンListView用Adapter.
*/
private class AccessTokenListAdapter extends ArrayAdapter<SQLiteToken> {
/** LayoutInflator. */
private LayoutInflater mInflater;
/** トークン配列. */
private List<SQLiteToken> mTokenList;
/**
* コンストラクタ.
* @param context コンストラクタ
* @param textViewResourceId textViewResourceId
* @param tokens トークン配列
*/
public AccessTokenListAdapter(final Context context, final int textViewResourceId,
final List<SQLiteToken> tokens) {
super(context, textViewResourceId, tokens);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mTokenList = tokens;
}
@Override
public int getCount() {
return mTokenList.size();
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final SQLiteToken token = (SQLiteToken) getItem(position);
View view = convertView;
if (view == null) {
view = mInflater.inflate(R.layout.access_token_list_item, (ViewGroup) null);
}
// アプリケーション名
TextView textView = (TextView) view.findViewById(R.id.textView);
textView.setText(getApplicationName(token));
// スコープ名一覧を表示
TextView textViewAccessToken = (TextView) view.findViewById(R.id.textViewAccessToken);
textViewAccessToken.setText(getScopeList(token));
// アプリのアイコン表示
ImageView imageViewIcon = (ImageView) view.findViewById(R.id.imageViewIcon);
imageViewIcon.setImageDrawable(getApplicationIcon(token));
// 行背景をクリックしたときの処理
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
openAccessTokenDescription(token);
}
});
// 削除ボタン
Button buttonDelete = (Button) view.findViewById(R.id.buttonDelete);
buttonDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
openDeleteTokenDialog(token);
}
});
return view;
}
/**
* アクセストークンをすべて削除されたことを画面に反映する.
*/
private void deleteAll() {
LocalOAuth2Main.destroyAllAccessToken();
mTokenList.clear();
notifyDataSetChanged();
setVisibleCommentView();
}
/**
* アクセストークンを削除する.
* @param token トークンデータ
*/
private void deleteToken(final SQLiteToken token) {
long tokenId = token.getId();
LocalOAuth2Main.destroyAccessToken(tokenId);
mTokenList.remove(token);
notifyDataSetChanged();
setVisibleCommentView();
}
}
/**
* トークンデータからアプリケーション名を取得する.
* @param token トークンデータ
* @return アプリケーション名
*/
private String getApplicationName(final SQLiteToken token) {
if (token != null) {
String applicationName = token.getApplicationName();
if (applicationName == null) {
applicationName = getString(R.string.no_application_name);
}
return applicationName;
} else {
return getString(R.string.no_token);
}
}
/**
* トークンデータからアプリケーションアイコンを取得する.
* <p>
* アイコンが存在しない場合には、デフォルトの画像を返却する。
* </p>
* @param token トークンデータ
* @return アイコン画像
*/
private Drawable getApplicationIcon(final SQLiteToken token) {
Drawable icon = null;
if (token != null) {
String clientId = token.getClientId();
SQLiteClient client = LocalOAuth2Main.findClientByClientId(clientId);
if (client != null) {
PackageInfoOAuth p = client.getPackageInfo();
icon = getPackageIcon(getActivity(), p.getPackageName());
}
}
if (icon == null) {
icon = getResources().getDrawable(R.drawable.ic_action_labels);
}
return icon;
}
/**
* パッケージアイコンを返す.
* @param context コンテキスト
* @param packageName パッケージ名
* @return not null: パッケージアイコン / null: パッケージが見つからない
*/
private Drawable getPackageIcon(final Context context, final String packageName) {
PackageManager pm = getActivity().getPackageManager();
try {
return pm.getApplicationIcon(packageName);
} catch (NameNotFoundException e) {
return null;
}
}
/**
* トークンデータからスコープ一覧の文字列を取得する.
* @param token トークンデータ
* @return スコープ一覧の文字列
*/
private String getScopeList(final SQLiteToken token) {
if (token != null) {
Scope[] scopes = token.getScope();
if (scopes != null && scopes.length > 0) {
String firstScopeName = ScopeUtil.getDisplayScope(getActivity(),
scopes[0].getScope(), null, null);
if (scopes.length == 1) {
return firstScopeName;
} else {
String format = getString(R.string.access_token_list_item_format);
return String.format(format, firstScopeName, scopes.length - 1);
}
}
}
return "";
}
/**
* トークンデータの詳細を表示する.
* @param token トークンデータ
*/
private void openAccessTokenDescription(final SQLiteToken token) {
AccessTokenDescriptionFramgent f = new AccessTokenDescriptionFramgent();
Bundle bundle = new Bundle();
bundle.putString(AccessTokenDescriptionFramgent.EXTRA_CLIENT_ID,
token.getClientId());
f.setArguments(bundle);
FragmentManager fm = getActivity().getFragmentManager();
FragmentTransaction t = fm.beginTransaction();
t.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
t.add(android.R.id.content, f, "description");
t.addToBackStack("tokenList");
t.commitAllowingStateLoss();
}
/**
* トークンデータの削除確認ダイアログを表示する.
* @param token 削除するトークンデータ
*/
private void openDeleteTokenDialog(final SQLiteToken token) {
String applicationName = token.getApplicationName();
String strTitle = applicationName;
String strGuidance = getString(R.string.access_token_delete_guidance);
String strPositive = getString(R.string.access_token_delete_positive);
String strNegative = getString(R.string.access_token_delete_negative);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle(strTitle).setMessage(strGuidance)
.setPositiveButton(strPositive, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
mListAdapter.deleteToken(token);
}
}).setNegativeButton(strNegative, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
}
}).setCancelable(true);
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}