/* * Tencent is pleased to support the open source community by making * Tencent GT (Version 2.4 and subsequent versions) available. * * Notwithstanding anything to the contrary herein, any previous version * of Tencent GT shall not be subject to the license hereunder. * All right, title, and interest, including all intellectual property rights, * in and to the previous version of Tencent GT (including any and all copies thereof) * shall be owned and retained by Tencent and subject to the license under the * Tencent GT End User License Agreement (http://gt.qq.com/wp-content/EULA_EN.html). * * Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the MIT License (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * * http://opensource.org/licenses/MIT * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.tencent.wstt.gt.activity; import com.tencent.wstt.gt.GTApp; import com.tencent.wstt.gt.R; import com.tencent.wstt.gt.api.utils.Env; import com.tencent.wstt.gt.dao.GTPref; import com.tencent.wstt.gt.service.GTFloatView; import com.tencent.wstt.gt.service.GTLogo; import com.tencent.wstt.gt.utils.ToastUtil; import android.Manifest; import android.app.Notification; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.support.v4.app.ActivityCompat; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.content.ContextCompat; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.TextView; public class GTMainActivity extends GTBaseFragmentActivity implements OnClickListener { // Android6.x之后,需要由用户明确授权的权限,放在MainActivity里提前做申请交互 private static final int REQUEST_NEED_PERMISSION = 101; // 悬浮窗的权限是特殊权限,需要单独处理 private static final int REQUEST_FLOAT_VIEW = 102; private static boolean isFloatViewAllowed = GTPref.getGTPref().getBoolean(GTPref.FLOAT_ALLOWED, false); // 页面碎片对象 private GTAUTFragment autFragment; private GTParamTopFragment paramFragment; private GTPerfFragment perfFragment; private GTLogFragment logFragment; private GTPluginFragment pluginFragment; // 页面布局 private View autLayout; private View paramLayout; private View perfLayout; private View logLayout; private View pluginLayout; // 在Tab布局上显示的图标的控件 private ImageView autImage; private ImageView paramImage; private ImageView perfImage; private ImageView logImage; private ImageView pluginImage; private TextView autText; private TextView paramText; private TextView perfText; private TextView logText; private TextView pluginText; public static boolean isActived = false; public static Notification notification; public static boolean dlgIsShow = false; private int curTabId; private static GTMainActivity instance; public static GTMainActivity getInstance() { return instance; } public GTMainActivity() { instance = this; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gt_activity_main); // 初始化布局元素 initViews(); // 重新初始化各页 removeFragments(); // 第一次启动时选中第0个tab if (savedInstanceState != null) { setTabSelection(savedInstanceState.getInt("curTabId")); } else { setTabSelection(0); } isActived = true; boolean hasPermission = (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); hasPermission = hasPermission && (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED); hasPermission = hasPermission && (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED); hasPermission = hasPermission && (ContextCompat.checkSelfPermission(this, Manifest.permission.SYSTEM_ALERT_WINDOW) == PackageManager.PERMISSION_GRANTED); if (!hasPermission) { ActivityCompat.requestPermissions( this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE}, REQUEST_NEED_PERMISSION); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_NEED_PERMISSION: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 授权了就可以保存了,do nothing即可 // 接收了危险权限后,再弹出悬浮窗处理特殊权限,这样还可以避过ACTION_MANAGE_OVERLAY_PERMISSION不支持API23之前的问题 if (! isFloatViewAllowed) { requestAlertWindowPermission(); } // 在授权后,需要将之前没权限创建的目录重新创建一次 Env.init(); } else { ToastUtil.ShowLongToast(GTApp.getContext(), "Permission not enough. Please consider granting it this permission."); } } } } private void requestAlertWindowPermission() { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); intent.setData(Uri.parse("package:" + getPackageName())); try{ startActivityForResult(intent, REQUEST_FLOAT_VIEW); } catch(Exception e) { // 有的定制系统会抛异常,这样的系统也不需要额外的悬浮窗授权 } } @Override protected void onDestroy() { super.onDestroy(); isActived = false; } @Override protected void onSaveInstanceState(Bundle savedInstanceState) { savedInstanceState.putInt("curTabId", curTabId); super.onSaveInstanceState(savedInstanceState); } /* * 在Activity重新加载时,要先清除遗留的Fragment */ private void removeFragments() { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); Fragment fragment = fragmentManager.findFragmentByTag("a"); if (fragment != null) { transaction.remove(fragment); } fragment = fragmentManager.findFragmentByTag("b"); if (fragment != null) { transaction.remove(fragment); } fragment = fragmentManager.findFragmentByTag("c"); if (fragment != null) { transaction.remove(fragment); } fragment = fragmentManager.findFragmentByTag("d"); if (fragment != null) { transaction.remove(fragment); } fragment = fragmentManager.findFragmentByTag("e"); if (fragment != null) { transaction.remove(fragment); } transaction.commitAllowingStateLoss(); } /** * 在这里获取到每个需要用到的控件的实例,并给它们设置好必要的点击事件。 */ private void initViews() { autLayout = findViewById(R.id.aut_layout); paramLayout = findViewById(R.id.param_layout); perfLayout = findViewById(R.id.perf_layout); logLayout = findViewById(R.id.log_layout); pluginLayout = findViewById(R.id.plugin_layout); autImage = (ImageView) findViewById(R.id.aut_image); paramImage = (ImageView) findViewById(R.id.param_image); perfImage = (ImageView) findViewById(R.id.perf_image); logImage = (ImageView) findViewById(R.id.log_image); pluginImage = (ImageView) findViewById(R.id.plugin_image); autText = (TextView) findViewById(R.id.aut_text); paramText = (TextView) findViewById(R.id.param_text); perfText = (TextView) findViewById(R.id.perf_text); logText = (TextView) findViewById(R.id.log_text); pluginText = (TextView) findViewById(R.id.plugin_text); autLayout.setOnClickListener(this); paramLayout.setOnClickListener(this); perfLayout.setOnClickListener(this); logLayout.setOnClickListener(this); pluginLayout.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.aut_layout: curTabId = 0; setTabSelection(0); break; case R.id.param_layout: curTabId = 1; setTabSelection(1); break; case R.id.perf_layout: curTabId = 2; setTabSelection(2); break; case R.id.log_layout: curTabId = 3; setTabSelection(3); break; case R.id.plugin_layout: curTabId = 4; setTabSelection(4); break; default: break; } } /** * 根据传入的index参数来设置选中的tab页。 * * @param index * 每个tab页对应的下标。 */ private synchronized void setTabSelection(int index) { // 每次选中之前先清楚掉上次的选中状态 clearSelection(); // 开启一个Fragment事务 FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); // 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况 hideFragments(transaction); //TODO switch (index) { case 0: // 当点击了AUT tab时,改变控件的图片和文字颜色 autImage.setImageResource(R.drawable.tab_selected_border); autText.setTextColor(Color.WHITE); if (autFragment == null) { autFragment = new GTAUTFragment(); transaction.add(R.id.content, autFragment, "a"); } else { transaction.show(autFragment); } break; case 1: // 当点击了参数 tab时,改变控件的图片和文字颜色 paramImage.setImageResource(R.drawable.tab_selected_border); paramText.setTextColor(Color.WHITE); if (paramFragment == null) { paramFragment = new GTParamTopFragment(); transaction.add(R.id.content, paramFragment, "b"); } else { transaction.show(paramFragment); paramFragment.onShow(true); } break; case 2: // 当点击了耗时 tab时,改变控件的图片和文字颜色 perfImage.setImageResource(R.drawable.tab_selected_border); perfText.setTextColor(Color.WHITE); if (perfFragment == null) { perfFragment = new GTPerfFragment(); transaction.add(R.id.content, perfFragment, "c"); } else { transaction.show(perfFragment); } break; case 3: // 当点击了日志 tab时,改变控件的图片和文字颜色 logImage.setImageResource(R.drawable.tab_selected_border); logText.setTextColor(Color.WHITE); if (logFragment == null) { logFragment = new GTLogFragment(); transaction.add(R.id.content, logFragment, "d"); } else { transaction.show(logFragment); } break; case 4: default: // 当点击了插件 tab时,改变控件的图片和文字颜色 pluginImage.setImageResource(R.drawable.tab_selected_border); pluginText.setTextColor(Color.WHITE); if (pluginFragment == null) { pluginFragment = new GTPluginFragment(); transaction.add(R.id.content, pluginFragment, "e"); } else { transaction.show(pluginFragment); } break; } /* * 直接使用commit()可能会出错: * IllegalStateException: Can not perform this action after onSaveInstanceState:\ * * @see http://developer.android.com/reference/android/app/FragmentTransaction.html#commitAllowingStateLoss() * * 大致意思是说我使用的 commit方法是在Activity的onSaveInstanceState()之后调用的,这样会出错,因为onSaveInstanceState * 方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后再给它添加Fragment就会出错。解决办法就 * 是把commit()方法替换成 commitAllowingStateLoss()就行了,其效果是一样的。 */ // transaction.commit(); transaction.commitAllowingStateLoss(); } /** * 清除掉所有的选中状态。 */ private void clearSelection() { int defaultColor = getResources().getColor(R.color.tab_default_textcolor); autImage.setImageResource(R.drawable.tab_default_border); autText.setTextColor(defaultColor); paramImage.setImageResource(R.drawable.tab_default_border); paramText.setTextColor(defaultColor); perfImage.setImageResource(R.drawable.tab_default_border); perfText.setTextColor(defaultColor); logImage.setImageResource(R.drawable.tab_default_border); logText.setTextColor(defaultColor); pluginImage.setImageResource(R.drawable.tab_default_border); pluginText.setTextColor(defaultColor); } /** * 将所有的Fragment都置为隐藏状态。 * * @param transaction * 用于对Fragment执行操作的事务 */ private void hideFragments(FragmentTransaction transaction) { if (autFragment != null) { transaction.hide(autFragment); } if (paramFragment != null) { paramFragment.onShow(false); transaction.hide(paramFragment); } if (perfFragment != null) { transaction.hide(perfFragment); } if (logFragment != null) { transaction.hide(logFragment); } if (pluginFragment != null) { transaction.hide(pluginFragment); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK){ dlgIsShow = false; moveTaskToBack(true); return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int item_id = item.getItemId(); Intent intent = null; switch (item_id) { case R.id.exit: GTApp.exitGT(); break; case R.id.log_switch: intent = new Intent(this, GTLogSwitchActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); break; case R.id.air_console: intent = new Intent(this, GTACSettingActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); break; case R.id.intervals: intent = new Intent(this, GTIntervalSettingActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); break; case R.id.about: intent = new Intent(this, GTAboutActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); break; } return false; } /* 进行验证码验证,或者进行快速登录的回调,这两个是进行快速登录可能遇到的情况 */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_FLOAT_VIEW: // 得到权限,置标志位,相应的提示用户重启GT等 isFloatViewAllowed = true; GTPref.getGTPref().edit().putBoolean(GTPref.FLOAT_ALLOWED, true).commit(); // 因为授权之前的启动悬浮窗会报异常关闭,所以这里重新启动悬浮窗服务 if ( GTPref.getGTPref().getBoolean(GTPref.AC_SWITCH_FLAG, true)) { Intent intent = new Intent(this, GTLogo.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startService(intent); Intent mintent = new Intent(this, GTFloatView.class); mintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startService(mintent); } break; default: break; } } }