WindowLeaked - Android

时间:2015-08-21 21:23:50

标签: java android android-intent camera alertdialog

我有一个WindowLeaked异常

  

08-21 22:04:44.405 12442-12442 / com.myapp.camera   E / WindowManager:android.view.WindowLeaked:Activity   com.myapp.camera.CameraActivity泄露了   window com.android.internal.policy.impl.PhoneWindow $ DecorView {6039706   最初添加的V.E ..... R ....... 0,0-1026,602}               在android.view.ViewRootImpl。(ViewRootImpl.java:382)               在android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:261)               在android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)               在android.app.Dialog.show(Dialog.java:298)               在com.myapp.camera.CameraActivity $ 2.run(CameraActivity.java:157)               在android.app.Activity.runOnUiThread(Activity.java:5272)               在com.myapp.camera.CameraActivity.getCameraInstance(CameraActivity.java:151)               在com.myapp.camera.CameraActivity.checkCameraHardware(CameraActivity.java:119)               在com.myapp.camera.CameraActivity.onCreate(CameraActivity.java:37)               在android.app.Activity.performCreate(Activity.java:5958)               在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)               在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)               在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)               在android.app.ActivityThread.access $ 800(ActivityThread.java:144)               在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1359)               在android.os.Handler.dispatchMessage(Handler.java:102)               在android.os.Looper.loop(Looper.java:155)               在android.app.ActivityThread.main(ActivityThread.java:5696)               at java.lang.reflect.Method.invoke(Native Method)               在java.lang.reflect.Method.invoke(Method.java:372)               在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1028)               在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

但到目前为止,我还没有找到可以解决问题的解决方案。这是代码:


AndroidManifest

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

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

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

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

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".CameraActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait">

        </activity>
    </application>

</manifest>


MainActivity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @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);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int itemId = item.getItemId();

        switch(itemId) {
            case R.id.action_camera:
                openCamera();
                break;
        }

        return super.onOptionsItemSelected(item);
    }

    private void openCamera() {
        Intent intent = new Intent(getApplicationContext(), CameraActivity.class);
        startActivity(intent);
    }
}


CameraActivity
我的问题在于这个课程,说它有一个泄漏的窗口。在第157行,您可以在else语句中找到alertDialog.show();。我知道如何修改我的代码,以防止错误显示。

public class CameraActivity extends AppCompatActivity {
    private static final String TAG = CameraActivity.class.getSimpleName();

    private Camera mCamera;
    private CameraPreview mCameraPreview;
    private AlertDialog mAlertDialog;

    //==============================================================================================
    // Activity Methods
    //==============================================================================================

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        // Check for Camera and then creates an instance of Camera.
        checkCameraHardware();

        // Create our Preview view and set it as the content of our activity.
        mCameraPreview =  new CameraPreview (this, mCamera);
        FrameLayout frameLayout = (FrameLayout) findViewById(R.id.cameraPreview);
        frameLayout.addView(mCameraPreview);
    }

    /**
     * Restarts the camera.
     */
    @Override
    protected void onResume() {
        super.onResume();
        checkCameraHardware();
    }

    /**
     * Stops the camera.
     */
    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera();
        dismissAlertDialog();
    }

    /**
     * Stops the camera.
     */
    @Override
    protected void onStop() {
        super.onStop();
        releaseCamera();
        dismissAlertDialog();
    }

    /**
     * Releases the resources associated with the camera source, and the
     * rest of the processing pipeline.
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseCamera();
        dismissAlertDialog();
    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.camera, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    //==============================================================================================
    // Camera Methods
    //==============================================================================================

    /**
     * Check if this device has a front facing camera.
     */
    private boolean checkCameraHardware() {
        if (Camera.getNumberOfCameras() >= 2){
            // this device has a front facing camera
            mCamera = getCameraInstance();
            return true;
        } else {
            // no front facing camera on this device
            return false;
        }
    }

    /**
     * A safe way to get an instance of the Camera object.
     */
    public Camera getCameraInstance() {
        mCamera = null;
        try {
            // Attempt to get a front facing Camera instance.
            mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
            mCamera.setDisplayOrientation(90);
        } catch (Exception e) {
            // Camera is not available (in use or does not exist).
            Log.e(TAG, e.getMessage());
            AlertDialog.Builder builder = new AlertDialog.Builder(CameraActivity.this);
            builder.setMessage(e.getMessage())
                    .setTitle(R.string.cameraErrorMessage)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            startActivity(intent);
                        }
                    });
            final AlertDialog alertDialog = builder.create();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (mAlertDialog != null && mAlertDialog.isShowing()) {
                        alertDialog.dismiss();
                    } else {
                        alertDialog.show();
                    }
                }
            });

        }
        return mCamera; // Returns null if camera is unavailable.
    }

    //==============================================================================================
    // Helper Methods
    //==============================================================================================

    private void releaseCamera() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    private void dismissAlertDialog() {
        if (mAlertDialog != null) {
            mAlertDialog.dismiss();
        }
        if (mAlertDialog != null && mAlertDialog.isShowing()) {
            mAlertDialog.dismiss();
        }
        mAlertDialog = null;
    }
}


CameraPreview

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = CameraPreview.class.getSimpleName();

    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 {
            if (mCamera != null) {
                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 {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();
            }
        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}


我希望我的问题很清楚,可以回答 提前谢谢。

0 个答案:

没有答案