Android從系統(tǒng)調(diào)用相冊(cè)O(shè)kHttp上傳到服務(wù)器(activity數(shù)據(jù)傳遞)

Android從系統(tǒng)調(diào)用相冊(cè)O(shè)kHttp上傳到服務(wù)器(activity數(shù)據(jù)傳遞)

想寫技術(shù)博客已經(jīng)好久,今天終于下定決心堅(jiān)持一周一個(gè)小博客,我是一名安卓工程師,工作剛剛一個(gè)月,水平有限,此文章是結(jié)合郭霖大神的《第一行代碼》以及自己參考網(wǎng)絡(luò)大神上的一些參考代碼結(jié)合起來的,在自己項(xiàng)目中進(jìn)行調(diào)用,雖然有些雜亂,但是也算是基本的實(shí)現(xiàn)了功能。

下面先來展示一下功能截圖

功能展示1.jpg
功能展示2.jpg

功能流程相信各位也都能看懂,在第一個(gè)注冊(cè)信息完成后點(diǎn)擊下一步后繼續(xù)完成第二個(gè)頁面的注冊(cè)信息,然后將注冊(cè)信息上傳到服務(wù)器。

我也是第一次工作第一次自己進(jìn)行獨(dú)立開發(fā),所以可能會(huì)走不少?gòu)澛?,但是總算功能能夠?qū)崿F(xiàn)了。
下面來給大家展示一下代碼,我會(huì)著重將一些重要的代碼展示出來

牽扯到的知識(shí)點(diǎn)

  • Android調(diào)用系統(tǒng)相冊(cè)及相機(jī)(隱性intent)
  • ContentProvider
  • okHttp
  • popupWindow
  • Bundle

代碼講解

為了能夠更好的點(diǎn)擊btn彈出相機(jī)或者相冊(cè),我自定義了一個(gè)popupWindow,這個(gè)如果你不想寫,可以百度得到。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_margin="10dp"
        android:orientation="vertical"
        android:paddingBottom="10dp">

        <Button
            android:id="@+id/btn_pop_album"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:background="#ffff"
            android:text="本地相冊(cè)"
            android:textSize="18sp" />

        <Button
            android:id="@+id/btn_pop_camera"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:background="#ffff"
            android:text="相機(jī)拍攝"
            android:textSize="18sp" />

        <Button
            android:id="@+id/btn_pop_cancel"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_marginTop="10dp"
            android:background="#ffff"
            android:text="取消"
            android:textSize="18sp" />
    </LinearLayout>

</RelativeLayout>

>

點(diǎn)擊popupWindow調(diào)用相機(jī)或相冊(cè)


View popView = View.inflate(this, R.layout.popup_choose_pic, null);
        Button btnPopAlbum = (Button) popView.findViewById(R.id.btn_pop_album);
        Button btnPopCamera = (Button) popView.findViewById(R.id.btn_pop_camera);
        Button btnPopCancel = (Button) popView.findViewById(R.id.btn_pop_cancel);
        //獲取屏幕寬高
        int widthPixels = getResources().getDisplayMetrics().widthPixels;
        int heightPixels = getResources().getDisplayMetrics().heightPixels * 1 / 3;
        final PopupWindow popupWindow = new PopupWindow(popView, widthPixels, heightPixels);
        popupWindow.setAnimationStyle(R.style.anim_popup_dir);
        popupWindow.setFocusable(true);
        //點(diǎn)擊popup外部消失
        popupWindow.setOutsideTouchable(true);
        //消失時(shí)屏幕變?yōu)榘胪该?        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                WindowManager.LayoutParams params = getWindow().getAttributes();
                params.alpha = 1.0f;
                getWindow().setAttributes(params);
            }
        });
        //出現(xiàn)時(shí)屏幕變?yōu)橥该?        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.alpha = 0.5f;
        getWindow().setAttributes(params);
        popupWindow.showAtLocation(popView, Gravity.BOTTOM, 0, 50);
        btnPopAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
                //調(diào)用相機(jī)
                invokeAlbum();
            }
        });
        btnPopCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
                //打開相機(jī)
                openCarema();
            }
        });
        btnPopCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
            }
        });


可以直接拷貝到xml里面看預(yù)覽圖

下面我們就著重講解點(diǎn)擊頭像這個(gè)功能邏輯

其實(shí)對(duì)于調(diào)用相冊(cè)以及相機(jī)這幾個(gè)功能,許多的API我也不是特別了解,也不能詳細(xì)的跟大家解釋一下,在這里我將我拷貝這些代碼的時(shí)候遇到的坑跟大家說下-------功能摘自《第一行代碼第二版》相機(jī)相冊(cè)那個(gè)章節(jié)。

