MipcaActivityCapture代码阅读------surfaceview的生命周期

前言

源代码来自http://blog.csdn.net/xiaanming/article/details/10163203,由于不懂surfaceDestroyed的调用时机,网上一般都说在surfaceview隐藏的时候调用,但是按back键、按home键、锁屏、跳转到另一个非完全覆盖的activity是否会调用surfaceDestroyed,不是很清楚。 所以用打印日志的方式分析了下各个函数的执行调用过程。
很多surfaceview的demo中都用到了hasSurface,但是hasSurface又有什么作用呢?曾经深表怀疑,仔细分析过代码才明白

四种方式的日志

back

进入MipcaActivityCapture这个activity

01-09 16:59:51.118:E/MipcaActivityCapture(25152): onCreate

01-09 16:59:51.141:E/MipcaActivityCapture(25152): onResume

01-09 16:59:51.141:E/MipcaActivityCapture(25152): hasSurface=false

01-09 16:59:51.259:E/MipcaActivityCapture(25152): surfaceCreated

01-09 16:59:51.259:E/MipcaActivityCapture(25152): initCamera

 

点back

01-09 16:59:54.102:E/MipcaActivityCapture(25152): onPause

01-09 16:59:54.227:E/MipcaActivityCapture(25152): surfaceDestroyed

01-09 16:59:54.391:E/MipcaActivityCapture(25152): onStop

01-09 16:59:54.399:E/MipcaActivityCapture(25152): onDestroy

 home

进入MipcaActivityCapture这个activity

01-09 16:59:51.118:E/MipcaActivityCapture(25152): onCreate

01-09 16:59:51.141:E/MipcaActivityCapture(25152): onResume

01-09 16:59:51.141:E/MipcaActivityCapture(25152): hasSurface=false

01-09 16:59:51.259:E/MipcaActivityCapture(25152): surfaceCreated

01-09 16:59:51.259:E/MipcaActivityCapture(25152): initCamera

 

 

点home

01-09 17:28:47.196:E/MipcaActivityCapture(26547): onPause

01-09 17:28:47.321:E/MipcaActivityCapture(26547): surfaceDestroyed

01-09 17:28:47.704:E/MipcaActivityCapture(26547): onStop

锁屏

进入MipcaActivityCapture这个activity

01-09 17:31:03.259:E/MipcaActivityCapture(26655): onCreate

01-09 17:31:03.282:E/MipcaActivityCapture(26655): hasSurface=false

01-09 17:31:03.282:E/MipcaActivityCapture(26655): onResume

01-09 17:31:03.438:E/MipcaActivityCapture(26655): surfaceCreated

01-09 17:31:03.438:E/MipcaActivityCapture(26655): initCamera

 

锁屏(按关机键)

01-09 17:31:09.907:E/MipcaActivityCapture(26655): onPause

01-09 17:31:09.938:E/MipcaActivityCapture(26655): onStop

 

解锁(按关机键)

01-09 17:35:51.509:E/MipcaActivityCapture(27383): onResume

01-09 17:35:51.509:E/MipcaActivityCapture(27383): hasSurface=true

01-09 17:35:51.509:E/MipcaActivityCapture(27383): initCamera

 跳转到一个非完全覆盖的activity

进入MipcaActivityCapture这个activity

01-09 17:43:38.126:E/MipcaActivityCapture(27383): onCreate

01-09 17:43:38.165:E/MipcaActivityCapture(27383): onResume

01-09 17:43:38.165:E/MipcaActivityCapture(27383): hasSurface=false

01-09 17:43:38.251:E/MipcaActivityCapture(27383): surfaceCreated

01-09 17:43:38.251:E/MipcaActivityCapture(27383): initCamera

 

跳转到一个非完全覆盖的activity时

01-09 17:43:44.446:E/MipcaActivityCapture(27383): onPause

01-09 17:43:44.477: E/OtherActivity(27383):---------------onCreate--------------------

01-09 17:43:44.477: E/OtherActivity(27383):---------------onStart--------------------

01-09 17:43:44.477: E/OtherActivity(27383):---------------onResume--------------------

 

按back

01-09 17:43:50.954: E/OtherActivity(27383):---------------onPause--------------------

01-09 17:43:50.977:E/MipcaActivityCapture(27383): onResume

01-09 17:43:50.977: E/MipcaActivityCapture(27383):hasSurface=true

01-09 17:43:50.977:E/MipcaActivityCapture(27383): initCamera

01-09 17:43:51.954: E/OtherActivity(27383):---------------onStop--------------------

01-09 17:43:51.954: E/OtherActivity(27383):---------------onDestroy--------------------

 


总结

onPause会调用CameraManager.get().closeDriver();

surfaceCreated一般在OnResume之后调用,

按back或home都会调用surfaceDestroyed ,surfaceDestroyed在OnPause和OnStop之间调用。

但是锁屏不会调用surfaceDestroyed,解锁也不会调surfaceCreated

跳转到一个非完全覆盖的activity时也不会调surfaceDestroyed,返回时也不会调surfaceCreated

 

按back/home或者锁屏都会调用OnPause,导致CameraManager.get().closeDriver();所以下次进入activity的时候要initCamera,这是怎么实现的呢?看下面这段代码,展现了hasSurface的作用。

        if(hasSurface) {

            initCamera(surfaceHolder);

        }else {

            surfaceHolder.addCallback(this);

            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        }

锁屏解锁后hasSurface为true,调用initCamera。

按back或者home再回来时hasSurface为false,此时在onResume之后会调用surfaceCreated,在surfaceCreated里面会调用initCamera。

