android頭像上傳(獲取頭像加剪切)

来源:http://www.cnblogs.com/wangfengdange/archive/2017/08/28/7443389.html
-Advertisement-
Play Games

因為項目中需要用到頭像上傳的功能,所以就下個Ddmo先來實現下。 demo我是類似仿微信的,在一個GridView中展示所有的圖片,其中第一個item可以去照相;獲取到圖片後再進行剪切。 圖片的剪切是從網上找的感覺不錯就用,暫時也沒有測試。 獲取圖片可以用:https://github.com/lo ...


因為項目中需要用到頭像上傳的功能,所以就下個Ddmo先來實現下。

demo我是類似仿微信的,在一個GridView中展示所有的圖片,其中第一個item可以去照相;獲取到圖片後再進行剪切。

圖片的剪切是從網上找的感覺不錯就用,暫時也沒有測試。

獲取圖片可以用:https://github.com/lovetuzitong/MultiImageSelector來實現

這裡的圓形圖像是用https://github.com/hdodenhof/CircleImageView來實現的

Demo寫的比較粗糙,效果只是在4.4的手機和7.0的模擬器跑了一遍,所以可能會出現問題的。

下載資源:http://download.csdn.net/download/qq_29774291/9955206

如下是demo的效果圖:

如下是選擇圖片中的代碼

通過LoaderManager來獲取到所有的圖片,然後第一個進行拍照的處理

  1 package com.item.demo.photo.activity;
  2 
  3 import android.Manifest;
  4 import android.app.LoaderManager;
  5 import android.content.ContentResolver;
  6 import android.content.Context;
  7 import android.content.CursorLoader;
  8 import android.content.Intent;
  9 import android.content.Loader;
 10 import android.content.pm.PackageManager;
 11 import android.database.Cursor;
 12 import android.net.Uri;
 13 import android.os.Build;
 14 import android.os.Environment;
 15 import android.provider.MediaStore;
 16 import android.support.annotation.NonNull;
 17 import android.support.v4.content.ContextCompat;
 18 import android.support.v4.content.FileProvider;
 19 import android.support.v7.app.AppCompatActivity;
 20 import android.os.Bundle;
 21 import android.text.TextUtils;
 22 import android.util.Log;
 23 import android.view.View;
 24 import android.widget.AdapterView;
 25 import android.widget.GridView;
 26 import android.widget.ImageView;
 27 
 28 import com.item.demo.photo.BuildConfig;
 29 import com.item.demo.photo.R;
 30 import com.item.demo.photo.adapter.MyPhotoAdapter;
 31 import com.item.demo.photo.uilts.Image;
 32 import java.io.File;
 33 import java.util.ArrayList;
 34 import java.util.List;
 35 
 36 /**
 37  * 圖片選擇界面
 38  */
 39 public class MyPhotoActivity extends AppCompatActivity {
 40 
 41     private static final int REQUEST_CAPTURE = 100;
 42     //private static final int REQUEST_PICK = 101;
 43     private static final int REQUEST_CROP_PHOTO = 102;
 44 
 45     public static  final int FINSH_RESULT = 104;//截圖後的返回
 46 
 47     private static final int LOADER_ID = 0x0100;
 48     private LoadCallBack mLoad = new LoadCallBack();
 49 
 50     private MyPhotoAdapter mAdapter;
 51     private List<Image> images = new ArrayList<>();
 52     //調用照相機返回圖片文件
 53     private File tempFile;
 54     private static final int MIN_IMAGE_FILE_SIZE = 10 * 1024; // 最小的圖片大小
 55 
 56     @Override
 57     protected void onCreate(Bundle savedInstanceState) {
 58         super.onCreate(savedInstanceState);
 59         setContentView(R.layout.activity_my_photo);
 60 
 61         GridView gv_photo = (GridView)findViewById(R.id.gv_photo);
 62         ImageView img_back = (ImageView)findViewById(R.id.iv_back);
 63         images.add(new Image());
 64         mAdapter = new MyPhotoAdapter(this,images);
 65         gv_photo.setAdapter(mAdapter);
 66         gv_photo.setOnItemClickListener(new AdapterView.OnItemClickListener() {
 67             @Override
 68             public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
 69                 if(i == 0){
 70                     //第一個就去照相
 71                    if(hasPermission(new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})){
 72                        gotoCamera();
 73                    }else {
 74                        requestPermission(0x02,new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE});
 75                    }
 76                 }else {
 77                     //這裡點擊獲取到圖片地址然後裁剪
 78                     gotoClipActivity(Uri.parse(images.get(i).getPath()));
 79                 }
 80             }
 81         });
 82         img_back.setOnClickListener(new View.OnClickListener() {
 83             @Override
 84             public void onClick(View view) {
 85                 finish();
 86             }
 87         });
 88     }
 89 
 90     @Override
 91     protected void onStart() {
 92         super.onStart();
 93 
 94         if(hasPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE})){
 95             getLoaderManager().initLoader(LOADER_ID,null,mLoad);
 96         }else {
 97             requestPermission(0x01,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE});
 98         }
 99     }