調(diào)用相冊(cè)

private void invokeAlbum() {
        //動(dòng)態(tài)申請(qǐng)危險(xiǎn)時(shí)權(quán)限,運(yùn)行時(shí)權(quán)限
        if (ContextCompat.checkSelfPermission(HgCompleteInfoActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
                PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(HgCompleteInfoActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        } else {
            openAlbum();
        }
    }
 private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, CHOOSE_PHOTO);
    }

在這里先進(jìn)行了動(dòng)態(tài)時(shí)權(quán)限,這是6.0之后支持的,具體的可以看郭霖的blog,目前著重實(shí)現(xiàn)功能

/**
     * 動(dòng)態(tài)獲取到的權(quán)限后的重寫
     *
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openAlbum();
                } else {
                    Toast.makeText(HgCompleteInfoActivity.this, "you denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }

這里是動(dòng)態(tài)獲取到權(quán)限后的重寫方法,如果不夠理解,可以想一下
app安裝時(shí)軟件介紹會(huì)解釋獲取哪些權(quán)限,那些權(quán)限是屬于manifests里注冊(cè)的,而動(dòng)態(tài)獲取權(quán)限時(shí),當(dāng)你第一次打開app時(shí),比如需要獲取你的地理位置,你點(diǎn)了拒絕,會(huì)彈出上面方法里面case1-->else邏輯。

  @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            
            case CHOOSE_PHOTO:
                if (resultCode == RESULT_OK) {
                    //判斷手機(jī)系統(tǒng)版本號(hào)
                    if (Build.VERSION.SDK_INT >= 19) {
                        handleImageOnKitKat(data);
                    } else {
                        handleImageBeforeKitKat(data);
                    }
                }
                break;
        }
    }
 private void handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri, null);
        displayImage(imagePath);
    }

    private void handleImageOnKitKat(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();
        //Log.i("uri", uri + "");
        if (DocumentsContract.isDocumentUri(HgCompleteInfoActivity.this, uri)) {
            //如果是document類型的uri,則通過document id 處理
            String docId = DocumentsContract.getDocumentId(uri);
            Log.i("type of document", docId);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];//解析出數(shù)字格式的id
                Log.i("type of document id", id);
                String selection = MediaStore.Images.Media._ID + "=" + id;
                Log.i("selection", selection);
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
            } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
                imagePath = getImagePath(contentUri, null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            //如果是content類型的uri,就用普通方式處理
            imagePath = getImagePath(uri, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            //如果是file類型的Uri,直接獲取圖片路徑
            imagePath = uri.getPath();
        }
        displayImage(imagePath);
    }
private String getImagePath(Uri uri, String selection) {
        String path = null;
        //通過uri和selection來獲取真實(shí)的圖片路徑
        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToNext()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cursor.close();
        }
        return path;
    }
 private void displayImage(String imagePath) {
        if (imagePath != null) {
            bitmap = BitmapFactory.decodeFile(imagePath);
            headFile = saveMyBitmap(bitmap, "head");
            //保存file到sp
            saveFile(headFile.getName());
            Glide.with(this).asBitmap().load(headFile).thumbnail(0.1f).into(civHead);
        } else {
            Toast.makeText(HgCompleteInfoActivity.this, "failed to get image ", Toast.LENGTH_SHORT).show();
        }
    }
//將bitmap轉(zhuǎn)化為png格式
    public File saveMyBitmap(Bitmap mBitmap, String prefix) {
        File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
        File file = null;
        try {
            file = File.createTempFile(
                    prefix,  /* prefix */
                    ".jpg",         /* suffix */
                    storageDir      /* directory */
            );
            FileOutputStream fos = new FileOutputStream(file);
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 10, fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }
    /**
     * 保存file到sp
     *
     * @param fileName
     */
    private void saveFile(String fileName) {
        SharedPreferences sp = getSharedPreferences("image", MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        edit.putString(HEAD_KEY, fileName);
        //提交edit
        edit.commit();
        Log.i(TAG, "saveFile: 保存成功" + sp.getString("head", null));
    }

這是阻擾我時(shí)間最多的邏輯部分,首先解釋一下這些代碼的邏輯

1.點(diǎn)擊獲取到的相冊(cè)顯示到我上圖中的CircleImageView(記得一定要壓縮,不然拍完照返回照片到ImageView會(huì)特別的慢,在這里我做的也不夠好,所以不展開講)
2.然后自己寫了兩個(gè)方法,savaFile和savaMyBitmap
3.在savaMyBitmap方法中,首先獲取了系統(tǒng)相冊(cè)的地址,然后每次我拍下照片或者選擇照片時(shí),都進(jìn)行簡(jiǎn)單的壓縮,因?yàn)閳D片要上傳到服務(wù)器進(jìn)行審核管理,做成微信頭像之類的超級(jí)壓縮方法有損畫質(zhì),所以我只是進(jìn)行了簡(jiǎn)單的壓縮上傳最后寫成一個(gè)文件。(在第二個(gè)頁面的時(shí)候可能會(huì)有幾個(gè)問題,三個(gè)ImageView即是三個(gè)bitmap,三個(gè)File文件。如何判斷及正確的顯示,我們可以定義成全局變量,因?yàn)槎际屈c(diǎn)擊事件,所以bitmap會(huì)在點(diǎn)擊后修改,然后保存下來。
4.在savaFile中,我靈機(jī)一動(dòng)(哈哈),想到了SharedPreferences這個(gè)神奇功能,我們沒有必要用sp去存file,因?yàn)闆]有那個(gè)方法,我們可以將名字存起來啊,edit.putString()中的HEAD_KEY就是我自己定的方法。你可以把sp當(dāng)成一個(gè)map,key是不會(huì)變的,但是value會(huì)變,所以理論上不管我們點(diǎn)多少次都會(huì)改變。
5.這樣文件就保存在本地了(可是不知道為啥我找不到,但是上傳到服務(wù)器里可以顯示)。

