Aplikasi kamera yang berfungsi sederhana menghindari masalah niat nol
- semua kode yang diubah termasuk dalam balasan ini; dekat dengan tutorial android
Saya telah menghabiskan banyak waktu untuk masalah ini, jadi saya memutuskan untuk membuat akun dan membagikan hasil saya dengan Anda.
Tutorial android resmi "Mengambil Foto Secara Sederhana" ternyata tidak cukup sesuai dengan yang dijanjikan. Kode yang disediakan di sana tidak berfungsi pada perangkat saya: Samsung Galaxy S4 Mini GT-I9195 yang menjalankan Android versi 4.4.2 / KitKat / API Level 19.
Saya menemukan bahwa masalah utama adalah baris berikut dalam metode yang dipanggil saat mengambil foto ( dispatchTakePictureIntent
dalam tutorial):
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
Akibatnya niat kemudian ditangkap dengan onActivityResult
menjadi nol.
Untuk mengatasi masalah ini, saya menarik banyak inspirasi dari balasan sebelumnya di sini dan beberapa posting bermanfaat di github (sebagian besar yang ini oleh deepwinter - terima kasih besar kepadanya; Anda mungkin ingin memeriksa jawabannya di posting yang berkaitan erat juga).
Mengikuti saran yang menyenangkan ini, saya memilih strategi menghapus putExtra
garis yang disebutkan dan melakukan hal yang sesuai untuk mendapatkan kembali gambar yang diambil dari kamera dalam metode onActivityResult () sebagai gantinya. Baris-baris kode yang menentukan untuk mendapatkan kembali bitmap yang terkait dengan gambar adalah:
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
Saya membuat aplikasi contoh yang hanya memiliki kemampuan untuk mengambil gambar, menyimpannya di kartu SD dan menampilkannya. Saya pikir ini mungkin bermanfaat bagi orang-orang dalam situasi yang sama dengan saya ketika saya menemukan masalah ini, karena saran bantuan saat ini kebanyakan merujuk pada posting github yang agak luas yang melakukan hal tersebut tetapi tidak terlalu mudah untuk diawasi bagi pemula seperti saya. Sehubungan dengan sistem file yang dibuat Android Studio per default saat membuat proyek baru, saya hanya perlu mengubah tiga file untuk tujuan saya:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.simpleworkingcameraapp.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="takePicAndDisplayIt"
android:text="Take a pic and display it." />
<ImageView
android:id="@+id/image1"
android:layout_width="match_parent"
android:layout_height="200dp" />
</LinearLayout>
MainActivity.java:
package com.example.android.simpleworkingcameraapp;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.Image;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private ImageView image;
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image1);
}
// copied from the android development pages; just added a Toast to show the storage location
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
Toast.makeText(this, mCurrentPhotoPath, Toast.LENGTH_LONG).show();
return image;
}
public void takePicAndDisplayIt(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
}
}
@Override
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
if (requestCode == REQUEST_TAKE_PHOTO && resultcode == RESULT_OK) {
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
image.setImageBitmap(bitmap);
}
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.simpleworkingcameraapp">
<!--only added paragraph-->
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- only crucial line to add; for me it still worked without the other lines in this paragraph -->
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Perhatikan bahwa solusi yang saya temukan untuk masalah ini juga menyebabkan penyederhanaan file manifes android: perubahan yang disarankan oleh tutorial android dalam hal menambahkan penyedia tidak lagi diperlukan karena saya tidak menggunakan apapun dalam kode java saya. Oleh karena itu, hanya beberapa baris standar - terutama tentang izin - yang harus ditambahkan ke file manifes.
Mungkin juga bermanfaat untuk menunjukkan bahwa autoimport Android Studio mungkin tidak mampu menangani java.text.SimpleDateFormat
dan java.util.Date
. Saya harus mengimpor keduanya secara manual.