如何在片段之间切换时处理相机?

时间:2017-05-17 09:37:21

标签: android android-fragments android-camera android-fragmentactivity

我使用2个按钮在2个不同的片段之间切换。一个片段具有摄像机视图并且第一次打开得非常好,但是当从第二个片段再次返回到相同的片段时会出现空白屏幕。虽然相机硬件是免费的,但是无法看到相机预览。我不使用camera2 api但是需要一个解决这个bug的方法。我添加了完整的代码和图像以获得帮助。 enter image description here

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.root.meeransunday" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar"
            android:screenOrientation="portrait"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <supports-screens android:smallScreens="true"
            android:normalScreens="true"
            android:largeScreens="true"
            android:xlargeScreens="true"
            android:anyDensity="true"
            android:resizeable="true"/>

    </application>
    <activity android:name="meeranSunday"
        android:configChanges="orientation|keyboardHidden"
        />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.CAMERA">

    </uses-permission>

    <uses-feature android:name="android.hardware.camera.autofocus" />

    <uses-feature android:name="android.hardware.camera" />
</manifest>

片段java类

public class scan extends Fragment implements ZXingScannerView.ResultHandler {
private ZXingScannerView zXingScannerView;
private SurfaceView mySurfaceView;
private Camera mCamera;
private CameraPreview mPreview;
private String m_Text = "";
private String number = "";

private OnFragmentInteractionListener mListener;

public scan() {}
@Override
public void handleResult(Result rawResult) {
    // Do something with the result here

    Log.e("handler", rawResult.getText()); // Prints scan results
    Log.e("handler", rawResult.getBarcodeFormat().toString()); // Prints the scan format (qrcode)

    // show the scanner result into dialog box.
    AlertDialog.Builder builder = new AlertDialog.Builder(this.getActivity());
    builder.setTitle("Scan Result");
    builder.setMessage(rawResult.getText());
    number = rawResult.getText().substring(rawResult.getText().length() - 13);

    //
    final EditText input = new EditText(this.getActivity());
    // Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
    input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
    builder.setView(input);

    // Set up the buttons
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            m_Text = input.getText().toString();

            try {
                SmsManager smsManager = SmsManager.getDefault();
                smsManager.sendTextMessage(number, null, m_Text + " Transferred To Your Account From MTM Account", null, null);

            } catch (Exception e) {

                e.printStackTrace();
            }
        }
    });
    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.cancel();
        }
    });

    builder.setNegativeButton("NO",
        new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });




    //
    AlertDialog alert1 = builder.create();
    alert1.show();


    // If you would like to resume scanning, call this method below:
    zXingScannerView.resumeCameraPreview(this);
}

// TODO: Rename and change types and number of parameters
public static scan newInstance() {
    scan fragment = new scan();
    Bundle args = new Bundle();
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

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

    if (checkCameraHardware(getActivity().getApplicationContext())) {
        Toast.makeText(this.getActivity(), "camera hardware is free", Toast.LENGTH_SHORT).show();
        zXingScannerView = new ZXingScannerView(this.getActivity().getApplicationContext());
        zXingScannerView.setResultHandler(this);
        zXingScannerView.startCamera(0);
    } else {

        Toast.makeText(this.getActivity(), "camera hardware is NOT free", Toast.LENGTH_SHORT).show();
    }

    FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_preview);
    preview.addView(zXingScannerView);
    return view;
}
@Override
public void onPause() {
    super.onPause();
    try {
        mCamera = Camera.open();
    } catch (RuntimeException e) {
        Log.d("camera opening attempt:", e.getMessage());
    } finally {
        if (mCamera != null) {
            Log.d("camera opening attempt:", "yups ");
            mCamera.release();
            zXingScannerView.stopCamera();
            zXingScannerView.stopCameraPreview();
        }
    }
}
@Override
public void onResume() {
    super.onResume();
    zXingScannerView.setResultHandler(this); // Register ourselves as a handler for scan results.
    zXingScannerView.startCamera(0); // Start camera on resume
}

public boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {

        return true;
    } else {

        return false;
    }
}


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() {
    Log.d("aa", "sdsdssdsddssssd");
    try {
        mCamera = Camera.open();
    } catch (RuntimeException e) {
        Log.d("camera opening attempt:", e.getMessage());
    } finally {
        if (mCamera != null) {
            mCamera.release();
            zXingScannerView.stopCamera();
            zXingScannerView.stopCameraPreview();
        }
    }

    super.onDetach();
    mListener = null;
}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name\

    void onFragmentInteraction(Uri uri);
}
}

MAinactivity

public class MainActivity extends AppCompatActivity
 implements NavigationView.OnNavigationItemSelectedListener {
 public int check = 0;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
     setSupportActionBar(toolbar);
     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
     ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
         this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
     drawer.setDrawerListener(toggle);
     toggle.syncState();

     NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
     navigationView.setNavigationItemSelectedListener(this);
     FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
     message frags = new message();
     fragmentTransaction.add(R.id.content_main, frags, "text");
     fragmentTransaction.commit();

     check += 1;
 }
 public void message(View v) {
     FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
     message sms = new message();


     fragmentTransaction.replace(R.id.content_main, sms, "text");
     fragmentTransaction.addToBackStack(null);
     fragmentTransaction.commit();
 }

 public void scan(View v) {
     FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

     scan scan = new scan();

     fragmentTransaction.replace(R.id.content_main, scan, "scan");
     fragmentTransaction.addToBackStack(null);
     fragmentTransaction.commit();


 }
 public void loadooncreate() {
     setContentView(R.layout.activity_main);
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
     setSupportActionBar(toolbar);

     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
     ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
         this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
     drawer.setDrawerListener(toggle);
     toggle.syncState();

     NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
     navigationView.setNavigationItemSelectedListener(this);
     FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
     message frags = new message();
     fragmentTransaction.add(R.id.content_main, frags, "text");
     fragmentTransaction.commit();
     check += 1;
 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
     // Inflate the menu; this adds items to the action bar if it is present.
     getMenuInflater().inflate(R.menu.main, menu);

     Toolbar toolbar2 = (Toolbar) findViewById(R.id.toolbar1);
     toolbar2.inflateMenu(R.menu.notify);

     toolbar2.getMenu().findItem(R.id.notifications).setIcon(buildCounterDrawable(2, R.drawable.notification));

     toolbar2.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {

         @Override
         public boolean onMenuItemClick(MenuItem arg0) {
             if (arg0.getItemId() == R.id.notifications) {
                 arg0.setIcon(buildCounterDrawable(0, R.drawable.notification));
                 ((RelativeLayout) findViewById(R.id.content_main)).removeAllViews();
                 FragmentManager fragmentManager = getFragmentManager();
                 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                 BlankFragment frag = new BlankFragment();
                 fragmentTransaction.add(R.id.content_main, frag, "first");
                 fragmentTransaction.commit();
             }
             return false;
         }
     });

     check = 1;
     return true;
 }

 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {
     if (keyCode == KeyEvent.KEYCODE_BACK) {
         //code to reset view
         FragmentManager fragmentManager = getFragmentManager();
         FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

         if (fragmentManager.findFragmentByTag("first") != null) {

             fragmentTransaction.remove(fragmentManager.findFragmentByTag("first"));
             fragmentTransaction.commit();
             loadooncreate();
         } else {

             finish();
         }

         return true;
     }
     return super.onKeyDown(keyCode, event);
 }
 private Drawable buildCounterDrawable(int count, int backgroundImageId) {
     LayoutInflater inflater = LayoutInflater.from(this);
     View view = inflater.inflate(R.layout.counter_menuitem_layout, null);
     view.setBackgroundResource(backgroundImageId);

     if (count == 0) {
         View counterTextPanel = view.findViewById(R.id.counterValuePanel);
         counterTextPanel.setVisibility(View.GONE);
     } else {
         //            TextView textView = (TextView) view.findViewById(count);
         //            textView.setText("1");
     }
     view.measure(
         View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
         View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
     view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

     view.setDrawingCacheEnabled(true);
     view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
     Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
     view.setDrawingCacheEnabled(false);

     return new BitmapDrawable(getResources(), bitmap);
 }

 @Override
 public boolean onPrepareOptionsMenu(Menu menu) {
     if (check > 3) {
         Toast.makeText(this.getApplicationContext(), "sdsdsdfdsfsd", Toast.LENGTH_SHORT).show();
         MenuItem item = menu.getItem(R.id.notifications);
         item.setIcon(buildCounterDrawable(2, R.drawable.notification));

     }
     //MenuItem item = (MenuItem)findViewById(R.id.notifications);
     //    item.setIcon(buildCounterDrawable(2, R.drawable.notification));

     return true;
 }
 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

     if (item.getItemId() == R.id.Home) {
         //close current fragment;
         FragmentManager fragmentManager = getFragmentManager();
         FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

         if (fragmentManager.findFragmentByTag("first") != null)

             fragmentTransaction.remove(fragmentManager.findFragmentByTag("first"));
         fragmentTransaction.commit();
         loadooncreate();

     }
     return super.onOptionsItemSelected(item);
 }


 @SuppressWarnings("StatementWithEmptyBody")
 @Override
 public boolean onNavigationItemSelected(MenuItem item) {
     // Handle navigation view item clicks here.
     int id = item.getItemId();

     if (id == R.id.nav_camera) {
         // Handle the camera action
     } else if (id == R.id.nav_gallery) {

     } else if (id == R.id.nav_slideshow) {

     } else if (id == R.id.nav_manage) {

     } else if (id == R.id.nav_share) {

     } else if (id == R.id.nav_send) {

     }

     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
     drawer.closeDrawer(GravityCompat.START);
     return true;
 }


 }