調(diào)用相機(jī)

private void openCarema() {
        //創(chuàng)建File對(duì)象,用于存儲(chǔ)拍照后的照片
        File outputImage = new File(getExternalCacheDir(), "output_image.jpg");
        if (outputImage.exists()) {
            outputImage.delete();
        }
        try {
            outputImage.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (Build.VERSION.SDK_INT >= 24) {
            imageUri = FileProvider.getUriForFile(HgCompleteInfoActivity.this, "com.qryl.qrylyh.activity.login.complete.fileprovider", outputImage);
        } else {
            imageUri = Uri.fromFile(outputImage);
        }
        //啟動(dòng)相機(jī)程序
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(intent, TAKE_PHOTO);
    }

這里不多贅述,調(diào)用Uri的邏輯功能代碼都是郭霖的,我是cv戰(zhàn)士。

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {
                    //將拍攝的圖片顯示出來
                    try {
                        bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                        headFile = saveMyBitmap(bitmap, "head");
                        //保存file到sp
                        saveFile(headFile.getName());
                        Glide.with(this).asBitmap().load(headFile).thumbnail(0.1f).into(civHead);
                        Log.i("wechat", "壓縮后圖片的大小" + ("字節(jié)碼:" + " 寬度為:" + bitmap.getWidth() + " 高度為:" + bitmap.getHeight()));
                        Log.i(TAG, "File:" + headFile.getName() + " 路徑:" + headFile.getAbsolutePath());
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
                  }
    }


和上面的方法基本都一樣。

使用Bundle以及SharedPreferences的理由

因?yàn)槲乙训谝豁摰臄?shù)據(jù)全部保存下來,全部在第二個(gè)頁面點(diǎn)擊注冊(cè)時(shí)一起上傳,這樣的話只是請(qǐng)求一次服務(wù)器,所以我想到了sp方法將文件名字存儲(chǔ)起來,在第二個(gè)頁面直接調(diào)用File方法把文件取出來即可
而Bundle只是為了區(qū)別分開,本來我是打開實(shí)現(xiàn)serializable的一個(gè)Map工具類集合進(jìn)行數(shù)據(jù)的傳遞,技術(shù)有限,老是異常,就想到了用File存儲(chǔ)的方法

其他注冊(cè)信息Bundle方法

  /**
     * 傳遞數(shù)據(jù)到下個(gè)頁面
     */
    private void putExtra() {
        Intent intent = new Intent(HgCompleteInfoActivity.this, CompletePicActivity.class);
        //傳遞數(shù)據(jù)
        Bundle bundle = new Bundle();
        //bundle.putByteArray("head", bytes);
        bundle.putString("name", ageDialogText);
        bundle.putString("identity", identityDialogText);
        bundle.putString("gender", genderDialogText);
        bundle.putString("age", ageDialogText);
        bundle.putString("workexperience", workExperienceDialogText);
        bundle.putString("begoodat", beGoodAtWorkDialogText);
        bundle.putString("localservice", null);
        intent.putExtras(bundle);
        startActivity(intent);
    }


