在做一個商城,第一個版本使用的OkHttp3來進行網路操作的,現在把第一個版本推倒重新做了個版本,於是就用上了正在如火如荼的Retrofit+RxJava來實現網路操作。在上傳圖片作為頭像時實現了一個上午也沒搞定,現在終於有時間再重新搞一下了。於是把使用OkHttp3上傳和Retrofit+RxJava上傳都總結了一下。
PS:圖片的獲取在不同版本上面可能會出現問題,不過這不是本文重點,主要是想展示一下上傳圖片時OkHttp3和Retrofit的引數問題。
申請許可權
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
複製程式碼
獲取照片
準備請求碼和臨時變數名
private static final int PHOTO_REQUEST_CAREMA = 1;// 拍照 private static final int PHOTO_REQUEST_GALLERY = 2;// 從相簿中選擇 private static final int PHOTO_REQUEST_CUT = 3;// 裁剪之後 private static final String PHOTO_FILE_NAME = "temp_photo.jpg";//臨時檔名 private File tempFile; 複製程式碼
開啟相簿獲取照片
public void gallery() { Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, PHOTO_REQUEST_GALLERY);//攜帶請求碼 } 複製程式碼
開啟相機獲取照片
public void camera() { Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); if (hasSdcard()) {// 判斷儲存卡是否可以用,可用進行儲存 tempFile = new File(Environment.getExternalStorageDirectory(), PHOTO_FILE_NAME); Uri uri = Uri.fromFile(tempFile); // 從檔案中建立uri intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } startActivityForResult(intent, PHOTO_REQUEST_CAREMA);//攜帶請求碼 } 複製程式碼
裁剪圖片
private void crop(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); // 裁剪框的比例,1:1 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // 裁剪後輸出圖片的尺寸大小 intent.putExtra("outputX", 250); intent.putExtra("outputY", 250); intent.putExtra("outputFormat", "JPEG");// 圖片格式 intent.putExtra("noFaceDetection", true);// 取消人臉識別 intent.putExtra("return-data", true); startActivityForResult(intent, PHOTO_REQUEST_CUT); // 開啟一個帶有返回值的Activity,請求碼為PHOTO_REQUEST_CUT }複製程式碼
判斷是否掛在了SD卡
private boolean hasSdcard() { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { return true; } else { return false; } }複製程式碼
獲取的是external資料庫對應的Image檔案
private Uri external(String external) { String myImageUrl = "content://media" + external; Uri uri = Uri.parse(myImageUrl); String[] proj = {MediaStore.Images.Media.DATA}; Cursor actualimagecursor = this.managedQuery(uri, proj, null, null, null); int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); actualimagecursor.moveToFirst(); String img_path = actualimagecursor.getString(actual_image_column_index); File file = new File(img_path); Uri fileUri = Uri.fromFile(file); return fileUri; }複製程式碼
在回撥中取圖片
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PHOTO_REQUEST_GALLERY) { // 從相簿返回的資料 if (data != null) {// 得到圖片的全路徑 Uri uri = data.getData(); crop(uri); } } else if (requestCode == PHOTO_REQUEST_CAREMA) {//從相機返回的資料 if (hasSdcard()) { crop(Uri.fromFile(tempFile)); } else { Toast.makeText(MainActivity.this, "未找到儲存卡,無法儲存照片!", Toast.LENGTH_LONG).show(); } } else if (requestCode == PHOTO_REQUEST_CUT) {//從剪下圖片返回的資料 if (data != null) { Bitmap bitmap = data.getParcelableExtra("data"); //將bitmap轉換為Uri Uri uri = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, null, null)); //對非正確的Uri處理,這類Uri存在手機的external.db中,可以查詢_data欄位查出對應檔案的uri if (uri.getPath().contains("external")) { uri = external(uri.getPath()); } //在這可以拿到裁剪後的圖片Uri,然後進行你想要的操作 upLoad2Server(uri); } try { tempFile.delete();//將臨時檔案刪除 } catch (Exception e) { e.printStackTrace(); } } super.onActivityResult(requestCode, resultCode, data); }複製程式碼
進行上傳操作(2種方法)
1.使用OkHttp3來上傳
1. 新增依賴:
compile 'com.squareup.okhttp3:okhttp:3.3.0'
2. 上傳程式碼如下:
private void upLoad2Server(Uri uri) {
File file = null;
try {
file = new File(new URI(uri.toString()));
} catch (URISyntaxException e) {
e.printStackTrace();
}
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
if (file != null) {
builder.addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse
("image*//*"), file));
}
MultipartBody requestBody = builder.build();
Request request = new Request.Builder()
.url("你的上傳介面")
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient.Builder().connectTimeout(10000, TimeUnit.SECONDS).readTimeout(10000, TimeUnit.SECONDS).writeTimeout(10000, TimeUnit.SECONDS).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
})
}複製程式碼
2.使用Retrofit+RxJava來上傳
1.新增依賴
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'io.reactivex:rxjava:1.2.4'
compile 'io.reactivex:rxandroid:1.2.1'
2.準備上傳介面
@Multipart
@POST("你的介面")
Observable<ResponseBody> upload(@Part MultipartBody.Part imgs);
public class NetApi {
public static final String BASE_URL = "你的域名";
private static NetApi mNetApi;
private static Retrofit retrofit;
private static NetService mNetService;
private NetApi() {
}
public static NetApi getInstance() {
if (null == mNetApi) {
mNetApi = new NetApi();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
mNetService = retrofit.create(NetService.class);
}
return mNetApi;
}
public void upload(Subscriber<ResponseBody> subscriber, MultipartBody.Part imgs) {
mNetService.upload(imgs)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
}
3.上傳方法如下:
private void upLoad2Server(Uri uri) {
File file = null;
try {
file = new File(new URI(uri.toString()));
} catch (URISyntaxException e) {
e.printStackTrace();
}
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestBody);
NetApi.getInstance().upload(new Subscriber<ResponseBody>() {
@Override
public void onCompleted() {
Log.e("MainActivity", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity", "onError,"+e.getMessage());
}
@Override
public void onNext(ResponseBody responseBody) {
try {
Log.e("MainActivity", "onNext,=" + responseBody.string());
} catch (IOException e) {
e.printStackTrace();
}
}
}, body);
}複製程式碼