package org.orange.familylink; import org.apache.commons.lang3.ArrayUtils; import org.orange.familylink.ContactDetailActivity.Contact; import org.orange.familylink.R.drawable; import org.orange.familylink.R.string; import org.orange.familylink.alarm.AlarmService; import org.orange.familylink.data.Message; import org.orange.familylink.data.Message.Code; import org.orange.familylink.data.MessageLogRecord.Direction; import org.orange.familylink.data.Settings; import org.orange.familylink.data.Settings.Role; import org.orange.familylink.data.UrgentMessageBody; import org.orange.familylink.fragment.dialog.InitialSetupDialogFragment; import org.orange.familylink.fragment.dialog.LocateFrequencyDialogFragment; import org.orange.familylink.fragment.dialog.NoContactInformationDialogFragment; import org.orange.familylink.fragment.dialog.RoleDialogFragment; import org.orange.familylink.fragment.dialog.RoleDialogFragment.OnRoleChangeListener; import org.orange.familylink.location.LocationService; import org.orange.familylink.location.LocationTracker; import org.orange.familylink.sms.SmsMessage; import org.orange.familylink.sms.SmsReceiverService; import android.app.ActionBar; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.app.Service; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.TextView; import android.widget.Toast; /** * 主{@link Activity}。应用的默认{@link Activity} * @author Team Orange */ public class MainActivity extends BaseActivity { private static enum DialogType { DIALOG_NO_CONTACT_INFORMATION; } private GridView mMainMenuGridView; private Role mRole; private Function[] mFunctions; @Override protected void onCreate(Bundle savedInstanceState) { PreferenceManager.setDefaultValues(this, R.xml.preferences, false); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mMainMenuGridView = (GridView) findViewById(R.id.main_menu); //开启接收短信服务 Intent smsIntent = new Intent(this, SmsReceiverService.class); smsIntent.setAction(SmsReceiverService.ACTION_FOREGROUND); startService(smsIntent); setup(); } @Override protected void onStart() { super.onStart(); changeMainMenuIfNecessary(); } /** * 根据用户角色,设置主菜单内容。 * @param role 当前用户角色 */ protected void setMainMenuContent(Role role) { if(role == Role.CAREE) mFunctions = FUNCTIONS_CAREE; else if(role == Role.CARER) mFunctions = FUNCTIONS_CARER; else if(role == null) { // 还没有配置用户角色, 现在配置 mFunctions = FUNCTIONS_GENERAL; // 弹出对话框 InitialSetupDialogFragment dialog = new InitialSetupDialogFragment(); dialog.setOnClickListener(new InitialSetupDialogFragment.OnClickListener() { @Override public void onClickPositiveButton(InitialSetupDialogFragment dialog) { changeMainMenuIfNecessary(); } }); dialog.show(getFragmentManager(), null); } else throw new IllegalArgumentException("ilegal role: " + role); mRole = role; } /** * 初始化各项配置。典型情况下在{@link #onCreate(Bundle)}调用 */ protected void setup() { setMainMenuContent(Settings.getRole(this)); setupMainMenu(); setupActionBar(); } /** * 配置{@link ActionBar},典型情况下在{@link #onCreate(Bundle)}调用 */ protected void setupActionBar() { ActionBar actionBar = getActionBar(); // Specify that the Home/Up button should not be enabled, since there is no hierarchical parent. actionBar.setHomeButtonEnabled(false); } /** * 配置主菜单,典型情况下在{@link #onCreate(Bundle)}调用 */ protected void setupMainMenu() { mMainMenuGridView.setAdapter(new MainMenuAdapter(this)); mMainMenuGridView.setOnItemClickListener(new OnMenuItemClickListener()); } /** * 如果需要,改变主菜单内容。例如改变用户角色时 * @return 如果改变了,返回true;如果无需改变,返回false */ protected boolean changeMainMenuIfNecessary() { Role role = Settings.getRole(this); if(mRole == role) return false; else { onRoleChanged(role); return true; } } /** * 当 用户角色 改变时,调用此方法 * @param newRole 新的用户角色 */ private void onRoleChanged(Role newRole) { MainMenuAdapter adapter = (MainMenuAdapter) mMainMenuGridView.getAdapter(); // 如果角色不再是 受顾者,关闭受顾者才使用的服务 if(mRole == Role.CAREE) { View view = null; view = mMainMenuGridView.getChildAt( adapter.getItemPosition(Function.LOCATE_SERVICE)); if(view.isActivated()) setLocateService(view, false); view = mMainMenuGridView.getChildAt( adapter.getItemPosition(Function.FALL_DOWN_ALARM_SERVICE)); if(view.isActivated()) setFallDownAlarmService(view, false); } // 更新Pagers的顺序设置 setMainMenuContent(newRole); // 通知ViewPager数据集有变化 adapter.notifyDataSetChanged(); } private void showDialogFragment(DialogType dialogType) { switch(dialogType) { case DIALOG_NO_CONTACT_INFORMATION: new NoContactInformationDialogFragment().show(getFragmentManager(), dialogType.name()); break; default: throw new UnsupportedOperationException("unsupported dialog:" + dialogType); } } /** * 检查指定服务是否已打开 * @param serviceClass 待检测的服务的{@link Class} * @return 如果已打开,返回true */ private boolean isServiceRunning(Class<? extends Service> serviceClass) { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (serviceClass.getName().equals(service.service.getClassName())) { return true; } } return false; } /** * 开启或关闭 {@link LocationService} 服务 * @param locateSwitch 本服务的开关按钮 * @param isOn 如果要打开服务,设为true;如果要关闭服务,设为false */ private void setLocateService(View locateSwitch, boolean isOn) { locateSwitch.setActivated(isOn); PreferenceManager.getDefaultSharedPreferences(MainActivity.this).edit() .putBoolean(Settings.PREF_KEY_START_LOCATION_SERVICE, isOn).commit(); final Intent intent = new Intent(this, LocationService.class); if(isOn){ startService(intent); }else{ stopService(intent); } } /** * 开启或关闭 {@link AlarmService} 服务 * @param locateSwitch 本服务的开关按钮 * @param isOn 如果要打开服务,设为true;如果要关闭服务,设为false */ private void setFallDownAlarmService(View alarmSwitch, boolean isOn) { alarmSwitch.setActivated(isOn); final Intent intent = new Intent(this, AlarmService.class); if(isOn) { startService(intent); } else { stopService(intent); } } private void sendMessage(Function function) { // 构造消息 final Message message = new SmsMessage(); switch(function) { case SEEK_HELP: message.setCode(Code.INFORM | Code.Extra.Inform.URGENT); UrgentMessageBody body = new UrgentMessageBody(); body.setType(UrgentMessageBody.Type.SEEK_HELP); LocationTracker locationTracker = new LocationTracker(this); if(locationTracker.canGetLocation()) { body.setPosition(locationTracker.getLatitude(), locationTracker.getLongitude()); } locationTracker.stopUsingGPS(); message.setBody(body.toJson()); break; case LOCATE_NOW: message.setCode(Code.COMMAND | Code.Extra.Command.LOCATE_NOW); break; default: throw new IllegalArgumentException("unsupported function: " + function); } new Thread() { @Override public void run() { // 发送消息 Contact contact = ContactDetailActivity.getDefaultContact(MainActivity.this); if(contact.phone != null && !contact.phone.isEmpty()) message.sendAndSave(MainActivity.this, contact.id, contact.phone); else runOnUiThread(new Runnable() { @Override public void run() { showDialogFragment(DialogType.DIALOG_NO_CONTACT_INFORMATION); } }); } }.start(); } private class MainMenuAdapter extends BaseAdapter { private Context mContext; public MainMenuAdapter(Context context) { super(); mContext = context; } @Override public int getCount() { return mFunctions.length; } @Override public Object getItem(int position) { return mFunctions[position]; } public int getItemPosition(Function function) { for(int i = 0 ; i < mFunctions.length ; i++) if(mFunctions[i] == function) return i; return -1; } @Override public long getItemId(int position) { return mFunctions[position].ordinal(); } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView item = null; if (convertView == null) { // if it's not recycled, initialize some attributes item = new TextView(mContext); item.setGravity(Gravity.CENTER); item.setTextAppearance(mContext, android.R.style.TextAppearance_Large); } else { item = (TextView) convertView; } Function function = mFunctions[position]; item.setText(function.getTitleResourceId()); item.setCompoundDrawablesWithIntrinsicBounds(0, function.getIconResourceId(), 0, 0); if(function == Function.LOCATE_SERVICE) item.setActivated(isServiceRunning(LocationService.class)); else if(function == Function.FALL_DOWN_ALARM_SERVICE) item.setActivated(isServiceRunning(AlarmService.class)); return item; } } private class OnMenuItemClickListener implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Function function = Function.values()[(int)id]; switch (function) { //----------------------- 受顾方 ----------------------- case LOCATE_SERVICE: { boolean newIsStarted = !view.isActivated(); setLocateService(view, newIsStarted); if(newIsStarted) Toast.makeText(MainActivity.this, R.string.have_started_periodically_contact, Toast.LENGTH_LONG).show(); else Toast.makeText(MainActivity.this, R.string.have_stopt_periodically_contact, Toast.LENGTH_LONG).show(); break; } case LOCATE_FREQUENCY: mLocateFrequencyDialogFragment.show(getFragmentManager(), null); break; case FALL_DOWN_ALARM_SERVICE: setFallDownAlarmService(view, !view.isActivated()); break; case SEEK_HELP: sendMessage(Function.SEEK_HELP); break; //----------------------- 监护方 ----------------------- case LOCATE_NOW: sendMessage(Function.LOCATE_NOW); break; //----------------------- 通用 ----------------------- case GIVE_A_CALL: { Contact contact = ContactDetailActivity.getDefaultContact(MainActivity.this); if(contact.phone != null && !contact.phone.isEmpty()) { Intent intent = new Intent(Intent.ACTION_CALL, Uri .parse("tel:" + contact.phone)); startActivity(intent); } else { showDialogFragment(DialogType.DIALOG_NO_CONTACT_INFORMATION); } break; } case OUTBOX: { Intent intent = new Intent(MainActivity.this, MessagesActivity.class); intent.putExtra(MessagesActivity.EXTRA_DIRECTION, Direction.SEND); startActivity(intent); break; } case RESPONSE_MESSAGE: { Intent intent = new Intent(MainActivity.this, MessagesActivity.class); intent.putExtra(MessagesActivity.EXTRA_DIRECTION, Direction.RECEIVE); startActivity(intent); break; } case CONTACTS_SETTING: startActivity(new Intent(MainActivity.this, ContactDetailActivity.class)); break; case ROLE_SETTING: mRoleDialogFragment.show(getFragmentManager(), null); break; default: throw new IllegalStateException("unsupport function: " + function.name()); } } } /** * 本应用的功能。在主功能菜单中作为菜单项使用。 * @author Team Orange */ private static enum Function { //----------------------- 受顾方 ----------------------- /** 定位服务(开关) */ LOCATE_SERVICE(R.string.locate_service, R.drawable.ic_main_menu_locate_service), /** 定位频率 */ LOCATE_FREQUENCY(R.string.locate_frequency, R.drawable.ic_main_menu_locate_frequency), /** 摔倒检测服务(开关) */ FALL_DOWN_ALARM_SERVICE(R.string.fall_down_alarm_service, R.drawable.ic_main_menu_fall_down_alarm_service), /** 求助 */ SEEK_HELP(R.string.seek_help, R.drawable.ic_main_menu_seek_help), //----------------------- 监护方 ----------------------- /** 现在获取对方地点 */ LOCATE_NOW(R.string.locate_now, R.drawable.ic_main_menu_locate_now), //----------------------- 通用 ----------------------- /** 给对方打电话 */ GIVE_A_CALL(R.string.call, R.drawable.ic_main_menu_call), /** 发件箱(已发消息) */ OUTBOX(R.string.outbox, R.drawable.ic_main_menu_outbox), /** 回馈信息(相应消息) */ RESPONSE_MESSAGE(R.string.response_message, R.drawable.ic_main_menu_response_message), /** 联系人设置 */ CONTACTS_SETTING(R.string.contacts_setting, R.drawable.ic_main_menu_contacts_setting), /** 角色设置 */ ROLE_SETTING(R.string.role_setting, R.drawable.ic_main_menu_role_setting); private final int mIconResourceId; private final int mTitleResourceId; /** * @param titleResId 标题 {@link string}资源ID * @param iconResId 图标 {@link drawable}资源ID */ private Function(int titleResId, int iconResId) { mIconResourceId = iconResId; mTitleResourceId = titleResId; } public int getIconResourceId() { return mIconResourceId; } public int getTitleResourceId() { return mTitleResourceId; } } private static final Function[] FUNCTIONS_GENERAL = {Function.GIVE_A_CALL, Function.OUTBOX, Function.RESPONSE_MESSAGE, Function.CONTACTS_SETTING, Function.ROLE_SETTING}; /** 受顾者的功能及其顺序 */ private static final Function[] FUNCTIONS_CAREE = ArrayUtils.addAll( new Function[]{Function.FALL_DOWN_ALARM_SERVICE, Function.LOCATE_SERVICE, Function.LOCATE_FREQUENCY, Function.SEEK_HELP}, FUNCTIONS_GENERAL); /** 照料者的功能及其顺序 */ private static final Function[] FUNCTIONS_CARER = ArrayUtils.addAll( new Function[]{Function.LOCATE_NOW}, FUNCTIONS_GENERAL); private final LocateFrequencyDialogFragment mLocateFrequencyDialogFragment = new LocateFrequencyDialogFragment(); private final RoleDialogFragment mRoleDialogFragment = new RoleDialogFragment(); { mRoleDialogFragment.setOnRoleChangeListener(new OnRoleChangeListener() { @Override public void onRoleChange(RoleDialogFragment dialog) { changeMainMenuIfNecessary(); } }); } }