@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_complete_pic);
        initView();

        Bundle bundle = getIntent().getExtras();

        String name = (String) bundle.get("name");
        String indentity = (String) bundle.get("identity");
        String gender = (String) bundle.get("gender");
        String age = (String) bundle.get("age");
        String workexperience = (String) bundle.get("workexperience");
        String begoodat = (String) bundle.get("begoodat");
        String localservice = (String) bundle.get("localservice");

        //dataMap.put("head", head.toString());
        dataMap.put("name", name);
        dataMap.put("indentity", indentity);
        dataMap.put("gender", gender);
        dataMap.put("age", age);
        dataMap.put("workexperience", workexperience);
        dataMap.put("begoodat", begoodat);
        dataMap.put("localservice", localservice);

    }

這沒啥好說的,第二個(gè)頁面直接取出來,我為了以后后期方便維護(hù),定義了一個(gè)HashMap,如果沒有此需求可以直接取出來當(dāng)成全局變量進(jìn)行調(diào)用即可。

調(diào)用圖片上傳的拓展

不知道大家是不是還記得第二個(gè)頁面有三個(gè)上傳照片的圖片,在剛才我也提過,如何在正確的相框中實(shí)現(xiàn)正確的圖片,是一個(gè)不難但是挺啰嗦的事情

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case TAKE_PHOTO:
                if (resultCode == RESULT_OK) {
                    //將拍攝的圖片顯示出來
                    try {
                        bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                        if (choosed_image == R.id.sfz_image) {//身份證
                            //保存file到sp
                            sfzFile = saveMyBitmap(bitmap, "sfz");
                            saveFile(SFZ_KEY, sfzFile.getName());
                            Glide.with(this).asBitmap().load(sfzFile).thumbnail(0.1f).into(sfzImage);
                        } else if (choosed_image == R.id.jkz_image) {//健康證
                            jkzFile = saveMyBitmap(bitmap, "jkz");
                            //保存file到sp
                            saveFile(JKZ_KEY, jkzFile.getName());
                            Glide.with(this).asBitmap().load(jkzFile).thumbnail(0.1f).into(jkzImage);
                        } else if (choosed_image == R.id.zgz_image) {//從業(yè)資格證
                            zgzFile = saveMyBitmap(bitmap, "zgz");
                            //保存file到sp
                            saveFile(ZGZ_KEY, zgzFile.getName());
                            Glide.with(this).asBitmap().load(zgzFile).thumbnail(0.1f).into(zgzImage);
                        }
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case CHOOSE_PHOTO:
                if (resultCode == RESULT_OK) {
                    //判斷手機(jī)系統(tǒng)版本號(hào)
                    if (Build.VERSION.SDK_INT >= 19) {
                        handleImageOnKitKat(data);
                    } else {
                        handleImageBeforeKitKat(data);
                    }
                }
                break;
        }
    }

這些代碼看著很繁瑣,其實(shí)東西沒多少,只是比上面的邏輯多了個(gè)if,在這里我定義了一個(gè)全局的int變量,將三個(gè)相冊(cè)區(qū)別開來,R.id.sfz_image就是一個(gè)int值不是嗎。這樣看起來更加具像化,最好不用數(shù)字區(qū)分開。savaFile一樣。

這樣基本的上傳照片基本完成,我們可以點(diǎn)擊注冊(cè)把數(shù)據(jù)整合起來直接上傳到服務(wù)器了,在這里我用了okHttp框架

