1. 简介
Android启动无黑屏是通过设置Window透明来实现的。主要是通过定义启动Activity的android:theme来实现的,但android:theme的定义是有要求的。
本方法可以实现以下两项要求:
1)启动无黑屏
2)启动画面全屏显示
2. 实现方案
res下目录结构:
2.1 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.xxx.gaoxueya"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="9"/>
<uses-feature android:glEsVersion="0x00020000" />
<application android:label="@string/app_name"
android:icon="@drawable/icon">
<!-- Tell Cocos2dxActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="cocos2dcpp" />
<activity android:name="org.cocos2dx.cpp.AppActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="cn.toltech.gaoxueya.SplashScreen"
android:theme="@style/Theme.Transparent">
<intent-filter>
<action android:name="android.intent.action.MAIN"></action>
<category android:name="android.intent.category.LAUNCHER"></category>
</intent-filter>
</activity>
</application>
<supports-screens android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
2.2 styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Animations" parent="@android:Animation" />
<style name="Animations.SplashScreen">
<item name="android:windowEnterAnimation">@anim/appear</item>
<item name="android:windowExitAnimation">@anim/disappear</item>
</style>
<style name="Theme.Transparent" parent="android:style/Theme.NoTitleBar.Fullscreen">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@style/Animations.SplashScreen</item>
</style>
</resources>
若在Theme.Transparent中增加了<item name="android:windowIsFloating">true</item>,则此Activity无法全屏显示。
2.3 appear.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/accelerate_interpolator"
android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="800"
/>
</set>
可根据效果需要设置fromAlpha和toAlpha的值。
2.4 disappear.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/decelerate_interpolator"
android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="800"
/>
</set>
可根据效果需要设置fromAlpha和toAlpha的值。
2.5 splash.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FF0000"
android:orientation="vertical"
>
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/lnxins"
>
</ImageView>
</LinearLayout>
2.6 SplashScreen.java
package cn.toltech.gaoxueya;;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.MotionEvent;
import android.widget.ImageView;
public class SplashScreen extends Activity {
/**
* The thread to process splash screen events
*/
private Thread mSplashThread;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Splash screen view
setContentView(R.layout.splash);
final SplashScreen sPlashScreen = this;
// The thread to wait for splash screen events
mSplashThread = new Thread(){
@Override
public void run(){
try {
synchronized(this){
// Wait given period of time or exit on touch
wait(5000);
}
}
catch(InterruptedException ex){
}
finish();
// Run next activity
Intent intent = new Intent();
intent.setClass(sPlashScreen, org.cocos2dx.cpp.AppActivity.class);
startActivity(intent);
//stop();
}
};
mSplashThread.start();
}
/**
* Processes splash screen touch events
*/
@Override
public boolean onTouchEvent(MotionEvent evt)
{
if(evt.getAction() == MotionEvent.ACTION_DOWN)
{
synchronized(mSplashThread){
mSplashThread.notifyAll();
}
}
return true;
}
}
2.7 AppActivity.java
package org.cocos2dx.cpp;
import org.cocos2dx.lib.Cocos2dxActivity;
// added by xxx on 2014.10.28
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.media.MediaPlayer;
import android.util.Log;
import java.io.IOException;
import android.os.Message;
import android.os.Handler;
public class AppActivity extends Cocos2dxActivity {
private static final String TAG="XXX";
private final static int HANDLER_MEDIA_PLAY = 1;
private final static int HANDLER_MEDIA_STOP = 2;
private final static int HANDLER_MEDIA_PAUSE = 3;
private final static int HANDLER_MEDIA_RESUME = 4;
private final static int HANDLER_MEDIA_SEEK = 5;
private static Handler sHandler;
private boolean mPlayerPaused = false;
private SurfaceHolder mediaSurfaceHolder = null;
private MediaPlayer mMediaPlayer = null;
private GetPosThread mPosThread = null;
//private boolean isMediaPlay = false;
private String mCurrentPath = null;
private int mCurrentCount = 0;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
initMedia();
}
/*
public Cocos2dxGLSurfaceView onCreateView() {
Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
// Demo2 should create stencil buffer
glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
return glSurfaceView;
}
private void initVideo(){
mediaSurfaceHolder = mMediaPlayView.getHolder();
mediaSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mediaSurfaceHolder.addCallback(new MediaSurfaceHolderCallBack());
}*/
private void initMedia(){
mediaSurfaceHolder = mMediaPlayView.getHolder();
mediaSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mediaSurfaceHolder.addCallback(new MediaSurfaceHolderCallBack());
this.sHandler = new Handler() {
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case HANDLER_MEDIA_PLAY:
// set MediaPlayer status
mPlayerPaused = false;
final String path = (String) msg.obj;
final int playNum = msg.arg1;
Log.d(TAG,"HANDLER_VIDEO_PLAY:" + "path=" + path + ", playNum=" + playNum);
// stop the thread that get cur position
if(mPosThread != null){
mPosThread.stopThread(true);
mPosThread = null;
}
//if(mServer != null) mServer.stopHandler();
if (mMediaPlayer != null) {
mMediaPlayer.stop();
// should set the state, if not, the following sequence will be error
// play -> pause -> stop -> resume
mPlayerPaused = false;
}
if (mCurrentPath == null) {
// it is the first time to play media
mMediaPlayer = createMediaPlayer(path);
// record the path and play number
if(mMediaPlayer != null){
mCurrentPath = path;
mCurrentCount = playNum;
}
} else {
// play new media or replay
// release old resource and create a new one
if (mMediaPlayer != null) {
mMediaPlayer.release();
}
mMediaPlayer = createMediaPlayer(path);
// record the path and play number
if(mMediaPlayer != null){
mCurrentPath = path;
mCurrentCount = playNum;
}
}
if (mMediaPlayer == null) {
Log.e(TAG, "ERROR: media player is null");
}
break;
case HANDLER_MEDIA_SEEK:
Log.d(TAG,"receive HANDLER_VIDEO_SEEK");
if((null != mMediaPlayer)&&(mMediaPlayer.isPlaying() || mPlayerPaused)){
mMediaPlayer.seekTo(msg.arg1);
Log.d(TAG,"seekTo:" + msg.arg1 + "ms");
}
break;
case HANDLER_MEDIA_STOP:
Log.d(TAG,"receive HANDLER_VIDEO_STOP");
// stop the thread that get cur position
if(mPosThread != null){
mPosThread.stopThread(true);
mPosThread = null;
}
//if(mServer != null) mServer.stopHandler();
if (mMediaPlayer != null) {
mMediaPlayer.stop();
// should set the state, if not, the following sequence will be error
// play -> pause -> stop -> resume
mPlayerPaused = false;
}
break;
case HANDLER_MEDIA_PAUSE:
Log.d(TAG,"receive HANDLER_VIDEO_PAUSE");
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mPlayerPaused = true;
}
break;
case HANDLER_MEDIA_RESUME:
Log.d(TAG,"receive HANDLER_VIDEO_RESUME");
if (mMediaPlayer != null && mPlayerPaused) {
mMediaPlayer.start();
mPlayerPaused = false;
}
break;
}
}
};
}
public class GetPosThread extends Thread {
private boolean _run = true;
public void stopThread( boolean run) {
this ._run = !run;
}
@Override
public void run() {
while(_run) {
try {
if((mMediaPlayer != null) && (mMediaPlayer.isPlaying())){
int pos = mMediaPlayer.getCurrentPosition();
nativeUpdateCurPos(pos);
}
else
{
if(mMediaPlayer == null) Log.d(TAG, "mMediaPlayer is null");
//if(mMediaPlayer.isPlaying()!= true) Log.d(TAG,"mMediaPlayer is not playing");
}
Thread.sleep(1000); // sleep 1s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG,"onPrepared...");
mediaSurfaceHolder.setFixedSize(mp.getVideoWidth(), mp.getVideoHeight());
// start play video
mp.start();
try{
// startup Get Pos Thread
mPosThread = new GetPosThread();
mPosThread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
};
private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
Log.d(TAG,"onCompletion...");
if(mCurrentCount == -1){
mp.seekTo(0);
mp.start();
}else{
// stop the thread that get cur position
if(mPosThread != null) mPosThread.stopThread(true);
// notify stop video play
nativePlayEnd();
}
}
};
private class MediaSurfaceHolderCallBack implements SurfaceHolder.Callback{
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d(TAG,"surfaceChanged...,width="+width+", height="+height);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG,"surfaceCreated...");
play("/mnt/sdcard/video/cg720p.mp4");
/*
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
try {
mMediaPlayer.setDataSource("/sdcard/video/cg.mp4");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mMediaPlayer.setDisplay(mediaSurfaceHolder);
try {
mMediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
} */
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if( mMediaPlayer != null && mMediaPlayer.isPlaying() ){
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
if( mediaSurfaceHolder != null ){
mediaSurfaceHolder = null;
}
}
}
private MediaPlayer createMediaPlayer(final String path) {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(mPreparedListener);
mediaPlayer.setOnCompletionListener(mCompletionListener);
mediaPlayer.setDisplay(mediaSurfaceHolder);
try {
mediaPlayer.setDataSource(path);
mediaPlayer.prepareAsync();
} catch (final Exception e) {
mediaPlayer = null;
Log.e(TAG, "error: " + e.getMessage(), e);
}
return mediaPlayer;
}
// Video Player Interface with C++
public static boolean play(final String path) {
Log.d(TAG,"receive native play: path=" +path);
final Message msg = new Message();
msg.what = HANDLER_MEDIA_PLAY;
msg.obj = path;
msg.arg1 = 1;
sHandler.sendMessage(msg);
return true;
}
public static boolean seekTo(int msec){
Log.d(TAG,"receive native seekTo: msec=" +msec);
final Message msg = new Message();
msg.what = HANDLER_MEDIA_SEEK;
msg.arg1 = msec;
sHandler.sendMessage(msg);
return true;
}
public static boolean stop(){
Log.d(TAG,"receive native stop");
final Message msg = new Message();
msg.what = HANDLER_MEDIA_STOP;
sHandler.sendMessage(msg);
return true;
}
public static boolean pause(){
Log.d(TAG,"receive native pause");
final Message msg = new Message();
msg.what = HANDLER_MEDIA_PAUSE;
sHandler.sendMessage(msg);
return true;
}
public static boolean resume(){
Log.d(TAG,"receive native resume");
final Message msg = new Message();
msg.what = HANDLER_MEDIA_RESUME;
sHandler.sendMessage(msg);
return true;
}
// Native method
private static native void nativeUpdateCurPos(int curPos);
private static native void nativePlayEnd();
}
更简单的方式:http://www.cnblogs.com/liqw/p/4263418.html