我有一个带开始按钮的简单屏幕.按下“开始”按钮后,我想转到带有SurfaceView的新屏幕以显示摄像机.
一切正常,但相机需要一段时间才能加载,这给了我一个黑屏.
我想加载新的布局.并且在装载后启动相机…
因此,我在后台线程中完成所有相机加载,但仍然,我得到一个黑屏……
这是我的布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/RelativeLayout1" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/blue_bg"> <SurfaceView android:id="@+id/surface_camera" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginLeft="25dp" android:layout_marginRight="25dp" android:layout_below="@id/scan_header" android:layout_above="@id/scan_footer"> </SurfaceView> </RelativeLayout>
这是我的Activity中的方法,它加载新视图:
private void setContent() { setContentView(R.layout.scan) Thread t = new Thread() { public void run() { final SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera); final SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder(); try { cameraView = new CameraView(); mSurfaceHolder.addCallback(cameraView); cameraView.setPictureListener(SunpluggedActivity.this); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } catch(Exception e) { Log.d(TAG,"Another exception"); e.printStackTrace(); } } }; t.start(); }
为什么新的布局没有显示,直到线程完成加载相机?
编辑:我已经尝试Thread中的Thread.sleep(200)睡了一段时间…当我这样做时,新的布局显示出来,但相机永远不会启动…
解决方法
好吧,问题是我在xml布局中使用了SurfaceView.
你打电话的那一刻:setContentView(your_layout) – > XML文件被夸大了.
这意味着,SurfaceView也会膨胀.这再次意味着调用SurfaceView onSurfaceCreated方法,触发打开相机等.
你打电话的那一刻:setContentView(your_layout) – > XML文件被夸大了.
这意味着,SurfaceView也会膨胀.这再次意味着调用SurfaceView onSurfaceCreated方法,触发打开相机等.
因此,整个过程需要一段时间,因此,您之前的Activity(例如,使用SurfaceView启动Activity的那个)似乎没有响应……
我在BG线程中创建CameraView的解决方案解决了无响应问题.但未能在SurfaceView中显示Camera输出.
解决方案是从xml中删除SurfaceView.这将立即启动您的活动(因为SurfaceView& Camera未实例化).
加载新的“活动”布局后,可以以编程方式将新的SurfaceView添加到屏幕上.当然,这也需要时间,但您的UI会快速切换到新活动,并且您可以在SurfaceView和Camera加载时显示加载程序!
所以:从XML中删除SURFACEVIEW – >在程序上添加它:
发布活动:
public class Launch extends Activity implements OnClickListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn = (Button)findViewById(R.id.button1); btn.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent = new Intent(Launch.this,SurfaceTestActivity.class); startActivity(intent); } }
Main.xml(只是一个启动新活动的按钮)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/RelativeLayout1" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ff6600"> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </RelativeLayout>
这是第二个活动(包含SurfaceView)
public class SurfaceTestActivity extends Activity { private Context mContext; private CameraView cameraView; private Handler mHandler = new Handler(); private final Runnable mLoadCamera = new Runnable() { public void run() { startCamera(); } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContent(); mContext = getApplicationContext(); } private void startCamera() { RelativeLayout rl = (RelativeLayout)findViewById(R.id.surface_camera); SurfaceView surfaceView = new SurfaceView(mContext); final SurfaceHolder mSurfaceHolder = surfaceView.getHolder(); try { cameraView = new CameraView(); mSurfaceHolder.addCallback(cameraView); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } catch(Exception e) { Log.d("debug","Another exception"); e.printStackTrace(); } if(rl != null && surfaceView != null) rl.addView(surfaceView); } private void setContent() { setContentView(R.layout.scan); // Post the Runnable with a Slight delay -> than your layout will be // shown. Without the delay -> your UI will feel inresponsive mHandler.postDelayed(mLoadCamera,100); } }
这是第二个Activity的布局(没有SURFACEVIEW)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/RelativeLayout1" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ff6600"> <RelativeLayout android:id="@+id/header" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Explanation Txt"></TextView> </RelativeLayout> <RelativeLayout android:id="@+id/footer" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Explanation Txt"></TextView> </RelativeLayout> <RelativeLayout android:id="@+id/surface_camera" android:layout_width="fill_parent" android:layout_height="match_parent" android:layout_above="@+id/footer" android:layout_below="@+id/header" android:background="#ff0066"> </RelativeLayout> </RelativeLayout>
最后,为了完成答案,这里是CameraView()的代码.打开相机并显示内容真的只是一个简单的实现:
public class CameraView implements SurfaceHolder.Callback{ // Variables private Camera mCamera = null; private boolean mPreviewRunning = false; private boolean mProcessing = false; private int mWidth = 0; private int mHeight = 0; @Override public void surfaceChanged(SurfaceHolder holder,int format,int width,int height) { if(mPreviewRunning ) { mCamera.stopPreview(); } // Store width and height mWidth = width; mHeight = height; // Set camera parameters Camera.Parameters p = mCamera.getParameters(); mCamera.setParameters(p); if(android.os.Build.VERSION.SDK_INT >= 8) { // If API >= 8 -> rotate display... mCamera.setDisplayOrientation(90); } try { mCamera.setPreviewDisplay(holder); } catch(IOException e) { e.printStackTrace(); } mCamera.startPreview(); mPreviewRunning = true; } @Override public void surfaceCreated(final SurfaceHolder holder) { try { mCamera = Camera.open(); mCamera.setPreviewDisplay(holder); } catch (IOException e) { mCamera.release(); mCamera = null; e.printStackTrace(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if(mCamera != null) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.setPreviewCallback(null); mPreviewRunning = false; mCamera.release(); mCamera = null; } } }