在第一行代碼里,okHttp只是簡(jiǎn)單的展示了一下方法,大家可以百度一下各種okHttp方法,因?yàn)槲覀冞@個(gè)項(xiàng)目,定的統(tǒng)一是post請(qǐng)求,而且因?yàn)閿?shù)據(jù)類型可能不同(File,String,int),所以我經(jīng)過半天的不懈努力,看到了一個(gè)nb的API:addFormDataPart()

 /**
     * 向服務(wù)器發(fā)送請(qǐng)求
     */
    private void postData() {
        SharedPreferences pref = getSharedPreferences("image", Context.MODE_PRIVATE);
        String headImage = pref.getString(HEAD_KEY, null);
        String sfzImage = pref.getString(SFZ_KEY, null);
        String jkzImage = pref.getString(JKZ_KEY, null);
        String zgzName = pref.getString(ZGZ_KEY, null);
        //Log.i(TAG, "postData: 頭像圖片名字" + imageName);
        OkHttpClient client = new OkHttpClient();
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
        File headFile = new File(storageDir, headImage);
        File sfzFile = new File(storageDir, sfzImage);
        File jkzFile = new File(storageDir, jkzImage);
        File zgzFile = new File(storageDir, zgzName);
        if (headFile != null) {
            // MediaType.parse() 里面是上傳的文件類型。
            RequestBody body = RequestBody.create(MediaType.parse("image/*"), headFile);
            // 參數(shù)分別為, 請(qǐng)求key ,文件名稱 , RequestBody
            builder.addFormDataPart("txImg", headFile.getName(), body);
        }
        if (sfzFile != null) {
            // MediaType.parse() 里面是上傳的文件類型。
            RequestBody body = RequestBody.create(MediaType.parse("image/*"), sfzFile);
            // 參數(shù)分別為, 請(qǐng)求key ,文件名稱 , RequestBody
            builder.addFormDataPart("sfzImg", sfzFile.getName(), body);
        }
        if (jkzFile != null) {
            // MediaType.parse() 里面是上傳的文件類型。
            RequestBody body = RequestBody.create(MediaType.parse("image/*"), jkzFile);
            // 參數(shù)分別為, 請(qǐng)求key ,文件名稱 , RequestBody
            builder.addFormDataPart("jkzImg", jkzFile.getName(), body);
        }
        if (zgzFile != null) {
            // MediaType.parse() 里面是上傳的文件類型。
            RequestBody body = RequestBody.create(MediaType.parse("image/*"), zgzFile);
            // 參數(shù)分別為, 請(qǐng)求key ,文件名稱 , RequestBody
            builder.addFormDataPart("zgzImg", zgzFile.getName(), body);
        }
        builder.addFormDataPart("loginId", "1");
        //builder.add("sfzImg", "1");
        //builder.add("zgzImg", "1");
        //builder.add("jkzImg", "1");
        builder.addFormDataPart("realName", "sdfdf");
        builder.addFormDataPart("gender", "0");
        builder.addFormDataPart("age", "10");
        builder.addFormDataPart("workYears", "10");
        builder.addFormDataPart("introduce", "sdfsdfsf");
        MultipartBody requestBody = builder.build();
        Request request = new Request.Builder().url("服務(wù)器地址").post(requestBody).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "onFailure: 失敗");
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.i(TAG, "onResponse: 成功 " + response.body().string());
            }
        });
    }

可以忽略那些沒用的提取數(shù)據(jù)代碼

寫到后面也比較懶了,因?yàn)槭侵苣?,晚上還有極限挑戰(zhàn)哈哈,所以要抓緊
在這client的回調(diào)我覺得用過okHttp的人都能看懂,重要的newCall方法里面的參數(shù),在這里我是用MultipartBody類,大家可以看上面那一段代碼的第12行開始

MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

這段代碼是定義的這是上傳的表單類型

RequestBody body = RequestBody.create(MediaType.parse("image/*"), headFile);
            // 參數(shù)分別為, 請(qǐng)求key ,文件名稱 , RequestBody
            builder.addFormDataPart("txImg", headFile.getName(), body);

image/*是因?yàn)?,我的圖片文件是.jpg格式。
在這里,我打了詳細(xì)的注釋,幫助大家也幫助自己理解。這樣,我們?cè)趦蓚€(gè)頁面進(jìn)行實(shí)現(xiàn)注冊(cè)頁面,用了一次請(qǐng)求就將數(shù)據(jù)上傳到了服務(wù)器。其實(shí)上傳的方式有很多種,用流的方式上傳圖片也是可以的。

第一次博客,因?yàn)樽约罕旧硎且粋€(gè)剛工作一個(gè)月的菜鳥,自己一個(gè)人搞安卓端的開發(fā),也算是獨(dú)立開發(fā)了。所以要多走不少?gòu)澛罚瑢?shí)現(xiàn)一個(gè)功能可能會(huì)麻煩不少。希望以后好好做一個(gè)cv戰(zhàn)士。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,486評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,600評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,108評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,652評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,385評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,616評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,798評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評(píng)論 1 295
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,334評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,570評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,745評(píng)論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,176評(píng)論 4 61
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,828評(píng)論 18 139
  • 我是他第一百個(gè)新娘,他很誠(chéng)實(shí)地告訴我。 “之前的女孩兒們都怎么了?” “那時(shí)候我還不成熟,也有遇到不合適的,就都離...
    沉芙閱讀 829評(píng)論 2 2
  • 麥肯錫前顧問大島祥譽(yù)寫的一本小冊(cè)子,把該作者在麥肯錫公司工作期間的一些方法、習(xí)慣匯集起來,一共有39點(diǎn)。通讀...
    讀書做更好的自己閱讀 732評(píng)論 0 0