在片段

时间:2017-04-12 11:26:04

标签: android android-layout android-fragments android-fragmentactivity

我正试图在片段中打开相机。我正在使用api level 19.因此使用相机库而不是camera2。下面是我尝试从here复制的代码我无法在片段中打开相机。告诉我哪里出了问题。 :(请任何人。我试图打开相机已经过了2天。

//片段类的代码名为scan



package layout;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.Layout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;

import com.example.root.meeransunday.R;

import java.io.ByteArrayOutputStream;
import java.io.File;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link scan.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link scan#newInstance} factory method to
 * create an instance of this fragment.
 */
public class scan extends Fragment {


    private Camera mCamera;
    private CameraPreview mPreview;
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    public scan() {
    }


    // TODO: Rename and change types and number of parameters
    public static scan newInstance(String param1, String param2) {
        scan fragment = new scan();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if(checkCameraHardware(getActivity().getApplicationContext())){
            getCameraInstance();
            mCamera = getCameraInstance();
            mPreview = new CameraPreview(this.getActivity(), mCamera);

            container.addView(mPreview);
        }
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_scan, container, false);
    }

//

    /** Check if this device has a camera */
    public boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }
    //

    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}




//相机Exception类的代码,因为它来自android //文档链接



package layout;

/**
 * Created by root on 4/12/17.
 */

import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;

import static android.content.ContentValues.TAG;

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
            // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}




//片段xml命名扫描



<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/Camera_preview"
    tools:context="layout.scan"
    android:background="#f5f5dc"
    android:layout_centerInParent="true"
    >

    <!-- TODO: Update blank fragment layout -->
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

    </RelativeLayout>

</FrameLayout>
&#13;
&#13;
&#13;

&#13;
&#13;
  java.lang.NullPointerException
                      at layout.CameraPreview.surfaceCreated(CameraPreview.java:37)
                      at android.view.SurfaceView.updateWindow(SurfaceView.java:662)
                      at android.view.SurfaceView.access$000(SurfaceView.java:90)
                      at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:195)
                      at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
                      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2191)
                      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1189)
                      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6223)
                      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:788)
                      at android.view.Choreographer.doCallbacks(Choreographer.java:591)
                      at android.view.Choreographer.doFrame(Choreographer.java:560)
                      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774)
                      at android.os.Handler.handleCallback(Handler.java:808)
                      at android.os.Handler.dispatchMessage(Handler.java:103)
                      at android.os.Looper.loop(Looper.java:193)
                      at android.app.ActivityThread.main(ActivityThread.java:5330)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:515)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
                      at dalvik.system.NativeStart.main(Native Method)
D/dalvikvm: threadid=13: interp stack at 0x62222000
I/Process: Sending signal. PID: 4972 SIG: 9
Application terminated.
&#13;
&#13;
&#13;

上面的错误日志^^

&#13;
&#13;
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.root.meeransunday, PID: 16453
                  java.lang.NullPointerException
                      at layout.CameraPreview.surfaceCreated(CameraPreview.java:37)
                      at android.view.SurfaceView.updateWindow(SurfaceView.java:662)
                      at android.view.SurfaceView.access$000(SurfaceView.java:90)
                      at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:195)
                      at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
                      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2191)
                      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1189)
                      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6223)
                      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:788)
                      at android.view.Choreographer.doCallbacks(Choreographer.java:591)
                      at android.view.Choreographer.doFrame(Choreographer.java:560)
                      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774)
                      at android.os.Handler.handleCallback(Handler.java:808)
                      at android.os.Handler.dispatchMessage(Handler.java:103)
                      at android.os.Looper.loop(Looper.java:193)
                      at android.app.ActivityThread.main(ActivityThread.java:5330)
                      at java.lang.reflect.Method.invokeNative(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:515)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
                      at dalvik.system.NativeStart.main(Native Method)
Device rivo-phantom_pz15-HB51Q0H9103UXBdisconnected, monitoring stopped.
Application terminated.
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:0)

AndroidManifest添加照相机的权限中:

<uses-permission android:name="android.permission.CAMERA" />

答案 1 :(得分:0)

您的代码无法找到相机预览的表面。 因此,在您的片段类中,您需要准确定义要显示相机预览的位置。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.fragment_scan, container, false);

     if(checkCameraHardware(getActivity().getApplicationContext())){
        getCameraInstance();
        mCamera = getCameraInstance();
        mPreview = new CameraPreview(this.getActivity(), mCamera);

        //container.addView(mPreview);--->Remove this line 
        //Add this line
        FrameLayout preview =(FrameLayout)view.findViewById(R.id.camera_preview);
        preview.addView(mPreview);
    }
    // Inflate the layout for this fragment
    return view;
}

此外,您还需要在布局文件中提供一个特定的容器:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
>
    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
    />
</LinearLayout>

我希望这可以解决你的问题......