【发布时间】:2015-07-15 14:00:53
【问题描述】:
我是 Android 开发新手。我创建了我的第一个应用程序,它是一个能够捕获图像、向用户查询与图像相关的汽车 ID、预览捕获的图像并将该图像上传到服务器的相机。
我有兴趣从可能的多个图像中随机发送一个图像,例如从图像目录到服务器。我不想向服务器发送多张图片——只是一张随机图片。
在对本网站以及许多其他网站进行大量研究后,我确定了以下内容:我必须获取捕获图像上传到的图像目录,我必须使用随机功能从所述目录中随机选择一张图像Android,我必须根据图片的文件uri设置图片位图,并且必须通过base64编码将位图转换为blob数据类型。
我执行了上述操作,但我的位图返回为 null,因为我收到消息“请选择图像”,这是该实例的 toast 消息。
这是我的代码:
public class MainActivity extends Activity {
// Activity request codes.
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
public static final int MEDIA_TYPE_IMAGE = 1;
Bitmap bitmap;
ProgressDialog pd;
InputStream is;
//Directory name to store captured images.
private static final String IMAGE_DIRECTORY_NAME = "Hello Camera";
private Uri fileUri; //File url to store captured images.
private ImageView imgPreview;
private Button btnCapturePicture;
private Button upload;
Button mButton;
EditText mEdit;
/* Initializes activity, defines UI layout, and retrieves widgets
* to interact with.
* @param savedInstanceState - data is caught here and saved for
* future app use.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button)findViewById(R.id.button);
mEdit = (EditText)findViewById(R.id.edittext);
mButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Log.v("EditText", mEdit.getText().toString());
}
});
imgPreview = (ImageView) findViewById(R.id.imgPreview);
btnCapturePicture = (Button) findViewById(R.id.btnCapturePicture);
upload = (Button) findViewById(R.id.upload);
upload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (bitmap == null) {
Toast.makeText(getApplicationContext(), "Please Select Image", Toast.LENGTH_LONG).show();
} else {
new ImageUpload().execute();
}
}
});
/**
* Captures image button click event in order to capture a photo.
* @param new View.OnClickListener- call to constructor
*/
btnCapturePicture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Captures an image.
captureImage();
}
});
//Checks for camera availability.
if (!isDeviceSupportCamera()) {
Toast.makeText(getApplicationContext(),
"Sorry! Your device doesn't support camera", Toast.LENGTH_LONG).show();
//Closes if a camera is not available on the device.
finish();
}
}
/**
* Checks if device has camera hardware.
*
* @return - true or false.
*/
private boolean isDeviceSupportCamera() {
if (getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
//Device has a camera.
return true;
} else {
// Device does not have a camera.
return false;
}
}
/*
* Launches camera app request image capture.
*/
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
//Starts the image capture Intent.
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
/**
* Gets and stores the file url. Will be null after returning from camera
* app.
*
* @param outState - Holds per-instance state from activity.
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Saves the file url in bundle. It will be null on screen orientation changes.
outState.putParcelable("file_uri", fileUri);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//Gets the file url.
fileUri = savedInstanceState.getParcelable("file_uri");
}
/**
* Receives activity result method. Will be called after closing the camera.
*
* @param requestCode - Requests to capture an image.
* @param resultCode - Based on success or failure of image capturing, shows
* an image preview or one of two error messages.
* @param data - Carries the result data(successfully captured image).
* @return - An image preview, or one of two error messages.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//If the result is the image capturing event,
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
//the image was successfully captured
// and will be displayed in the preview.
previewCapturedImage();
} else if (resultCode == RESULT_CANCELED) {
//The user cancelled the image capturing.
Toast.makeText(getApplicationContext(),
"User cancelled image capture", Toast.LENGTH_SHORT).show();
} else {
//Image capturing failed, but the user did not actually cancel it.
Toast.makeText(getApplicationContext(),
"Sorry! Failed to capture image", Toast.LENGTH_SHORT).show();
}
}
}
/**
* Displays the image from a path to ImageView.
* Downsizes an image if necessary and throws exception
* if the image is too large.
*/
private void previewCapturedImage() {
try {
imgPreview.setVisibility(View.VISIBLE);
upload.setVisibility(View.VISIBLE);
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
Log.v("Directory", mediaStorageDir.toString());
mediaStorageDir.listFiles(new FileFilter() {
public boolean accept(File file) {
return !file.isDirectory();
}
});
File[] listFiles = mediaStorageDir.listFiles();
Log.v("File listFiles", listFiles.toString());
Random r = new Random ();
Log.v("Random r", r.toString());
File randomPicture = listFiles[r.nextInt(listFiles.length)];
Log.v("Random Picture File", randomPicture.toString());
Uri pictureUri = Uri.fromFile(randomPicture);
Log.v("PictureUri", pictureUri.toString());
BitmapFactory.Options options = new BitmapFactory.Options();
// Downsizes images. Will throw OutOfMemory Exception for larger images.
options.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeFile(pictureUri.getPath(), options);
Log.v("Bitmap", bitmap.toString());
ImageView imgView = (ImageView) findViewById(R.id.imgPreview);
Log.v("ImgView", imgView.toString());
imgView.setImageBitmap(bitmap);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
/**
* Creates the file uri to store an image.
*
* @param type - Refers to the captured image.
* @return Uri.fromFile - The file uri to store an image.
*/
public Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/**
* Returns the captured image.
*
* @param type - Refers to the captured image.
* @return null or mediaFile - mediaFile: Captured
* image inside of timestamped file.
*/
private static File getOutputMediaFile(int type) {
// External sdcard location.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
Log.v("Directory Two", mediaStorageDir.toString());
// Create the storage directory if it does not exists
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create " + IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Creates a media file name corresponding to a timestamp.
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
/*
* Uploads the saved and captured image to the server.
*/
public class ImageUpload extends AsyncTask<String, String,String> {
String postUrl = "";
public void postURL(String url) {
postUrl = url;
}
/**
* Compresses the selected gallery image and encodes
* compressed image to a base64 string.
*
* @param params
*/
@Override
protected String doInBackground(String... params) {
String result = null;
try {
HttpClient client = new DefaultHttpClient();
String postURL = "";
HttpPost post = new HttpPost("http://IP here/files/justine/image_save.php");
ArrayList<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();
String msg = mEdit.getText().toString();
nameValuePair.add(new BasicNameValuePair("carid",msg));
//Converts image file uri to blob base64
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] byte_arr = stream.toByteArray();
String image_str = new String(Base64.encode(byte_arr, Base64.DEFAULT));
nameValuePair.add(new BasicNameValuePair("carimage", image_str));
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(nameValuePair, HTTP.UTF_8);
post.setEntity(ent);
HttpResponse responsePOST = client.execute(post);
HttpEntity resEntity = responsePOST.getEntity();
result = EntityUtils.toString(resEntity);
if (resEntity != null) {
Log.i("RESPONSE", EntityUtils.toString(resEntity));
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(getApplicationContext(),
"Successfully uploaded", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
"Sorry! Failed to upload", Toast.LENGTH_SHORT).show();
}
}
}
}
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.justin.myapplication" >
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="22" />
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:anyDensity="true">
</supports-screens>
<!-- Accessing camera hardware -->
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.screen.portrait" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboard|keyboardHidden"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Logcat:
07-15 13:34:52.998 22775-22775/? D/dalvikvm﹕ Late-enabling CheckJNI
07-15 13:34:53.154 22775-22775/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
07-15 13:34:53.162 22775-22775/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
07-15 13:34:53.170 22775-22775/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
07-15 13:34:53.256 22775-22775/com.example.justin.myapplication D/OpenGLRenderer﹕ Enabling debug mode 0
07-15 13:35:08.795 22775-22775/com.example.justin.myapplication V/EditText﹕ 77869548059
07-15 13:35:10.779 22775-22775/com.example.justin.myapplication V/Directory Two﹕ /storage/emulated/0/Pictures/Hello Camera
07-15 13:35:11.490 22775-22775/com.example.justin.myapplication W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
07-15 13:35:18.350 22775-22775/com.example.justin.myapplication V/Directory﹕ /storage/emulated/0/Pictures/Hello Camera
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/File listFiles﹕ [Ljava.io.File;@427723e8
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/Random r﹕ java.util.Random@4277d730
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/Random Picture File﹕ /storage/emulated/0/Pictures/Hello Camera/IMG_20150713_143026.jpg
07-15 13:35:18.412 22775-22775/com.example.justin.myapplication V/PictureUri﹕ file:///storage/emulated/0/Pictures/Hello%20Camera/IMG_20150713_143026.jpg
07-15 13:35:18.443 22775-22775/com.example.justin.myapplication D/dalvikvm﹕ GC_FOR_ALLOC freed 207K, 3% free 8778K/9024K, paused 19ms, total 21ms
07-15 13:35:18.443 22775-22775/com.example.justin.myapplication I/dalvikvm-heap﹕ Grow heap (frag case) to 8.897MB for 314944-byte allocation
07-15 13:35:18.459 22775-22784/com.example.justin.myapplication D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 3% free 9079K/9332K, paused 18ms, total 18ms
07-15 13:35:18.607 22775-22775/com.example.justin.myapplication V/Bitmap﹕ android.graphics.Bitmap@4275f650
07-15 13:35:18.607 22775-22775/com.example.justin.myapplication V/ImgView﹕ android.widget.ImageView{42748e50 V.ED.... ......I. 0,0-0,0 #7f0c0051 app:id/imgPreview}
我对位图返回 null 的原因感到困惑。我很感激任何关于原因的见解以及关于如何改进我当前代码以实现我感兴趣的目标的任何建议。非常感谢。
【问题讨论】:
-
读取错误。这个文件
Is a directory -
我猜
mediaStorageDir.listFiles()会返回目录和文件。 -
另一件事。您在
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_DIRECTORY_NAME);中创建图像,但您直接在Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);中查找它们。你需要在你寻找它们的地方寻找你的图像。 -
这两个目录不同。您在
/storage/emulated/0/Pictures/Hello Camera中创建了一个文件,但随后您列出了/storage/emulated/0/Pictures的内容。 -
请不要破坏您的帖子;这对那些试图帮助你的人是不公平的,而且你剥夺了未来的访问者从同一个帖子中获得帮助的机会。
标签: java android random bitmap android-camera