上次堆叠错误

W/MessageQueue: Handler (android.hardware.Camera$EventHandler) {428e2000} sending message to a Handler on a dead thread
                java.lang.RuntimeException: Handler (android.hardware.Camera$EventHandler) {428e2000} sending message to a Handler on a dead thread
                    at android.os.MessageQueue.enqueueMessage(MessageQueue.java:294)
                    at android.os.Handler.sendMessageAtTime(Handler.java:473)
                    at android.os.Handler.sendMessageDelayed(Handler.java:446)
                    at android.os.Handler.sendMessage(Handler.java:383)
                    at android.hardware.Camera.postEventFromNative(Camera.java:852)
                    at dalvik.system.NativeStart.run(Native Method)

2 个答案:

答案 0 :(得分:1)

您可以尝试此操作,移除onAttachonDetach。也请在onCreate

中替换此代码
if (checkCameraHardware(getActivity().getApplicationContext())) {
    Toast.makeText(this.getActivity(), "camera hardware is free", Toast.LENGTH_SHORT).show();
    zXingScannerView = new ZXingScannerView(this.getActivity().getApplicationContext());
    zXingScannerView.setResultHandler(this);
    zXingScannerView.startCamera(0);
} else {

    Toast.makeText(this.getActivity(), "camera hardware is NOT free", Toast.LENGTH_SHORT).show();
}

有了这个。

 zXingScannerView = new ZXingScannerView(this.getActivity().getApplicationContext());

然后改变onPause和onResume。

  @Override
  public void onPause()
  super.onPause(); {
      if (zXingScannerView != null) {
          zXingScannerView.stopCamera();
          zXingScannerView.stopCameraPreview();
      }
  }
  @Override
  public void onResume() {
      super.onResume();
      if (checkCameraHardware(getActivity().getApplicationContext())) {
          Toast.makeText(this.getActivity(), "camera hardware is free", Toast.LENGTH_SHORT).show();
          zXingScannerView.setResultHandler(this); // Register ourselves as a 
          zXingScannerView.startCamera(0); // Start camera on resume
      }
  }

同时删除所有这些对象

  private SurfaceView mySurfaceView;
  private Camera mCamera;
  private CameraPreview mPreview;

不需要它们,它位于zXingScannerView中。

答案 1 :(得分:1)

实际上,当切换到其他片段时,您不是释放对象,首先释放onPause()方法中的所有对象,并且onResume()重新连接相机。试试这个:

@Override
public void onResume() {
    super.onResume();
    if (zXingScannerView!= null) {
        zXingScannerView.stopCameraPreview();
        zXingScannerView.resumeCameraPreview(this);
    }
}