自定義Logo二維碼繪制(追加上一篇簡單二維碼繪制)
1.實作思路 2.實作(新增拍照以及相冊上傳logo以及分享和保存二維碼)
簡單繪制二維碼地址:
Android 實作簡單繪制二維碼(包含帶LOGO的二維碼的繪制)
1.實作思路
<style>#mermaid-svg-yYdAn0OP0tWTGJGs .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .label text{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .node rect,#mermaid-svg-yYdAn0OP0tWTGJGs .node circle,#mermaid-svg-yYdAn0OP0tWTGJGs .node ellipse,#mermaid-svg-yYdAn0OP0tWTGJGs .node polygon,#mermaid-svg-yYdAn0OP0tWTGJGs .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-yYdAn0OP0tWTGJGs .node .label{text-align:center;fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .node.clickable{cursor:pointer}#mermaid-svg-yYdAn0OP0tWTGJGs .arrowheadPath{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-yYdAn0OP0tWTGJGs .flowchart-link{stroke:#333;fill:none}#mermaid-svg-yYdAn0OP0tWTGJGs .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-yYdAn0OP0tWTGJGs .edgeLabel rect{opacity:0.9}#mermaid-svg-yYdAn0OP0tWTGJGs .edgeLabel span{color:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-yYdAn0OP0tWTGJGs .cluster text{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-yYdAn0OP0tWTGJGs .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-yYdAn0OP0tWTGJGs text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-yYdAn0OP0tWTGJGs .actor-line{stroke:grey}#mermaid-svg-yYdAn0OP0tWTGJGs .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-yYdAn0OP0tWTGJGs #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .sequenceNumber{fill:#fff}#mermaid-svg-yYdAn0OP0tWTGJGs #sequencenumber{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs #crosshead path{fill:#333;stroke:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .messageText{fill:#333;stroke:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-yYdAn0OP0tWTGJGs .labelText,#mermaid-svg-yYdAn0OP0tWTGJGs .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-yYdAn0OP0tWTGJGs .loopText,#mermaid-svg-yYdAn0OP0tWTGJGs .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-yYdAn0OP0tWTGJGs .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-yYdAn0OP0tWTGJGs .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-yYdAn0OP0tWTGJGs .noteText,#mermaid-svg-yYdAn0OP0tWTGJGs .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-yYdAn0OP0tWTGJGs .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-yYdAn0OP0tWTGJGs .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-yYdAn0OP0tWTGJGs .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-yYdAn0OP0tWTGJGs .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .section{stroke:none;opacity:0.2}#mermaid-svg-yYdAn0OP0tWTGJGs .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-yYdAn0OP0tWTGJGs .section2{fill:#fff400}#mermaid-svg-yYdAn0OP0tWTGJGs .section1,#mermaid-svg-yYdAn0OP0tWTGJGs .section3{fill:#fff;opacity:0.2}#mermaid-svg-yYdAn0OP0tWTGJGs .sectionTitle0{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .sectionTitle1{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .sectionTitle2{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .sectionTitle3{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-yYdAn0OP0tWTGJGs .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .grid path{stroke-width:0}#mermaid-svg-yYdAn0OP0tWTGJGs .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-yYdAn0OP0tWTGJGs .task{stroke-width:2}#mermaid-svg-yYdAn0OP0tWTGJGs .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .taskText:not([font-size]){font-size:11px}#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-yYdAn0OP0tWTGJGs .task.clickable{cursor:pointer}#mermaid-svg-yYdAn0OP0tWTGJGs .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-yYdAn0OP0tWTGJGs .taskText0,#mermaid-svg-yYdAn0OP0tWTGJGs .taskText1,#mermaid-svg-yYdAn0OP0tWTGJGs .taskText2,#mermaid-svg-yYdAn0OP0tWTGJGs .taskText3{fill:#fff}#mermaid-svg-yYdAn0OP0tWTGJGs .task0,#mermaid-svg-yYdAn0OP0tWTGJGs .task1,#mermaid-svg-yYdAn0OP0tWTGJGs .task2,#mermaid-svg-yYdAn0OP0tWTGJGs .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutside0,#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutside2{fill:#000}#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutside1,#mermaid-svg-yYdAn0OP0tWTGJGs .taskTextOutside3{fill:#000}#mermaid-svg-yYdAn0OP0tWTGJGs .active0,#mermaid-svg-yYdAn0OP0tWTGJGs .active1,#mermaid-svg-yYdAn0OP0tWTGJGs .active2,#mermaid-svg-yYdAn0OP0tWTGJGs .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-yYdAn0OP0tWTGJGs .activeText0,#mermaid-svg-yYdAn0OP0tWTGJGs .activeText1,#mermaid-svg-yYdAn0OP0tWTGJGs .activeText2,#mermaid-svg-yYdAn0OP0tWTGJGs .activeText3{fill:#000 !important}#mermaid-svg-yYdAn0OP0tWTGJGs .done0,#mermaid-svg-yYdAn0OP0tWTGJGs .done1,#mermaid-svg-yYdAn0OP0tWTGJGs .done2,#mermaid-svg-yYdAn0OP0tWTGJGs .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-yYdAn0OP0tWTGJGs .doneText0,#mermaid-svg-yYdAn0OP0tWTGJGs .doneText1,#mermaid-svg-yYdAn0OP0tWTGJGs .doneText2,#mermaid-svg-yYdAn0OP0tWTGJGs .doneText3{fill:#000 !important}#mermaid-svg-yYdAn0OP0tWTGJGs .crit0,#mermaid-svg-yYdAn0OP0tWTGJGs .crit1,#mermaid-svg-yYdAn0OP0tWTGJGs .crit2,#mermaid-svg-yYdAn0OP0tWTGJGs .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-yYdAn0OP0tWTGJGs .activeCrit0,#mermaid-svg-yYdAn0OP0tWTGJGs .activeCrit1,#mermaid-svg-yYdAn0OP0tWTGJGs .activeCrit2,#mermaid-svg-yYdAn0OP0tWTGJGs .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-yYdAn0OP0tWTGJGs .doneCrit0,#mermaid-svg-yYdAn0OP0tWTGJGs .doneCrit1,#mermaid-svg-yYdAn0OP0tWTGJGs .doneCrit2,#mermaid-svg-yYdAn0OP0tWTGJGs .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-yYdAn0OP0tWTGJGs .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-yYdAn0OP0tWTGJGs .milestoneText{font-style:italic}#mermaid-svg-yYdAn0OP0tWTGJGs .doneCritText0,#mermaid-svg-yYdAn0OP0tWTGJGs .doneCritText1,#mermaid-svg-yYdAn0OP0tWTGJGs .doneCritText2,#mermaid-svg-yYdAn0OP0tWTGJGs .doneCritText3{fill:#000 !important}#mermaid-svg-yYdAn0OP0tWTGJGs .activeCritText0,#mermaid-svg-yYdAn0OP0tWTGJGs .activeCritText1,#mermaid-svg-yYdAn0OP0tWTGJGs .activeCritText2,#mermaid-svg-yYdAn0OP0tWTGJGs .activeCritText3{fill:#000 !important}#mermaid-svg-yYdAn0OP0tWTGJGs .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-yYdAn0OP0tWTGJGs g.classGroup text .title{font-weight:bolder}#mermaid-svg-yYdAn0OP0tWTGJGs g.clickable{cursor:pointer}#mermaid-svg-yYdAn0OP0tWTGJGs g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-yYdAn0OP0tWTGJGs g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-yYdAn0OP0tWTGJGs .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-yYdAn0OP0tWTGJGs .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-yYdAn0OP0tWTGJGs .dashed-line{stroke-dasharray:3}#mermaid-svg-yYdAn0OP0tWTGJGs #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs .commit-id,#mermaid-svg-yYdAn0OP0tWTGJGs .commit-msg,#mermaid-svg-yYdAn0OP0tWTGJGs .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-yYdAn0OP0tWTGJGs g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-yYdAn0OP0tWTGJGs g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-yYdAn0OP0tWTGJGs g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-yYdAn0OP0tWTGJGs .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-yYdAn0OP0tWTGJGs .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-yYdAn0OP0tWTGJGs .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-yYdAn0OP0tWTGJGs .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-yYdAn0OP0tWTGJGs .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-yYdAn0OP0tWTGJGs .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-yYdAn0OP0tWTGJGs .edgeLabel text{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-yYdAn0OP0tWTGJGs .node circle.state-start{fill:black;stroke:black}#mermaid-svg-yYdAn0OP0tWTGJGs .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-yYdAn0OP0tWTGJGs #statediagram-barbEnd{fill:#9370db}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-state .divider{stroke:#9370db}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-yYdAn0OP0tWTGJGs .note-edge{stroke-dasharray:5}#mermaid-svg-yYdAn0OP0tWTGJGs .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-yYdAn0OP0tWTGJGs .error-icon{fill:#522}#mermaid-svg-yYdAn0OP0tWTGJGs .error-text{fill:#522;stroke:#522}#mermaid-svg-yYdAn0OP0tWTGJGs .edge-thickness-normal{stroke-width:2px}#mermaid-svg-yYdAn0OP0tWTGJGs .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-yYdAn0OP0tWTGJGs .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-yYdAn0OP0tWTGJGs .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-yYdAn0OP0tWTGJGs .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-yYdAn0OP0tWTGJGs .marker{fill:#333}#mermaid-svg-yYdAn0OP0tWTGJGs .marker.cross{stroke:#333}
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style>
<style>#mermaid-svg-yYdAn0OP0tWTGJGs {
color: rgba(0, 0, 0, 0.75);
font: ;
}</style>
是
是
否
否
用戶
選擇logo
是否選擇
使用用戶選擇logo
輸入二維碼內容
點擊生成按鈕
是否輸入二維碼內容
生成二維碼
默認使用系統圖示
2.實作(新增拍照以及相冊上傳logo以及分享和保存二維碼)
引數說明:
//拍照
public static final int TAKE_PHOTO = 1 ;
//從相冊選擇圖片
public static final int CHOOSE_PHOTO = 2 ;
//二維碼寬度
public static final int QR_CODE_WIDTH = 500 ;
//logo的尺寸不能高于二維碼的20%.大于可能會導致二維碼失效
public static final int LOGO_WIDTH_MAX = QR_CODE_WIDTH / 5 ;
//logo的尺寸不能小于二維碼的10%,否則不搭
public static final int LOGO_WIDTH_MIN = QR_CODE_WIDTH / 10 ;
//定義黑色
private static final int BLACK = 0xFF000000 ;
//定義白色
private static final int WHITE = 0xFFFFFFFF ;
//生成的二維碼
private Bitmap genBitMap;
//繪制的logo二維碼
private Bitmap logoBitMap;
//圖片地址
private Uri imageUri;
1)、拍照上傳
private void takePhoto ( ) {
// 創建File物件,用于存盤拍照后的圖片
File outputImage = new File ( getExternalCacheDir ( ) , "output_image.jpg" ) ;
try {
if ( outputImage. exists ( ) ) {
outputImage. delete ( ) ;
}
outputImage. createNewFile ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
if ( Build. VERSION. SDK_INT < 24 ) { //SDK版本小于24 使用Uri決議
imageUri = Uri. fromFile ( outputImage) ;
} else {
imageUri = FileProvider. getUriForFile ( LogoQRCode. this , "fatcats.top.qrcodedemo.fileprovider" , outputImage) ;
}
// 啟動相機程式
Intent intent = new Intent ( "android.media.action.IMAGE_CAPTURE" ) ;
intent. putExtra ( MediaStore. EXTRA_OUTPUT, imageUri) ;
startActivityForResult ( intent, TAKE_PHOTO) ;
}
補充FileProvider:
在app開發程序中需要用到FileProvider的主要有 1.1、相機拍照以及圖片裁剪 1.2、呼叫系統應用安裝器安裝apk(應用升級) 1.3、基本配置使用方法:在以前使用的是v4的包下的FileProvider,到現在可以使用androidx包下的FileProvider(androidx.core.content.FileProvider)
< provider
android: name= "android.support.v4.content.FileProvider"
android: authorities= "${applicationId}.provider"
android: exported= "false"
android: grantUriPermissions= "true" >
< meta- data
android: name= "android.support.FILE_PROVIDER_PATHS"
android: resource= "@xml/provider_paths" / >
< / provider>
說明:
authorities:標識,在當前系統內必須是唯一值,一般用包名,
exported:表示該 FileProvider 是否需要公開出去,
granUriPermissions:是否允許授權檔案的臨時訪問權限,(這里是給出了權限)
1.4.xml檔案配置:
< ? xml version= "1.0" encoding= "utf-8" ? >
< paths xmlns: android= "http://schemas.android.com/apk/res/android" >
< ! -- path設為空值表示將整個sd卡共享-- >
< external- path
name= "external_storage"
path= "" / >
< / paths>
補充說明:xml中標簽的配置可以參考FileProvider原始碼中的標簽說明
public class FileProvider extends ContentProvider {
private static final String[ ] COLUMNS = {
OpenableColumns. DISPLAY_NAME, OpenableColumns. SIZE } ;
private static final String
META_DATA_FILE_PROVIDER_PATHS = "android.support.FILE_PROVIDER_PATHS" ;
private static final String TAG_ROOT_PATH = "root-path" ;
private static final String TAG_FILES_PATH = "files-path" ;
private static final String TAG_CACHE_PATH = "cache-path" ;
private static final String TAG_EXTERNAL = "external-path" ;
private static final String TAG_EXTERNAL_FILES = "external-files-path" ;
private static final String TAG_EXTERNAL_CACHE = "external-cache-path" ;
private static final String TAG_EXTERNAL_MEDIA = "external-media-path" ;
. . .
2)、從相冊選擇
private void choosePhotoFromAlbum ( ) {
if ( ContextCompat. checkSelfPermission ( LogoQRCode. this , Manifest. permission. WRITE_EXTERNAL_STORAGE) != PackageManager. PERMISSION_GRANTED) {
ActivityCompat. requestPermissions ( LogoQRCode. this , new String [ ] { Manifest. permission. WRITE_EXTERNAL_STORAGE} , 1 ) ;
} else {
openAlbum ( ) ;
}
}
2.1、打開相冊
private void openAlbum ( ) {
Intent intent = new Intent ( "android.intent.action.GET_CONTENT" ) ;
intent. setType ( "image/*" ) ;
startActivityForResult ( intent, CHOOSE_PHOTO) ;
}
2.2、回傳結果
@Override
protected void onActivityResult ( int requestCode, int resultCode, Intent data) {
super . onActivityResult ( requestCode, resultCode, data) ;
switch ( requestCode) {
case TAKE_PHOTO:
if ( resultCode == RESULT_OK) {
try {
logoBitMap = BitmapFactory. decodeStream ( getContentResolver ( ) . openInputStream ( imageUri) ) ;
// 將拍攝的照片顯示出來
logoImg. setImageBitmap ( logoBitMap) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
break ;
case CHOOSE_PHOTO:
if ( resultCode == RESULT_OK) {
// 判斷手機系統版本號
if ( Build. VERSION. SDK_INT >= 19 ) {
// 4.4及以上系統使用這個方法處理圖片
handleImageOnKitKat ( data) ;
} else {
// 4.4以下系統使用這個方法處理圖片
handleImageBeforeKitKat ( data) ;
}
}
break ;
default :
break ;
}
}
2.3、sdk4.4以上處理圖片方法
@SuppressLint ( "NewApi" )
private void handleImageOnKitKat ( Intent data) {
String imagePath = null;
Uri uri = data. getData ( ) ;
Log. d ( "TAG" , "handleImageOnKitKat: uri is " + uri) ;
if ( DocumentsContract. isDocumentUri ( this , uri) ) {
// 如果是document型別的Uri,則通過document id處理
String docId = DocumentsContract. getDocumentId ( uri) ;
if ( "com.android.providers.media.documents" . equals ( uri. getAuthority ( ) ) ) {
String id = docId. split ( ":" ) [ 1 ] ; // 決議出數字格式的id
String selection = MediaStore. Images. Media. _ID + "=" + id;
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) ; // 根據圖片路徑顯示圖片
}
2.4 SDK4.4以下處理圖片方式
private void handleImageBeforeKitKat ( Intent data) {
Uri uri = data. getData ( ) ;
String imagePath = getImagePath ( uri, null) ;
displayImage ( imagePath) ;
}
2.5 展示圖片
private void displayImage ( String imagePath) {
if ( imagePath != null) {
Toast. makeText ( this , "成功" , Toast. LENGTH_SHORT) . show ( ) ;
logoBitMap = BitmapFactory. decodeFile ( imagePath) ;
// 顯示圖片
Bitmap bitmap = createBitmap ( ( ( BitmapDrawable) getDrawable ( R. drawable. bg) ) . getBitmap ( ) , logoBitMap) ;
logoImg. setImageBitmap ( bitmap) ;
} else {
Toast. makeText ( this , "獲取圖片失敗" , Toast. LENGTH_SHORT) . show ( ) ;
}
}
補充:createBitmap(Bitmap bgBitmap , Bitmap logoBitmap)方法在上文中有提到,小編在不在此再多敘述啦
3)、儲存圖片
3.1 儲存圖片處理
private void saveImg ( Bitmap bitmap) {
String fileName = "qr_" + System. currentTimeMillis ( ) + ".jpg" ; //圖片保存名稱格式
boolean isSaveSuccess = ImgStoreUtils. saveImageToGallery ( LogoQRCode. this , bitmap, fileName) ;
if ( isSaveSuccess) {
Toast. makeText ( LogoQRCode. this , "圖片已保存至本地" , Toast. LENGTH_LONG) . show ( ) ;
} else {
Toast. makeText ( LogoQRCode. this , "保存圖片失敗,請稍后重試" , Toast. LENGTH_SHORT) . show ( ) ;
}
}
圖片保存工具:ImgStoreUtils
public static boolean saveImageToGallery ( Context context, Bitmap qrBitmap, String fileName) {
// 保存圖片至指定路徑
String storePath = Environment. getExternalStorageDirectory ( ) . getAbsolutePath ( ) + File. separator + "qrcode" ;
File appDir = new File ( storePath) ;
if ( ! appDir. exists ( ) ) {
appDir. mkdir ( ) ;
}
File file = new File ( appDir, fileName) ;
try {
FileOutputStream fos = new FileOutputStream ( file) ;
//通過io流的方式來壓縮保存圖片(80代表壓縮20%)
boolean isSuccess = qrBitmap. compress ( Bitmap. CompressFormat. JPEG, 80 , fos) ;
fos. flush ( ) ;
fos. close ( ) ;
Uri uri = Uri. fromFile ( file) ;
//發送廣播通知系統圖庫重繪資料
context. sendBroadcast ( new Intent ( Intent. ACTION_MEDIA_SCANNER_SCAN_FILE, uri) ) ;
if ( isSuccess) {
return true ;
} else {
return false ;
}
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
return false ;
}
4)、分享圖片
private void shareImg ( Bitmap bitmap) {
Uri uri = Uri. parse ( MediaStore. Images. Media. insertImage ( getContentResolver ( ) , bitmap, null, null) ) ;
Intent intent = new Intent ( ) ;
intent. setAction ( Intent. ACTION_SEND) ;
intent. setType ( "image/*" ) ; //設定分享內容的型別
intent. putExtra ( Intent. EXTRA_STREAM, uri) ;
intent = Intent. createChooser ( intent, "分享" ) ;
startActivity ( intent) ;
}
5.效果圖:
專案地址放在GitHub上啦