作为一个玩Android的新手,之前一直在玩有关UI的东西,很少接触后端,昨天网上帮同学完成一个项目,要求实现手机调用摄像头拍照,然后预览照片最后还要讲图片上传到服务端。于是就找到了这样一个github上的文档
上传拍下的照片、视频到服务器
这个文档写的非常的清楚,代码也有,不过我这里还是想写点我的分析。
Config这个类,这个类用于保存文件上传所送到的 URL 地址,还有在移动设备中存储图片/视频的目录名称。你可能需要在测试 App 时使用你自己的 URL 地址进行上传操作。上面的链接没有给出Config 的代码,其实也不需要给出 因为这里你只需要设置你上传文件的URL的地址就好了。这里我贴出自己的代码。
public static final String FILE_UPLOAD_URL = "http://XXXXXXXXX/fileUpload.php"; // Directory name to store captured images and videos
public static final String IMAGE_DIRECTORY_NAME = "Android File Upload";
FILE_UPLOAD_URL就是你连接后端服务器用的,我这里用的是php,别的行不行我就不知道了,理论上是没问题。
AndroidMultiPartEntity这个类我也没有认真的去分析它,就知道它在进度条的进度增量上有用到。
后面就是MainActivity这个类了,这个类的界面很简单按钮一个就行(因为这里我只需要拍照不需要录像),这里我也把我的代码贴上,虽然没多大区别。
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
private static final int MEDIA_TYPE_IMAGE = 1;
private Uri fileUri;
private Button btn_take,btn_load;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_take = (Button) findViewById(R.id.btn_take);
btn_load= (Button) findViewById(R.id.btn_load);
btn_take.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
takephoto();
}
});
if(!isDeviceSupportCamera()){
Toast.makeText(getApplicationContext(), "Sorry! Your device doesn't support camera", Toast.LENGTH_LONG).show();
finish();
}
}
//检查设备是否有摄像机
private boolean isDeviceSupportCamera() {
if (getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
private void takephoto(){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
public Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// if the result is capturing Image
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// successfully captured the image
// launching upload activity
Log.e(TAG, "I have finish it");
launchUploadActivity(true);
} else if (resultCode == RESULT_CANCELED) {
// user cancelled Image capture
Toast.makeText(getApplicationContext(),
"User cancelled image capture", Toast.LENGTH_SHORT)
.show();
} else {
// failed to capture image
Toast.makeText(getApplicationContext(),
"Sorry! Failed to capture image", Toast.LENGTH_SHORT)
.show();
}
} else {
// failed to record video
Toast.makeText(getApplicationContext(),
"Sorry! Failed to record video", Toast.LENGTH_SHORT)
.show();
}
}
private void launchUploadActivity(boolean isImage){
Intent i = new Intent(MainActivity.this, UpLoadActivity.class);
i.putExtra("filePath", fileUri.getPath());
i.putExtra("isImage", isImage);
startActivity(i);
Log.e(TAG, "Did i have finish");
}
private static File getOutputMediaFile(int type) {
// External sdcard location
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
Config.IMAGE_DIRECTORY_NAME);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(TAG, "Oops! Failed create "
+ Config.IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Create a media file name
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;
}
}
点击按钮即调用takephoto()这个函数,这个函数就是请求手机调用摄像头的。当然别忘记在AndroidManifest.xml 中添加相应的权限 。
拍照确定 保存该照片后,程序直接跳转到UploadAcitvity
因为我们在调用摄像头的时候使用的是startActivityForResult这个函数,这个函数是在你调用摄像头这个Activity完成后去执行onActivityResult()这个函数,然后根据requestCode和resultCode两个参数决定实现某种功能,在这里若拍照成功,则返回RESULT_OK然后跳转到UploadAcitivity中去。这里我在学习下是怎么保存image的。
我们可以看到takephoto()种有一个变量fileUri,从变量名就看得出是image的路径。好,接下来就是getOutputMediaFileUri和getOutputMediaFile,getOutputMediaFileUri()函数中就只有一句代码,主要就是fromFile这个函数,这个函数的作用呢是从文件中创建一个URI。该URI的形式是“文件://”。除’/’编码路径的字符。那么getOutputMediaFile这个函数肯定是将图片以及图片的信息放到保存起来作为一个文件。
好的,最后我们进入UploadAcitvity中去,我们可以在launchUploadActivity()这个函数中看到,在我们调用UploadAcitvity时还给她传了两个参数,一个是fileUri(图片的路径),一个是isImage(判断它是否是图片)。
package com.qingfeng.imageload;
import com.qingfeng.imageload.AndroidMultiPartEntity.ProgressListener;
import java.io.File;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
public class UploadActivity extends Activity {
// LogCat tag
private static final String TAG = MainActivity.class.getSimpleName();
private ProgressBar progressBar;
private String filePath = null;
private TextView txtPercentage;
private ImageView imgPreview;
private VideoView vidPreview;
private Button btnUpload;
long totalSize = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload);
txtPercentage = (TextView) findViewById(R.id.txtPercentage);
btnUpload = (Button) findViewById(R.id.btnUpload);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
imgPreview = (ImageView) findViewById(R.id.imgPreview);
vidPreview = (VideoView) findViewById(R.id.videoPreview);
// Changing action bar background color
getActionBar().setBackgroundDrawable(
new ColorDrawable(Color.parseColor(getResources().getString(
R.color.action_bar))));
// Receiving the data from previous activity
Intent i = getIntent();
// image or video path that is captured in previous activity
filePath = i.getStringExtra("filePath");
// boolean flag to identify the media type, image or video
boolean isImage = i.getBooleanExtra("isImage", true);
if (filePath != null) {
// Displaying the image or video on the screen
previewMedia(isImage);
} else {
Toast.makeText(getApplicationContext(),
"Sorry, file path is missing!", Toast.LENGTH_LONG).show();
}
btnUpload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// uploading the file to server
new UploadFileToServer().execute();
}
});
}
/**
* Displaying captured image/video on the screen
* */
private void previewMedia(boolean isImage) {
// Checking whether captured media is image or video
if (isImage) {
imgPreview.setVisibility(View.VISIBLE);
vidPreview.setVisibility(View.GONE);
// bimatp factory
BitmapFactory.Options options = new BitmapFactory.Options();
// down sizing image as it throws OutOfMemory Exception for larger
// images
options.inSampleSize = 8;
final Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
imgPreview.setImageBitmap(bitmap);
} else {
imgPreview.setVisibility(View.GONE);
vidPreview.setVisibility(View.VISIBLE);
vidPreview.setVideoPath(filePath);
// start playing
vidPreview.start();
}
}
/**
* Uploading the file to server
* */
private class UploadFileToServer extends AsyncTask<Void, Integer, String> {
@Override
protected void onPreExecute() {
// setting progress bar to zero
progressBar.setProgress(0);
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... progress) {
// Making progress bar visible
progressBar.setVisibility(View.VISIBLE);
// updating progress bar value
progressBar.setProgress(progress[0]);
// updating percentage value
txtPercentage.setText(String.valueOf(progress[0]) + "%");
}
@Override
protected String doInBackground(Void... params) {
return uploadFile();
}
@SuppressWarnings("deprecation")
private String uploadFile() {
String responseString = null;
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Config.FILE_UPLOAD_URL);
try {
AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
new ProgressListener() {
@Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
File sourceFile = new File(filePath);
// Adding file data to http body
entity.addPart("image", new FileBody(sourceFile));
// Extra parameters if you want to pass to server
entity.addPart("website",
new StringBody("www.android.com"));
entity.addPart("email", new StringBody("promisesaybye@gmail.com"));
totalSize = entity.getContentLength();
httppost.setEntity(entity);
// Making server call
HttpResponse response = httpclient.execute(httppost);
HttpEntity r_entity = response.getEntity();
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
// Server response
responseString = EntityUtils.toString(r_entity);
} else {
responseString = "Error occurred! Http Status Code: "
+ statusCode;
}
} catch (ClientProtocolException e) {
responseString = e.toString();
} catch (IOException e) {
responseString = e.toString();
}
return responseString;
}
@Override
protected void onPostExecute(String result) {
Log.e(TAG, "Response from server: " + result);
// showing the server response in an alert dialog
showAlert(result);
super.onPostExecute(result);
}
}
/**
* Method to show alert dialog
* */
private void showAlert(String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message).setTitle("Response from Servers")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// do nothing
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
上面是有关UploadActivity的代码。最重要的肯定是上传到服务器的编写了—-UploadFileToServer()里面的doInBackground()这个函数中的uploadFile。里面有个addPart我去官网搜都没搜到,若有大神知道还望指点~