我有一个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());
}
}
}
我希望我的问题很清楚,可以回答
提前谢谢。