代码

稍微改了下原代码
package com.example.qr_codescan;

import java.io.IOException;
import java.util.Vector;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.mining.app.zxing.camera.CameraManager;
import com.mining.app.zxing.decoding.CaptureActivityHandler;
import com.mining.app.zxing.decoding.InactivityTimer;
import com.mining.app.zxing.view.ViewfinderView;
/**
 * Initial the camera
 * @author Ryan.Tang
 */
public class MipcaActivityCapture extends Activity implements Callback {

	private static final String TAG = MipcaActivityCapture.class.getSimpleName();
	private CaptureActivityHandler handler;
	private ViewfinderView viewfinderView;
	private boolean hasSurface;
	private Vector<BarcodeFormat> decodeFormats;
	private String characterSet;
	private InactivityTimer inactivityTimer;
	private MediaPlayer mediaPlayer;
	private boolean playBeep;
	private static final float BEEP_VOLUME = 0.10f;
	private boolean vibrate;
	Button btn;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		Log.e(TAG, "onCreate");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_capture1);
		//ViewUtil.addTopView(getApplicationContext(), this, R.string.scan_card);
		CameraManager.init(getApplication());
		viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
		
		Button mButtonBack = (Button) findViewById(R.id.button_back);
		mButtonBack.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				MipcaActivityCapture.this.finish();
				
			}
		});
		hasSurface = false;
		inactivityTimer = new InactivityTimer(this);
		
		btn=(Button) findViewById(R.id.btn1);
		btn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {

				Intent intent=new Intent(MipcaActivityCapture.this, OtherActivity.class);
				startActivity(intent);
				
			}
		});
	}

	@Override
	protected void onResume() {
		Log.e(TAG, "onResume");
		super.onResume();
		SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
		SurfaceHolder surfaceHolder = surfaceView.getHolder();
		Log.e(TAG, "hasSurface="+hasSurface);
		if (hasSurface) {
			initCamera(surfaceHolder);
		} else {
			surfaceHolder.addCallback(this);
			surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		}
		decodeFormats = null;
		characterSet = null;

		playBeep = true;
		AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
		if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
			playBeep = false;
		}
		initBeepSound();
		vibrate = true;
 
		
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (handler != null) {
			handler.quitSynchronously();
			handler = null;
		}
		CameraManager.get().closeDriver();

		Log.e(TAG, "onPause");
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		Log.e(TAG, "onStop");
	}
	@Override
	protected void onDestroy() {
		inactivityTimer.shutdown();
		super.onDestroy();
		Log.e(TAG, "onDestroy");
	}
	
	/**
	 * 处理扫描结果
	 * @param result
	 * @param barcode
	 */
	public void handleDecode(Result result, Bitmap barcode) {
		inactivityTimer.onActivity();
		playBeepSoundAndVibrate();
		String resultString = result.getText();
		if (resultString.equals("")) {
			Toast.makeText(MipcaActivityCapture.this, "Scan failed!", Toast.LENGTH_SHORT).show();
		}else {
			Intent resultIntent = new Intent();
			Bundle bundle = new Bundle();
			bundle.putString("result", resultString);
			bundle.putParcelable("bitmap", barcode);
			resultIntent.putExtras(bundle);
			this.setResult(RESULT_OK, resultIntent);
		}
		MipcaActivityCapture.this.finish();
	}
	
	private void initCamera(SurfaceHolder surfaceHolder) {

		Log.e(TAG, "initCamera");
		try {
			CameraManager.get().openDriver(surfaceHolder);
		} catch (IOException ioe) {
			return;
		} catch (RuntimeException e) {
			return;
		}
		if (handler == null) {
			handler = new CaptureActivityHandler(this, decodeFormats,
					characterSet);
		}
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {

	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {

		Log.e(TAG, "surfaceCreated");
		if (!hasSurface) {
			hasSurface = true;
			initCamera(holder);
		}

	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		hasSurface = false;

		Log.e(TAG, "surfaceDestroyed");

	}

	public ViewfinderView getViewfinderView() {
		return viewfinderView;
	}

	public Handler getHandler() {
		return handler;
	}

	public void drawViewfinder() {
		viewfinderView.drawViewfinder();

	}

	private void initBeepSound() {
		if (playBeep && mediaPlayer == null) {
			// The volume on STREAM_SYSTEM is not adjustable, and users found it
			// too loud,
			// so we now play on the music stream.
			setVolumeControlStream(AudioManager.STREAM_MUSIC);
			mediaPlayer = new MediaPlayer();
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mediaPlayer.setOnCompletionListener(beepListener);

			AssetFileDescriptor file = getResources().openRawResourceFd(
					R.raw.beep);
			try {
				mediaPlayer.setDataSource(file.getFileDescriptor(),
						file.getStartOffset(), file.getLength());
				file.close();
				mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
				mediaPlayer.prepare();
			} catch (IOException e) {
				mediaPlayer = null;
			}
		}
	}

	private static final long VIBRATE_DURATION = 200L;

	private void playBeepSoundAndVibrate() {
		if (playBeep && mediaPlayer != null) {
			mediaPlayer.start();
		}
		if (vibrate) {
			Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
			vibrator.vibrate(VIBRATE_DURATION);
		}
	}

	/**
	 * When the beep has finished playing, rewind to queue up another one.
	 */
	private final OnCompletionListener beepListener = new OnCompletionListener() {
		public void onCompletion(MediaPlayer mediaPlayer) {
			mediaPlayer.seekTo(0);
		}
	};

}


 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值