100 
101     private class LoadCallBack implements LoaderManager.LoaderCallbacks<Cursor>{
102         private final String[] IMAGE_PROJECTION = new String[]{
103                 MediaStore.Images.Media._ID,//Id
104                 MediaStore.Images.Media.DATA,//圖片路徑
105                 MediaStore.Images.Media.DATE_ADDED//圖片的創建時間
106         };
107 
108         @Override
109         public Loader<Cursor> onCreateLoader(int id, Bundle args) {
110             //創建一個Loader
111             if(id == LOADER_ID){
112                 //如果是我們的ID則進行初始化
113                 return new CursorLoader(getBaseContext(),
114                         MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
115                         IMAGE_PROJECTION,
116                         null,
117                         null,
118                         IMAGE_PROJECTION[2] + " DESC");
119             }
120             return null;
121         }
122 
123         @Override
124         public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
125             //當Loader載入完成時
126             List<Image> images = new ArrayList<>();
127             //判斷是否有數據
128             if(data != null){
129                 int count = data.getCount();
130                 if(count > 0){
131                     data.moveToFirst();
132                     // 得到對應的列的Index坐標
133                     int indexId = data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]);
134                     int indexPath = data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]);
135                     int indexDate = data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]);
136                     do {
137                         // 迴圈讀取,直到沒有下一條數據
138                         int id = data.getInt(indexId);
139                         String path = data.getString(indexPath);
140                         long dateTime = data.getLong(indexDate);
141 
142                         File file = new File(path);
143                         if (!file.exists() || file.length() < MIN_IMAGE_FILE_SIZE) {
144                             // 如果沒有圖片,或者圖片大小太小,則跳過
145                             continue;
146                         }
147                         // 添加一條新的數據
148                         Image image = new Image();
149                         image.setId(id);
150                         image.setPath(path);
151                         image.setDate(dateTime);
152                         images.add(image);
153 
154                     } while (data.moveToNext());
155                 }
156             }
157             updateSource(images);
158         }
159 
160         @Override
161         public void onLoaderReset(Loader<Cursor> loader) {
162             updateSource(null);
163         }
164     }
165 
166     /**
167      * 通知Adapter數據更改的方法
168      * @param images 新的數據
169      */
170     private void updateSource(List<Image> images){
171         this.images.clear();
172         this.images.add(new Image());
173         if(images == null || images.size() == 0) return;
174         this.images.addAll(images);
175         mAdapter.notifyDataSetChanged();
176     }
177 
178     /**
179      *許可權的返回
180      */
181     @Override
182     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
183         super.onRequestPermissionsResult(requestCode, permissions, grantResults);
184         switch(requestCode){
185             case 0x02:
186                 if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
187                     gotoCamera();
188                 }
189                 break;
190             case 0x01:
191                 if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
192                     getLoaderManager().initLoader(LOADER_ID,null,mLoad);
193                 }
194         }
195     }
196 
197     @Override
198     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
199         super.onActivityResult(requestCode, resultCode, data);
200         switch (requestCode){
201             case REQUEST_CAPTURE://系統相機返回
202                 if(resultCode == RESULT_OK){
203                     Log.d("jiejie","--------相機---------" + Uri.fromFile(tempFile).toString());
204                     Log.d("jiejie","--------path----------" + getRealFilePathFromUri(MyPhotoActivity.this,Uri.fromFile(tempFile)));
205                     gotoClipActivity(Uri.fromFile(tempFile));
206                 }
207 
208                 break;
209             case REQUEST_CROP_PHOTO:
210                 if(resultCode == RESULT_OK){
211                     if(data != null){
212                         Uri uri = data.getData();
213                         Log.d("jiejie","-------------" + data.getData().getPath());
214                         String cropImagePath = getRealFilePathFromUri(MyPhotoActivity.this,uri);
215                         Log.d("jiejie","------crop--------" + cropImagePath);
216                         Intent intent = new Intent();
217                         intent.putExtra("image",cropImagePath);
218                         setResult(FINSH_RESULT,intent);
219                         MyPhotoActivity.this.finish();
220                     }
221 
222                 }
223                 break;
224         }
225     }
226 
227     /**
228      * 跳轉到系統照相機
229      */
230     private void gotoCamera(){
231         String SDState = Environment.getExternalStorageState();
232         //判斷SD卡是否存在
233         if(SDState.equals(Environment.MEDIA_MOUNTED)){
234             tempFile = new File(checkDirPath(Environment.getExternalStorageDirectory().getPath()+ "/image/"), System.currentTimeMillis() + ".jpg");
235             //隱式的打開調用系統相冊
236             Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
237             if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
238                 intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
239                 //如果是7.0及以上的系統使用FileProvider的方式創建一個Uri
240                 Uri contentUri = FileProvider.getUriForFile(MyPhotoActivity.this, BuildConfig.APPLICATION_ID + ".fileProvider", tempFile);
241                 intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
242             }else {
243                 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
244             }
245             startActivityForResult(intent,REQUEST_CAPTURE);
246         }
247     }
248 
249     /**
250      * 打開截圖的界面
251      * @param uri
252      */
253     private void gotoClipActivity(Uri uri){
254         if(uri == null){
255             return;
256         }
257         Intent intent = new Intent(this,ClipImageActivity.class);
258         intent.putExtra("type",1);
259         intent.setData(uri);
260         startActivityForResult(intent,REQUEST_CROP_PHOTO);
261     }
262 
263     /**
264      * 檢查文件是否存在
265      */
266     private static String checkDirPath(String dirPath) {
267         if (TextUtils.isEmpty(dirPath)) {
268             return "";
269         }
270         File dir = new File(dirPath);
271         if (!dir.exists()) {
272             dir.mkdirs();
273         }
274         return dirPath;
275     }
276     /**
277      * 判斷是否有指定的許可權
278      */
279     public boolean hasPermission(String... permissions) {
280 
281         for (String permisson : permissions) {
282             if (ContextCompat.checkSelfPermission(this, permisson)
283                     != PackageManager.PERMISSION_GRANTED) {
284                 return false;
285             }
286         }
287         return true;
288     }
289     /**
290      * 申請指定的許可權.
291      */
292     public void requestPermission(int code, String... permissions) {
293 
294         if (Build.VERSION.SDK_INT >= 23) {
295             requestPermissions(permissions, code);
296         }
297     }
298 
299     /**
300      * 根據Uri返迴文件絕對路徑
301      * 相容了file:///開頭的 和 content://開頭的情況
302      */
303     public static String getRealFilePathFromUri(final Context context, final Uri uri) {
304         if (null == uri) return null;
305         final String scheme = uri.getScheme();
306         String data = null;
307         if (scheme == null)
308             data = uri.getPath();
309         else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
310             data = uri.getPath();
311         } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
312             Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
313             if (null != cursor) {
314                 if (cursor.moveToFirst()) {
315                     int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
316                     if (index > -1) {
317                         data = cursor.getString(index);
318                     }
319                 }
320                 cursor.close();
321             }
322         }
323         return data;
324     }
325 }

