首页 > 解决方案 > 每次打开相机时应用程序都会崩溃

问题描述

我写了一个应用程序,它应该拍照和录制视频,然后在屏幕上显示。在手机上尝试时,相机无法使用,但可以在模拟器中使用。

执行应用程序时,这正是发生的情况:

每次我点击按钮打开相机,应用程序停止,它显示的错误是应用程序名称已停止,再次打开应用程序

当我再次单击打开应用程序时,它恢复正常状态

我已在我的程序中授予相机权限

下面是我的代码:

public class EventActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
    public static final String KEY_MENU_TYPE = "menutype";
    //public static final String KEY_PREF_USER_DETAILS = "prefUserDetails";
    private static final String TAG = EventActivity.class.getSimpleName();

    private static final String SERVER_IMAGE_PATH = "http://edo.com/imageupload/";
    private static final String SERVER_PATH = "http://edo.com/";

    String[] PERMISSIONS = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};

    private GoogleApiClient mGoogleApiClient;

    private Location mLastLocation;
    private LocationRequest mLocationRequest;

    private EditText event, eventDescription, name;
    private TextView attachmentStatus;

    private static final int TAKE_PICTURE = 1;
    private static final int PERMISSION_ALL = 3;

    private Uri capturedImageUri;
    private Uri videoUri;
    private String mediaFile;
    private String videoFile;

    private static final int MY_SOCKET_TIMEOUT_MS = 5000;
    private String[] serverData;
    private static final int REQUEST_VIDEO_CAPTURE = 300;

    private boolean isImage;
    private String locationResult;
    String menutype = "";


 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event);
        Intent intent = getIntent();
       /* ActionBar mBar = getSupportActionBar();
        if(mBar != null){
            mBar.setDisplayHomeAsUpEnabled(true);
        }*/

        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addApi(LocationServices.API)
                    .build();
        }
        mLocationRequest = createLocationRequest();

        Button photoVideoButton = (Button)findViewById(R.id.take_image_video);
        photoVideoButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showOptionDialog();
            }
        });
        attachmentStatus = (TextView)findViewById(R.id.file_status);
        event = (EditText)findViewById(R.id.enter_event);
        eventDescription =(EditText)findViewById(R.id.enter_event_description);
        name = (EditText)findViewById(R.id.name);

        Button cancelUploadButton = (Button) findViewById(R.id.cancel_upload);
        assert cancelUploadButton != null;
        cancelUploadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                resetViewControls();
            }
        });

        Button sendToServerButton = (Button) findViewById(R.id.send_to_server);
        assert sendToServerButton != null;
        sendToServerButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String eventValue = event.getText().toString().trim();
                String eventDescriptionValue = eventDescription.getText().toString();
                String nameValue = name.getText().toString();
                String locationValue = "";

                if(TextUtils.isEmpty(eventValue) || TextUtils.isEmpty(eventDescriptionValue) || TextUtils.isEmpty(nameValue)){
                    Toast.makeText(EventActivity.this, getString(R.string.send_to_server_error), Toast.LENGTH_LONG).show();
                    return;
                }

                if(locationResult == null || locationResult.equals("")){
                    locationValue = "";
                }else{
                    locationValue = locationResult;
                }

                if(TextUtils.isEmpty(mediaFile) && TextUtils.isEmpty(videoFile)){
                    Toast.makeText(EventActivity.this, "Please attach a photo or video", Toast.LENGTH_LONG).show();
                    return;
                }

                if(!TextUtils.isEmpty(mediaFile) && isImage){
                    // send the information to remote server
                    Bitmap storeBitmap = BitmapFactory.decodeFile(mediaFile);
                    Bitmap resizedBitmap = Bitmap.createScaledBitmap(storeBitmap, 640, 420, true);
                    String imageBasedString = convertBitmapToBaseImageString(resizedBitmap);

                    serverData = new String[]{eventValue, eventDescriptionValue, nameValue, imageBasedString, locationValue};
                    sendCapturedImageToServer(serverData);

                    //move stored video to a new folder
                    String photoPath = getMovedFilePath(mediaFile, eventValue);
                    moveFileToNewDestination(mediaFile, photoPath);

                }else if(!TextUtils.isEmpty(mediaFile) && !isImage){

                    //Store the video to your server
                    uploadVideoToServer(videoFile, eventValue, eventDescriptionValue, nameValue, locationValue);
                    //move stored video to a new folder
                    String photoPath = getMovedFilePath(videoFile, eventValue);
                    moveFileToNewDestination(videoFile, photoPath);

                }else{
                    // Image or video is missing. Show message to user
                    Toast.makeText(EventActivity.this, getString(R.string.upload_image_or_video), Toast.LENGTH_LONG).show();
                }
            }
        });


        this.menutype = intent.getStringExtra(KEY_MENU_TYPE);
        if (this.menutype == null) {
            this.menutype = "";
        }
    }


    public void goBack(View view) {
        Intent intent;
        if (this.menutype.equals("PRE")) {
            intent = new Intent(this, PreElectionMenuActivity.class);
        } else if (this.menutype.equals("ACC")) {
            intent = new Intent(this, AccreditationMenuActivity.class);
        } else if (this.menutype.equals("ELE")) {
            intent = new Intent(this, VotingMenuActivity.class);
        } else if (this.menutype.equals("INC")) {
            intent = new Intent(this, IncidentMenuActivity.class);
        } else {
            intent = new Intent(this, HomeActivity.class);
        }
        startActivity(intent);
    }

    private String getMovedFilePath(String filePath, String eventName){
        int indexPosition = filePath.lastIndexOf(".");
        String fileExtension = filePath.substring(indexPosition, filePath.length());
        String newFilename = eventName + fileExtension;
        return getFileDestinationPath(newFilename);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == TAKE_PICTURE) {
                capturedImageUri = data.getData();

                if (!hasPermissions(this, PERMISSIONS)){
                    ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
                }else {
                    mediaFile = "";
                    mediaFile = getRealPathFromURIPath(capturedImageUri, EventActivity.this);
                    Log.d(TAG, "Capture image path" + mediaFile);
                    attachmentStatus.setText("Image file has been attached");
                    isImage = true;
                }
            }
            if (requestCode == REQUEST_VIDEO_CAPTURE) {
                videoUri = data.getData();

                if (!hasPermissions(this, PERMISSIONS)){
                    ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
                }else{
                    videoFile = getRealPathFromURIPath(videoUri, EventActivity.this);
                    Log.d(TAG, "Captured video path " + videoUri);
                    Log.d(TAG, "New path " + videoFile);
                    attachmentStatus.setText("Video file has been attached");
                    isImage = false;
                }
            }
        }
    }

    private void resetViewControls(){
        event.setText("");
        eventDescription.setText("");
        name.setText("");
        attachmentStatus.setText(R.string.attached_file);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(capturedImageUri != null){
            if (!hasPermissions(this, PERMISSIONS)){
                ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
            }else {
                mediaFile = getRealPathFromURIPath(capturedImageUri, EventActivity.this);
            }
        }
    }

    private String getRealPathFromURIPath(Uri contentURI, Activity activity) {
        Cursor cursor = activity.getContentResolver().query(contentURI, null, null, null, null);
        if (cursor == null) {
            return contentURI.getPath();
        } else {
            cursor.moveToFirst();
            int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            return cursor.getString(idx);
        }
    }

    private String convertBitmapToBaseImageString(Bitmap bitmap){
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 50, stream);
        byte[] byte_arr = stream.toByteArray();
        return Base64.encodeToString(byte_arr, 0);
    }

    private void sendCapturedImageToServer(String[] photoDetails){
        Map<String, String> params = new HashMap<String,String>();
        params.put("EVENT", photoDetails[0]);
        params.put("EVENT_DESCRIPTION", photoDetails[1]);
        params.put("NAME", photoDetails[2]);
        params.put("CAPTURE_IMAGE", photoDetails[3]);
        params.put("EVENT_LOCATION", photoDetails[4]);

        GsonRequest<ServerObject> serverRequest = new GsonRequest<ServerObject>(
                Request.Method.POST,
                SERVER_IMAGE_PATH,
                ServerObject.class,
                params,
                createRequestSuccessListener(),
                createRequestErrorListener());

        serverRequest.setRetryPolicy(new DefaultRetryPolicy(
                MY_SOCKET_TIMEOUT_MS,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

        VolleySingleton.getInstance(EventActivity.this).addToRequestQueue(serverRequest);
    }

    private Response.Listener<ServerObject> createRequestSuccessListener() {
        return new Response.Listener<ServerObject>() {
            @Override
            public void onResponse(ServerObject response) {
                try {
                    Log.d(TAG, "Json Response " + response.getSuccess());
                    if(!TextUtils.isEmpty(response.getSuccess()) && response.getSuccess().equals("1")){
                        Toast.makeText(EventActivity.this, getString(R.string.successful_upload), Toast.LENGTH_LONG).show();
                        resetViewControls();
                    }else{
                        Toast.makeText(EventActivity.this, getString(R.string.server_error), Toast.LENGTH_LONG).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
        };
    }

    private Response.ErrorListener createRequestErrorListener() {
        return new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                error.printStackTrace();
            }
        };
    }

    public static void getAddressFromLocation(final double lat, final double lon, final Context context, final Handler handler) {
        Thread thread = new Thread() {
            @Override public void run() {
                Geocoder geocoder = new Geocoder(context, Locale.getDefault());
                String result = null;
                try {
                    List<Address> list = geocoder.getFromLocation(lat, lon, 1);
                    if (list != null && list.size() > 0) {
                        Address address = list.get(0);
                        // sending back first address line and locality
                        result = address.getAddressLine(0) + ", " + address.getLocality() + ", " +  address.getCountryName() ;
                        Log.d(TAG, "The converted Address " + result);
                    }
                } catch (IOException e) {
                    Log.e(TAG, "Impossible to connect to GeoCoder", e);
                } finally {
                    Message msg = Message.obtain();
                    msg.setTarget(handler);
                    if (result != null) {
                        msg.what = 1;
                        Bundle bundle = new Bundle();
                        bundle.putString("address", result);
                        msg.setData(bundle);
                    } else
                        msg.what = 0;
                    msg.sendToTarget();
                }
            }
        };
        thread.start();
    }

    @SuppressLint("HandlerLeak")
    private class GeoCoderHandler extends Handler {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case 1:
                    Bundle bundle = message.getData();
                    locationResult = bundle.getString("address");
                    Log.d(TAG, "Location Result " + locationResult);
                    break;
                default:
                    locationResult = null;
            }
        }
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
        PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());

        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(@NonNull LocationSettingsResult result) {
                final Status status = result.getStatus();

                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        Log.d(TAG, "Connection method has been called");
                        if(!hasPermissions(EventActivity.this, PERMISSIONS)){
                            ActivityCompat.requestPermissions(EventActivity.this, PERMISSIONS, PERMISSION_ALL);
                        }
                        else{
                            if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                                    && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                                mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
                                if(mLastLocation != null){
                                    getAddressFromLocation(mLastLocation.getLatitude(), mLastLocation.getLongitude(), EventActivity.this, new GeoCoderHandler());
                                }
                            }
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        break;
                }
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_ALL: {
                // If request is cancelled, the result arrays are empty.
                if(grantResults[0] == PackageManager.PERMISSION_DENIED){
                    Toast.makeText(EventActivity.this, "Sorry!!!, you can't use this app without granting this permission", Toast.LENGTH_LONG).show();
                    finish();
                }
                if (grantResults[1] == PackageManager.PERMISSION_DENIED || grantResults[2] == PackageManager.PERMISSION_DENIED) {
                    // permission was denied, show alert to explain permission
                    showPermissionAlert();
                }else{
                    //permission is granted. Get current location values
                    if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                            && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
                    }
                }
            }
        }
    }

    private void showPermissionAlert(){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.permission_request_title);
        builder.setMessage(R.string.app_permission_notice);
        builder.create();

        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if(!hasPermissions(EventActivity.this, PERMISSIONS)){
                    ActivityCompat.requestPermissions(EventActivity.this, PERMISSIONS, PERMISSION_ALL);
                }
            }
        });

        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(EventActivity.this, R.string.permission_refused, Toast.LENGTH_LONG).show();
            }
        });
        builder.show();
    }

    protected LocationRequest createLocationRequest() {
        LocationRequest mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(3000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        return mLocationRequest;
    }

    @Override
    protected void onStart() {
        mGoogleApiClient.connect();
        super.onStart();
    }

    @Override
    protected void onStop() {
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    @Override
    public void onConnectionSuspended(int i) {
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean isLocationEnabled(){
        LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }catch (Exception ex){}
        try{
            network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        }catch (Exception ex){}
        if(!gps_enabled && !network_enabled){
            return false;
        }
        return true;
    }

    private void showLocationAlert(){
        AlertDialog.Builder dialog = new AlertDialog.Builder(this);
        dialog.setMessage(getResources().getString(R.string.gps_enable));
        dialog.setPositiveButton(getResources().getString(R.string.network_location), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                EventActivity.this.startActivity(myIntent);
            }
        });
        dialog.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
            }
        });
        dialog.show();
    }

    private void moveFileToNewDestination(String fromPath, String toPath){
        File fromFile = new File(fromPath);
        File toFile = new File(toPath);
        if(!toFile.exists()){
            try {
                toFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        FileInputStream fromStream = null;
        FileOutputStream toStream = null;

        try {
            fromStream = new FileInputStream(fromFile);
            toStream = new FileOutputStream(toFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        byte[] sourceByte = new byte[1024];
        int index;
        try {
            while((index = fromStream.read(sourceByte)) > 0){
                if (toStream != null) {
                    toStream.write(sourceByte, 0, index);
                }
            }
            Log.d(TAG, "Video successfully moved to a new location");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getFileDestinationPath(String filename){
        String filePathEnvironment = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
        File directoryFolder = new File(filePathEnvironment + "/events/");
        if(!directoryFolder.exists()){
            directoryFolder.mkdir();
        }
        Log.d(TAG, "Full path " + filePathEnvironment + "/events/" + filename);
        return filePathEnvironment + "/events/" + filename;
    }

    private void uploadVideoToServer(String pathToVideoFile, String eventName, String eventDescription, String eventCoverage, String eventLocation){

        File videoFile = new File(pathToVideoFile);
        RequestBody videoBody = RequestBody.create(MediaType.parse("video/*"), videoFile);
        MultipartBody.Part vFile = MultipartBody.Part.createFormData("video", videoFile.getName(), videoBody);

        RequestBody event = RequestBody.create(MediaType.parse("text/plain"), eventName);
        RequestBody description = RequestBody.create(MediaType.parse("text/plain"), eventDescription);
        RequestBody name = RequestBody.create(MediaType.parse("text/plain"), eventCoverage);
        RequestBody location = RequestBody.create(MediaType.parse("text/plain"), eventLocation);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(SERVER_PATH)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        VideoInterface vInterface = retrofit.create(VideoInterface.class);
        Call<ResultObject> serverCom = vInterface.uploadVideoToServer(vFile, event, description, name, location);
        serverCom.enqueue(new Callback<ResultObject>() {
            @Override
            public void onResponse(Call<ResultObject> call, retrofit2.Response<ResultObject> response) {
                ResultObject result = response.body();
                if(!TextUtils.isEmpty(result.getSuccess()) && result.getSuccess().equals("1")){
                    Toast.makeText(EventActivity.this, getString(R.string.successful_upload), Toast.LENGTH_LONG).show();
                    resetViewControls();
                }else{
                    Toast.makeText(EventActivity.this, getString(R.string.server_error), Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call<ResultObject> call, Throwable t) {
                Log.d(TAG, "Error message " + t.getMessage());
            }
        });
    }

    private void showOptionDialog(){
        final Dialog dialog = new Dialog(EventActivity.this);
        dialog.setTitle("SELECT ACTION TO COMPLETE");
        dialog.setContentView(R.layout.image_video_layout);

        final TextView takePhoto = (TextView)dialog.findViewById(R.id.take_photo);
        final TextView recordVideo = (TextView)dialog.findViewById(R.id.record_video);

        dialog.show();

        takePhoto.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                Log.d(TAG, "Take a picture");
                if(isLocationEnabled()){
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(intent, TAKE_PICTURE);
                }else{
                    showLocationAlert();
                }
                dialog.dismiss();
            }
        });

        recordVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "Record a video");
                Intent videoCaptureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
                if(videoCaptureIntent.resolveActivity(getPackageManager()) != null){
                    startActivityForResult(videoCaptureIntent, REQUEST_VIDEO_CAPTURE);
                }
                dialog.dismiss();
            }
        });
    }

    private boolean gps_enabled;
    private boolean network_enabled;

标签: android

解决方案


推荐阅读