简体   繁体   English

Android手电筒应用每隔一次启动就会崩溃

[英]Android flashlight app crashes every other launch

I am new to app development and wanted to make a simple flashlight app for fun. 我是应用程序开发的新手,并希望制作一个简单的手电筒应用程序来玩乐。 However, for some reason my flashlight app crashes every other launch. 但是,由于某种原因,我的手电筒应用程序每次其他启动都会崩溃。 I thought I might need an onDestroy() method, but not sure if that's the problem. 我以为我可能需要onDestroy()方法,但不确定是否是问题所在。 I also always get a NullPointerException and the problem seems to be within the onCreate() method. 我也总是收到NullPointerException ,问题似乎在onCreate()方法内。 Thanks for any help! 谢谢你的帮助!

package com.monstartech.superuser.flashlight;

import android.annotation.SuppressLint;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.widget.ImageButton;


/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 */
public class FullscreenActivity extends AppCompatActivity {


    //Camera variables:
    private Camera camera;
    ImageButton flashlightSwitchImg;
    private boolean isFlashLightOn;
    Parameters params;


    /**
     * Whether or not the system UI should be auto-hidden after
     * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
     */
    private static final boolean AUTO_HIDE = true;

    /**
     * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
     * user interaction before hiding the system UI.
     */
    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;

    /**
     * Some older devices needs a small delay between UI widget updates
     * and a change of the status and navigation bar.
     */
    private static final int UI_ANIMATION_DELAY = 300;
    private final Handler mHideHandler = new Handler();
    private View mContentView;


    private final Runnable mHidePart2Runnable = new Runnable() {
        @SuppressLint("InlinedApi")
        @Override
        public void run() {
            // Delayed removal of status and navigation bar

            // Note that some of these constants are new as of API 16 (Jelly Bean)
            // and API 19 (KitKat). It is safe to use them, as they are inlined
            // at compile-time and do nothing on earlier devices.
            mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
        }
    };

    private View mControlsView;
    private final Runnable mShowPart2Runnable = new Runnable() {
        @Override
        public void run() {
            // Delayed display of UI elements
            ActionBar actionBar = getSupportActionBar();
            if (actionBar != null) {
                actionBar.show();
            }
            mControlsView.setVisibility(View.VISIBLE);
        }
    };
    private boolean mVisible;
    private final Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            hide();
        }
    };
    /**
     * Touch listener to use for in-layout UI controls to delay hiding the
     * system UI. This is to prevent the jarring behavior of controls going away
     * while interacting with activity UI.
     */
    private final View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (AUTO_HIDE) {
                delayedHide(AUTO_HIDE_DELAY_MILLIS);
            }
            return false;
        }
    };


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

        mVisible = true;
        mControlsView = findViewById(R.id.fullscreen_content_controls);
        mContentView = findViewById(R.id.fullscreen_content);

        // Set up the user interaction to manually show or hide the system UI.
        mContentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                toggle();
            }
        });


        // Upon interacting with UI controls, delay any scheduled hide()
        // operations to prevent the jarring behavior of controls going away
        // while interacting with the UI.
        //TODO: uncoment? findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);

        //Camera Stuff's old spot
        //Camera Stuff:
        flashlightSwitchImg = (ImageButton) findViewById(R.id.flashlightSwitch);
        boolean isCameraFlash = getApplicationContext().getPackageManager().
                hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);

        if(!isCameraFlash) {
            showNoCameraAlert();
        } else {
            camera = Camera.open();
            params = camera.getParameters();
        }

        flashlightSwitchImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(isFlashLightOn) {
                    setFlashLightOff();
                } else {
                    setFlashLightOn();
                }
            }


        });
    }

    private void showNoCameraAlert() {
        new AlertDialog.Builder(this).setTitle("Error: No Camera Flash Found!!").
                setMessage("Camera flashlight not available in this Android device!").
                setPositiveButton(android.R.string.yes,new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                })
                .setIcon(android.R.drawable.ic_dialog_alert)
                .show();
        return;
    }

    //setFlashLightOn
    private void setFlashLightOn() {
        params = camera.getParameters();
        params.setFlashMode(Parameters.FLASH_MODE_TORCH);
        camera.setParameters(params);
        camera.startPreview();
        isFlashLightOn = true;
        flashlightSwitchImg.setImageResource(R.drawable.light_on);
    }

    //setFlashLightOff
    private void setFlashLightOff() {
        params.setFlashMode(Parameters.FLASH_MODE_OFF);
        camera.setParameters(params);
        camera.stopPreview();
        isFlashLightOn = false;
        flashlightSwitchImg.setImageResource(R.drawable.light_off);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if(camera != null) {
            camera.release();
            camera = null;
        }
    }
    //end Camera stuff




    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        // Trigger the initial hide() shortly after the activity has been
        // created, to briefly hint to the user that UI controls
        // are available.
        delayedHide(100);
    }

    private void toggle() {
        if (mVisible) {
            hide();
        } else {
            show();
        }
    }

    private void hide() {
        // Hide UI first
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.hide();
        }
        mControlsView.setVisibility(View.GONE);
        mVisible = false;

        // Schedule a runnable to remove the status and navigation bar after a delay
        mHideHandler.removeCallbacks(mShowPart2Runnable);
        mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
    }

    @SuppressLint("InlinedApi")
    private void show() {
        // Show the system bar
        mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
        mVisible = true;

        // Schedule a runnable to display UI elements after a delay
        mHideHandler.removeCallbacks(mHidePart2Runnable);
        mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
    }

    /**
     * Schedules a call to hide() in [delay] milliseconds, canceling any
     * previously scheduled calls.
     */
    private void delayedHide(int delayMillis) {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        //Your code
    }
}