其中處理動態的許可權還需要添加7.0的照相處理

在清單文件中加如下配置:

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.item.demo.photo.fileProvider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

 

圖片的剪切

package com.item.demo.photo.activity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
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.TextView;
import com.item.demo.photo.R;
import com.item.demo.photo.view.ClipViewLayout;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

/**
 * 圖片剪切
 */
public class ClipImageActivity extends AppCompatActivity implements View.OnClickListener {

    private ClipViewLayout clipViewLayout1;
    private ClipViewLayout clipViewLayout2;
    private ImageView back;
    private TextView tv_ok;
    //類別 1:圓形  2:方形
    private int type;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_clip_image);
        type = getIntent().getIntExtra("type",1);
        initView();
    }

    private void initView() {
        clipViewLayout1 = (ClipViewLayout)findViewById(R.id.clipViewLayout1);
        clipViewLayout2 = (ClipViewLayout)findViewById(R.id.clipViewLayout2);
        back = (ImageView)findViewById(R.id.iv_back);
        tv_ok = (TextView)findViewById(R.id.tv_ok);
        back.setOnClickListener(this);
        tv_ok.setOnClickListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(type == 1){
            clipViewLayout1.setVisibility(View.VISIBLE);
            clipViewLayout2.setVisibility(View.GONE);
            //設置圖片資源
            clipViewLayout1.setImageSrc(getIntent().getData());
        }else {
            clipViewLayout2.setVisibility(View.VISIBLE);
            clipViewLayout1.setVisibility(View.GONE);
            clipViewLayout2.setImageSrc(getIntent().getData());
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.iv_back:
                finish();
                break;
            case R.id.tv_ok:
                generateUriAndReturn();
                break;
        }
    }

    /**
     * 生成Uri並且通過setResult返回給打開的Activity
     */
    private void generateUriAndReturn() {
        //調用返回剪切圖
        Bitmap zoomedCropBitmap;
        if (type == 1) {
            zoomedCropBitmap = clipViewLayout1.clip();
        } else {
            zoomedCropBitmap = clipViewLayout2.clip();
        }
        if (zoomedCropBitmap == null) {
            Log.e("android", "zoomedCropBitmap == null");
            return;
        }
        Uri mSaveUri = Uri.fromFile(new File(getCacheDir(), "cropped_" + System.currentTimeMillis() + ".jpg"));
        if (mSaveUri != null) {
            OutputStream outputStream = null;
            try {
                outputStream = getContentResolver().openOutputStream(mSaveUri);
                if (outputStream != null) {
                    zoomedCropBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
                }
            } catch (IOException ex) {
                Log.e("android", "Cannot open file: " + mSaveUri, ex);
            } finally {
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            Intent intent = new Intent();
            intent.setData(mSaveUri);
            setResult(RESULT_OK, intent);
            finish();
        }
    }
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Android精選源碼 Android優質博客 前幾天看到同事里有一個界面絢麗的應用,覺得有點意思,就讓他把APK發給我,我想反編譯看看裡面的代碼。結果,這哥們在手機里找了好一陣子,最後給我說:手機沒有root,找不到APK文件在哪裡。我再讓他試試其他機子,結果都差不多:要不然找起來很麻煩,要不然根 ...
  • Android開機圖片替換 Android從啟動到進入Launcher一共會展示三張圖片,如果只是更換靜態圖則更換這三張圖片即可,要想換成動畫那就要另外操作。 首先查找這個文件: /bootable/bootloader/lk/project/<project>.mk 裡邊有這個配置,記住這個等號後 ...
  • UX設計師是以用戶體驗為中心,進行產品設計,他們的任務就是讓用戶說出“Yes”。UX設計涉及到人機交互的各個方面,如可用性、功能性、交互設計、信息架構設計等等。就這些方面來說,原型工具不可或缺。市場上的原型工具有很多,但想找到合心意的卻比較困難。其實,挑選工具也是有門道的,在確定具體用戶及項目需求前 ...
  • iOS精選源碼 iOS優質博客 前言發現好久沒有研究、學習iOS優秀開源代碼,現在大部分時間都在寫業務代碼, 學習其他語言及一些雜七雜八的事情。所以現在就從簡短的開源代碼開始學習。這一篇就寫FaceBook, 這個極度熱愛開源的公司, 它的一套關於KVO的開源代碼。GitHub代碼演示代碼地址正文F ...
  • 一、前沿||潛心修心,學無止盡。生活如此,coding亦然。本人鳥窩,一隻正在求職的鳥。聯繫我可以直接微信:jkxx123321 二、項目總結 **||**文章參考資料:1. http://blog.csdn.net/u011272795/article/details/73824558 2.htt ...
  • 參考資料:https://github.com/sunyardTime/React-Native-CodeStyle 感謝情書哥無私奉獻 ##一、編程規約 ###(一) 命名規約 【強制】 代碼中命名均不能以下劃線或美元符號開始,也不能以下劃線或美元符號結束; 【強制】 代碼中命名嚴禁使用拼音與英文 ...
  • ...
  • Notification的幾種基本使用方法,大家肯定都已經爛熟於心,我也不必多說.給一個鏈接:https://zhuanlan.zhihu.com/p/25841482 接下來我想說的是android5.0 後的彈出通知, 網上的方法是: 但上面的做法並不能在android5.0以下的設備上使通知彈 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...