在分析启动界面SplashActivity前,先来看看清单文件中对这个界面的设置:
<!-- 开屏页 -->
<activity
android:name=".activity.SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/horizontal_slide" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
其中有一点需要注意:android:theme="@style/horizontal_slide",咱们点进去看看。
11以前是这个
<style name="horizontal_slide" parent="android:Theme.NoTitleBar">
<item name="android:windowAnimationStyle">@style/AnimFade2</item>
</style>
11以后
<style name="horizontal_slide" parent="android:style/Theme.Holo.Light.NoActionBar">
<item name="android:windowAnimationStyle">@style/AnimFade2</item>
</style>
只要是说明没有标题栏。
AnimFade2:
<style name="AnimFade2" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/slide_in_from_right</item>
<item name="android:activityOpenExitAnimation">@anim/slide_out_to_left</item>
<item name="android:activityCloseExitAnimation">@anim/slide_out_to_right</item>
<item name="android:activityCloseEnterAnimation">@anim/slide_in_from_left</item>
</style>
可以清晰发现所设置的动画,都是Activity的切换动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromXDelta="100%p"
android:toXDelta="0" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromXDelta="0"
android:toXDelta="-100%p" />
</set>
配置了解完了,咱们接下来看界面。
xml文件就不详细说明了,因为这个界面继承自BaseActivity所以先来看看BaseActivity里面有什么东西。
public class BaseActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
}
@Override
protected void onResume() {
super.onResume();
// onresume时,取消notification显示
HXSDKHelper.getInstance().getNotifier().reset();
// umeng
MobclickAgent.onResume(this);
}
@Override
protected void onStart() {
super.onStart();
// umeng
MobclickAgent.onPause(this);
}
/**
* 返回
*
* @param view
*/
public void back(View view) {
finish();
}
}
很简单,因为是聊天软件,所以设置当界面可见时取消notification显示,以及umeng的一些设置,最后写了一个返回的公共方法。
接下来看主要代码:
public class SplashActivity extends BaseActivity {
private LinearLayout rootLayout;
private TextView versionText;
// 停留时间
private static final int sleepTime = 2000;
@Override
protected void onCreate(Bundle arg0) {
setContentView(R.layout.activity_splash);
super.onCreate(arg0);
rootLayout = (LinearLayout) findViewById(R.id.splash_root);
// 显示版本信息的文字
versionText = (TextView) findViewById(R.id.tv_version);
versionText.setText(getVersion());
// 设置渐变动画
AlphaAnimation animation = new AlphaAnimation(0.3f, 1.0f);
animation.setDuration(1500);
rootLayout.startAnimation(animation);
}
@Override
protected void onStart() {
super.onStart();
// 判断是否有登录 已经登录直接进入主界面 否则进入登录界面
new Thread(new Runnable() {
public void run() {
if (DemoHXSDKHelper.getInstance().isLogined()) {
// ** 免登陆情况 加载所有本地群和会话
// 不是必须的,不加sdk也会自动异步去加载(不会重复加载);
// 加上的话保证进了主页面会话和群组都已经load完毕
long start = System.currentTimeMillis();
EMGroupManager.getInstance().loadAllGroups();
EMChatManager.getInstance().loadAllConversations();
long costTime = System.currentTimeMillis() - start;
// 等待sleeptime时长
if (sleepTime - costTime > 0) {
try {
Thread.sleep(sleepTime - costTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 进入主页面
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
} else {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
// 进入登录界面
startActivity(new Intent(SplashActivity.this, LoginActivity.class));
finish();
}
}
}).start();
}
/**
* 获取当前应用程序的版本号
*/
private String getVersion() {
String st = getResources().getString(R.string.Version_number_is_wrong);
PackageManager pm = getPackageManager();
try {
PackageInfo packinfo = pm.getPackageInfo(getPackageName(), 0);
String version = packinfo.versionName;
return version;
} catch (NameNotFoundException e) {
e.printStackTrace();
return st;
}
}
}
其中设置了一个1500毫秒的渐变动画,并且根据应用版本修改界面上的TextView。
在onStart方法里面开启一条线程用来检测账号是否已经登录,如果已经登录的话直接进入主界面,否则的话进入等登录界面。并且确保停留时间不能比设定的时间(sleepTime = 2000)小。
在这里使用了一个类:DemoHXSDKHelper,进去看下到底是怎么来检测账号是否登录的。
继承自抽象类HXSDKHelper,可以看到这个类:
/**
* The developer can derive from this class to talk with HuanXin SDK
* All the Huan Xin related initialization and global listener are implemented in this class which will
* help developer to speed up the SDK integration。
* this is a global instance class which can be obtained in any codes through getInstance()
*
* 开发人员可以选择继承这个环信SDK帮助类去加快初始化集成速度。此类会初始化环信SDK,并设置初始化参数和初始化相应的监听器
* 不过继承类需要根据要求求提供相应的函数,尤其是提供一个{@link HXSDKModel}. 所以请实现abstract protected HXSDKModel createModel();
* 全局仅有一个此类的实例存在,所以可以在任意地方通过getInstance()函数获取此全局实例
*
* @author easemob
*
*/
既然是初始化,那肯定是在一个全局的APP类里面了,到清单文件里面看一下是DemoApplication类,
public static DemoHXSDKHelper hxSDKHelper = new DemoHXSDKHelper();
@Override
public void onCreate() {
super.onCreate();
// 获取一个全局的Context
applicationContext = this;
// 获取一个全局的APP实例
instance = this;
/**
* this function will initialize the HuanXin SDK
*
* @return boolean true if caller can continue to call HuanXin related
* APIs after calling onInit, otherwise false.
*
* 环信初始化SDK帮助函数
* 返回true如果正确初始化,否则false,如果返回为false,请在后续的调用中不要调用任何和环信相关的代码
*
* for example: 例子:
*
* public class DemoHXSDKHelper extends HXSDKHelper
*
* HXHelper = new DemoHXSDKHelper();
* if(HXHelper.onInit(context)){ // do HuanXin related work }
*/
hxSDKHelper.onInit(applicationContext);
}
接下来看下初始化里面的内容:onInit
/**
* application context
*/
protected Context appContext = null;
/**
* init flag: test if the sdk has been inited before, we don't need to init again
*/
private boolean sdkInited = false;
/**
* this function will initialize the HuanXin SDK
*
* @return boolean true if caller can continue to call HuanXin related APIs after calling onInit, otherwise false.
*
* 环信初始化SDK帮助函数
* 返回true如果正确初始化,否则false,如果返回为false,请在后续的调用中不要调用任何和环信相关的代码
*
* for example:
* 例子:
*
* public class DemoHXSDKHelper extends HXSDKHelper
*
* HXHelper = new DemoHXSDKHelper();
* if(HXHelper.onInit(context)){
* // do HuanXin related work
* }
*/
public synchronized boolean onInit(Context context){
if(sdkInited){
return true;
}
appContext = context;
// create HX SDK model
hxModel = createModel();
// create a default HX SDK model in case subclass did not provide the model
if(hxModel == null){
hxModel = new DefaultHXSDKModel(appContext);
}
int pid = android.os.Process.myPid();
String processAppName = getAppName(pid);
Log.d(TAG, "process app name : " + processAppName);
// 如果app启用了远程的service,此application:onCreate会被调用2次
// 为了防止环信SDK被初始化2次,加此判断会保证SDK被初始化1次
// 默认的app会在以包名为默认的process name下运行,如果查到的process name不是app的process name就立即返回
if (processAppName == null || !processAppName.equalsIgnoreCase(hxModel.getAppProcessName())) {
Log.e(TAG, "enter the service process!");
// 则此application::onCreate 是被service 调用的,直接返回
return false;
}
// 初始化环信SDK,一定要先调用init()
EMChat.getInstance().init(context);
// 设置sandbox测试环境
// 建议开发者开发时设置此模式
if(hxModel.isSandboxMode()){
EMChat.getInstance().setEnv(EMEnvMode.EMSandboxMode);
}
if(hxModel.isDebugMode()){
// set debug mode in development process
EMChat.getInstance().setDebugMode(true);
}
Log.d(TAG, "initialize EMChat SDK");
initHXOptions();
initListener();
sdkInited = true;
return true;
}
初始化之后可以通过SDK来判断是否已经在服务端登录:
/**
* 检查是否已经登录过
* @return
*/
public boolean isLogined(){
return EMChat.getInstance().isLoggedIn();
}
这里只显示部分代码,由于初始化的内容比较多,且都是SDK方面的东西,此处不再详讲。
到此启动界面就已经讲完了,接下来会按照没有登录的逻辑进入登录界面。