Logcat Logcat

05-11 15:11:39.793 18729-18729/com.monstartech.superuser.flashlight D/Activity: #1 setTransGradationModeColor false
05-11 15:11:40.583 18729-18729/com.monstartech.superuser.flashlight D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
05-11 15:11:40.653 18729-18729/com.monstartech.superuser.flashlight D/AndroidRuntime: Shutting down VM
05-11 15:11:40.653 18729-18729/com.monstartech.superuser.flashlight W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41d01da0)
05-11 15:11:40.653 18729-18729/com.monstartech.superuser.flashlight E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                      Process: com.monstartech.superuser.flashlight, PID: 18729
                                                                                      java.lang.NullPointerException
  at com.monstartech.superuser.flashlight.FullscreenActivity.setFlashLightOn(FullscreenActivity.java:173)
  at com.monstartech.superuser.flashlight.FullscreenActivity.access$700(FullscreenActivity.java:24)
  at com.monstartech.superuser.flashlight.FullscreenActivity$6.onClick(FullscreenActivity.java:150)
  at android.view.View.performClick(View.java:4754)
  at android.view.View$PerformClick.run(View.java:19591)
  at android.os.Handler.handleCallback(Handler.java:733)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:146)
  at android.app.ActivityThread.main(ActivityThread.java:5731)
  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:1291)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
  at dalvik.system.NativeStart.main(Native Method)
05-11 15:11:41.773 18729-18729/com.monstartech.superuser.flashlight 

I/Process: Sending signal. PID: 18729 SIG: 9

You are nulling out the camera onStop , but not recreating the camera object onStart . 您将使相机onStop无效,而不是重新创建相机对象onStart I would just cancel the camera but not make it null onStop . 我只是取消相机,但不要在onStop上将其设置为null。

onStop doesn't mean your app is destroyed. onStop并不意味着您的应用程序已被破坏。 It will be restarted as you left it, in this case with a null camera object. 它将在您离开时重新启动,在这种情况下将使用空相机对象。

According to your Logcat, the app is crashing at line 173, which looks like it is this line: 根据您的Logcat,该应用程序在第173行崩溃,看起来像是在这行:

params = camera.getParameters();

So your camera variable is probably null. 因此,您的相机变量可能为null。 So check for a null camera. 因此,请检查相机是否为空。 You can probably use the same logic from line 137 to initialize the camera. 您可能可以使用第137行中的相同逻辑来初始化相机。

private void setFlashLightOn() {
    if (camera == null) {
        // make isCameraFlash a class level variable
        if(!isCameraFlash) {
            showNoCameraAlert();
        } else {
            camera = Camera.open();
            params = camera.getParameters();
        }
    }

    params = camera.getParameters();
    // etc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM