初始,准备工作
- 安装Android sudio 开发工具
- 搭建android 运行环境(java14)
- 腾讯云OCR产品开通,及其秘钥获取
一、建立一个Android空项目及目录层次介绍
(1)android 空项目以及环境搭建,请参考:Windows Android studio 搭建基础的Android 环境(Java SE 14)
(2)目录结构介绍
- .gredia以及idea目录 :目录下放置的都是as自动生成的文件,本章无需关系
- app 目录 : 本章用到的文件目录,仅着重介绍需要使用的文件及目录
- src > main > java 目录 : 放置所有代码目录,数据交互,事件操作
- src > main > res 目录 : 资源目录,即android 前端样式 展示界面等前端相关
- src > main > AndroidMinifest.xml 文件 : 整个项目配置文件,开通权限,首页访问设置,其他页面管理都在此
- build.gradle文件 :app模块的构建脚本
- build目录 : 包含编译时自动生成的文件,本章无关
- gradle目录 :包含gradle wrapper的配置文件,本章无关
- gitgnore文件 : 文件是用来将制定的目录或文件排除在版本控制之外的,本章无关
- build.gradle文件 : 全局的gradle构建脚本,通常文件的内容不需要修改,本章无关
- gradle.properties文件 :全局的gradle配置文件,这里配置的属性将会影响到项目中所有的gradle编译脚本,本章无关
- gradlew和gradlew.bat 文件 :这两个文件是用来在命令行界面执行gradle命令的,其中gradlew是在linux或mac系统中使用的,gradlew.bat是在windows系统中使用的,本章无关
- ***.iml 文件:iml文件是所有intellij IDEA项目都会自动生成的文件,标识是 intellij IDEA项目,本章无关
- local.properties文件 : 自动生成用于指定本机sdk的路径,不需要修改,除非sdk路径发生改变,本章无关
- settings.gradle文件 :指定项目中所有引用的模块,通常情况下模块的引入都是自动生成的,本章无关
小结回顾及知识扩展:
(1)创建一个界面
(2)加载 GSON 类库
二、构建前端页面样式
- 界面放置 res > layout 文件夹下, 生成示例:activity_face.xml 文件
- value 目录 : 放置存储值的文件
- res/drawable-xxxx目录 : 是存放图片的目录
代码示例,(为方便展示与基础学习,前端未拆分样式)
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<!-- tools:context 是指你 src -> main -> java 中对应的代码文件 -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="#CC0000"
android:paddingLeft="56dp"
android:paddingRight="56dp">
<TextView
android:id="@ id/nav_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="人脸识别"
android:textColor="#FDFDFD"
android:textSize="16sp" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_marginTop="30dp">
<EditText
android:layout_width="200dp"
android:layout_height="match_parent"
android:background="@drawable/ic_launcher_background"
android:backgroundTint="#C52424"
android:textColor="#ffffff"
android:focusable="false"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:text="NeedQualityDetection"
android:textSize="18dp" />
<EditText
android:id="@ id/needQualityDetection"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:hint="0 or 1"
android:text="1"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_marginTop="30dp">
<!--android:layout_gravity="center_vertical"-->
<EditText
android:layout_width="200dp"
android:layout_height="match_parent"
android:background="@drawable/ic_launcher_background"
android:backgroundTint="#C52424"
android:textColor="#ffffff"
android:focusable="false"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:text="FaceModelVersion"
android:textSize="18dp" />
<EditText
android:id="@ id/paramFaceModel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:hint="2.0 or 3.0"
android:text="3.0"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp" />
</LinearLayout>
<ImageView
android:id="@ id/photoView"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_gravity="center"
android:layout_margin="20dp"
/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_marginTop="10dp">
<Button
android:id="@ id/albumBtnEvt"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:background="#FF5722"
android:text="打 开 相 册"
android:textColor="#FFFEFE"
android:onClick="getImageFromAlbum"/>
<Button
android:layout_width="wrap_content"
android:layout_height="44dp"
android:background="#FF5722"
android:text="拍 照"
android:textColor="#FFFEFE"
android:layout_marginLeft="20dp"
android:onClick="toCamera"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="#A52A2A"
android:text="发 送 请 求"
android:textColor="#FFFEFE"
android:layout_marginLeft="20dp"
android:onClick="onFormBtnClick"/>
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_marginTop="5dp">
<!--android:layout_gravity="center_vertical"-->
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="年 龄"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
<EditText
android:id="@ id/ageEvt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_marginTop="5dp">
<!--android:layout_gravity="center_vertical"-->
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="性 别"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
<EditText
android:id="@ id/sexEvt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_marginTop="5dp">
<!--android:layout_gravity="center_vertical"-->
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="装 束"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
<EditText
android:id="@ id/markEvt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_marginTop="5dp">
<!--android:layout_gravity="center_vertical"-->
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="表 情"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
<EditText
android:id="@ id/ExpressionEvt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textSize="18dp"
android:focusable="false"/>
</LinearLayout>
</LinearLayout>
三、后端响应代码 (src > main > java > com.xxxxx 下)
代码语言:javascript复制package com.example.faceiai;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.gson.Gson;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends Activity {
//申明前端布局属性
private TextView needQualityDetectionEvt, paramFaceModelVersionEvt, markEvt, ageEvt, sexEvt, ExpressionEvt;
//设置需要的拍照、相册权限
private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA };//权限
//申明前端图片展示属性
private ImageView photoViewEvt;
//申明人脸检测属性
private String response;
final Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
/**
* 加载初始化
*/
private void init(){
// android 7.0系统解决拍照的问题
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
//初始化控件 findViewById 用R.id到前端通过android:id指定的id 获取当前选中属性
needQualityDetectionEvt = findViewById(R.id.needQualityDetection);
paramFaceModelVersionEvt = findViewById(R.id.paramFaceModel);
photoViewEvt = findViewById(R.id.photoView);
sexEvt = findViewById(R.id.sexEvt);
ageEvt = findViewById(R.id.ageEvt);
markEvt = findViewById(R.id.markEvt);
ExpressionEvt = findViewById(R.id.ExpressionEvt);
}
/**
* 表单提交点击事件
* 前端通过android:onClick 指定点击时间触发方法
* @param v
*/
public void onFormBtnClick(View v){
//android4.0 以后不能在主线程发起网络请求,该异步网络请求
new Thread(new Runnable()
{
@Override
public void run()
{
//获取前端 needQualityDetection 的 value
int needQualityDetection = Integer.parseInt(needQualityDetectionEvt.getText().toString());
//获取前端 paramFaceModelVersion 的 value
String paramFaceModelVersion = paramFaceModelVersionEvt.getText().toString();
//获取前端相册或者拍照时间生成的缩略图的Bitmap值
Bitmap photoBitmap = ((BitmapDrawable) photoViewEvt.getDrawable()).getBitmap();
//图片Bitmap -转化-> base64
String photoBase64 = bitmapToBase64(photoBitmap);
Map<String, Object> params = new HashMap<>();
params.put("Image", photoBase64);
params.put("FaceModelVersion", paramFaceModelVersion);
params.put("NeedFaceAttributes", 1);
params.put("NeedQualityDetection", needQualityDetection);
Gson gson = new Gson();
String param = gson.toJson(params);
Log.e("request", param);
// TODO Auto-generated method stub
//发送请求 本地封装的https 请求
response = AuthFace.getAuthTC3("DetectFace", param, AuthFace.Version);
//response = "{"Response":{"ImageWidth":1080,"ImageHeight":1440,"FaceInfos":[{"X":119,"Y":18,"Width":558,"Height":721,"FaceAttributesInfo":{"Gender":1,"Age":24,"Expression":28,"Hat":false,"Glass":false,"Mask":true,"Hair":{"Length":3,"Bang":0,"Color":0},"Pitch":5,"Yaw":17,"Roll":2,"Beauty":79,"EyeOpen":true},"FaceQualityInfo":{"Score":29,"Sharpness":43,"Brightness":34,"Completeness":{"Eyebrow":98,"Eye":99,"Nose":94,"Cheek":64,"Mouth":71,"Chin":35}}}],"FaceModelVersion":"3.0","RequestId":"4c1ebdb5-7a96-405e-a9bc-0a329ea26cda"}}";
handler.post(new Runnable() {
@Override
public void run() {
try {
//处理json 数据 把JSON数据转化为对象
JSONObject jsonObject = new JSONObject(response.toString());
//返回错误提示
if (jsonObject.getJSONObject("Response").has("Error")){
String Message = jsonObject.getJSONObject("Response").getJSONObject("Error").getString("Message");
String RequestId = jsonObject.getJSONObject("Response").getString("RequestId");
String Code = jsonObject.getJSONObject("Response").getJSONObject("Error").getString("Code");
//给前端设置值
sexEvt.setText(Message);
ageEvt.setText(Message);
markEvt.setText(Code);
ExpressionEvt.setText(RequestId);
} else {
//正确的人脸检测反馈
JSONObject FaceAttributesInfo = jsonObject.getJSONObject("Response").getJSONArray("FaceInfos").getJSONObject(0).getJSONObject("FaceAttributesInfo");
int Gender = FaceAttributesInfo.getInt("Gender");
int Age = FaceAttributesInfo.getInt("Age");
int Expression = FaceAttributesInfo.getInt("Expression");
Boolean Mark = FaceAttributesInfo.getBoolean("Mask");
//给前端设置值
sexEvt.setText(FaceUtilsJson.getGenderName(Gender));
ageEvt.setText(String.valueOf(Age));
markEvt.setText(FaceUtilsJson.getMask(Mark));
ExpressionEvt.setText(FaceUtilsJson.getExpressionName(Expression));
}
}catch (JSONException e){
Log.e("JSON error", e.getMessage());
}
}
});
}
}).start();
}
/**
* 获取相册事件
* @param v
*/
public void getImageFromAlbum(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, 100);// 100: 相册的返回码参数(随便一个值就行,只要不冲突就好)
}
//跳转相机
public void toCamera(View v) {
//查看相机权限 用户手动授权
if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ){
Log.e("camera","提示是否要授权");
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, 3);
}else{
Log.e("camera","直接打开相机");
//已经有权限
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //跳转到 ACTION_IMAGE_CAPTURE
//判断内存卡是否可用,可用的话就进行存储
//putExtra:取值,Uri.fromFile:传一个拍照所得到的文件,fileImg.jpg:文件名
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),"fileImg.jpg")));
startActivityForResult(intent,101); // 101: 相机的返回码参数(随便一个值就行,只要不冲突就好)
}
}
/**
* 自带方法,相册更相机时间确定后,返回回来指定的方法
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
switch (requestCode){
case 100: //相册返回的数据(相册的返回码)
if (data == null) {
Log.e("onActivityResult", "暂无内容");
return;
}
Uri uriPath = data.getData();
//方案一
//photoViewEvt.setImageURI(uriPath);
//方案二
try {
//获取相册的图片bitmap值
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uriPath));
//质量压缩
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] bytes = bos.toByteArray();
Bitmap mSrcBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
photoViewEvt.setImageBitmap(mSrcBitmap);
} catch (IOException e) {
Log.e("onActivityResult 100", e.getMessage());
e.printStackTrace();
}
break;
case 101: //相机返回的数据(相机的返回码)
try {
File tempFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),"fileImg.jpg"); //相机取图片数据文件
Uri uri = Uri.fromFile(tempFile); //图片文件
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
//质量压缩
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] bytes = bos.toByteArray();
Bitmap mSrcBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
photoViewEvt.setImageBitmap(mSrcBitmap);
} catch (IOException e) {
Log.e("onActivityResult", e.getMessage());
e.printStackTrace();
}
break;
}
}
/*
* bitmap转base64
* */
private static String bitmapToBase64(Bitmap bitmap) {
String result = null;
ByteArrayOutputStream baos = null;
try {
if (bitmap != null) {
baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
baos.flush();
baos.close();
byte[] bitmapBytes = baos.toByteArray();
result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.flush();
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}
人脸识别V3鉴权接口请求代码示例 (src > main > java > com.xxx > AuthFace.java)
代码语言:javascript复制package com.example.faceiai;
import android.text.TextUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* 人脸识别V3鉴权
*/
public class AuthFace {
private static String SecretId = "";
private static String SecretKey = "";
private static String Url = "https://iai.tencentcloudapi.com";
//规范请求串
private static String HTTPRequestMethod = "POST";
private static String CanonicalURI = "/";
private static String CanonicalQueryString = "";
private static String CanonicalHeaders = "content-type:application/json; charset=utf-8nhost:iai.tencentcloudapi.comn";
private static String SignedHeaders = "content-type;host";//参与签名的头部信息
//签名字符串
private static String Algorithm = "TC3-HMAC-SHA256";
private static String Service = "iai";
private static String Stop = "tc3_request";
//版本
public static String Version = "2018-03-01";
/**
* v3鉴权
* @param action 人脸识别接口名 例如 DetectFace
* @param paramJson json化的参数
* @param version 版本号 2018-03-01
* @return
*/
public static String getAuthTC3(String action, String paramJson, String version){
try{
String hashedRequestPayload = HashEncryption(paramJson);
String CanonicalRequest =
HTTPRequestMethod 'n'
CanonicalURI 'n'
CanonicalQueryString 'n'
CanonicalHeaders 'n'
SignedHeaders 'n'
hashedRequestPayload;
//时间戳
Date date = new Date();
//微秒->秒
String timestamp = String.valueOf(date.getTime() / 1000);
//格林威治时间转化
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
formatter.setTimeZone(TimeZone.getTimeZone("GMT 0"));
String dateString = formatter.format(date.getTime());
//签名字符串
String credentialScope = dateString "/" Service "/" Stop;
String hashedCanonicalRequest = HashEncryption(CanonicalRequest);
String stringToSign = Algorithm "n"
timestamp "n"
credentialScope "n"
hashedCanonicalRequest;
//计算签名
byte[] secretDate = HashHmacSha256Encryption(("TC3" SecretKey).getBytes("UTF-8"), dateString);
byte[] secretService = HashHmacSha256Encryption(secretDate, Service);
byte[] secretSigning = HashHmacSha256Encryption(secretService, Stop);
//签名字符串
byte[] signatureHmacSHA256 = HashHmacSha256Encryption(secretSigning, stringToSign);
//替换java DatatypeConverter.printHexBinary(d).toLowerCase()
StringBuilder builder = new StringBuilder();
for (byte b : signatureHmacSHA256) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' hex;
}
builder.append(hex);
}
String signature = builder.toString().toLowerCase();
//组装签名字符串
String authorization = Algorithm ' '
"Credential=" SecretId '/' credentialScope ", "
"SignedHeaders=" SignedHeaders ", "
"Signature=" signature;
//创建header 头部
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", authorization);
headers.put("Host", "iai.tencentcloudapi.com");
headers.put("Content-Type", "application/json; charset=utf-8");
headers.put("X-TC-Action", action);
headers.put("X-TC-Version", version);
headers.put("X-TC-Timestamp", timestamp);
//headers.put("X-TC-Region", "ap-chengdu");
//request 请求
String response = resquestPostData(Url, paramJson, headers);
return response;
}catch(Exception e){
return e.getMessage();
}
}
/*
* Function : 发送Post请求到服务器
* Param : params请求体内容,encode编码格式
*/
public static String resquestPostData(String strUrlPath, String data, Map<String, String> headers) {
try {
URL url = new URL(strUrlPath);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setConnectTimeout(3000); //设置连接超时时间
httpURLConnection.setDoInput(true); //打开输入流,以便从服务器获取数据
httpURLConnection.setDoOutput(true); //打开输出流,以便向服务器提交数据
httpURLConnection.setRequestMethod("POST"); //设置以Post方式提交数据
httpURLConnection.setUseCaches(false); //使用Post方式不能使用缓存
//设置header
if (headers.isEmpty()) {
//设置请求体的类型是文本类型
httpURLConnection.setRequestProperty("Content-Type", "application/json");
} else {
for (Map.Entry<String, String> entry : headers.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
httpURLConnection.setRequestProperty(key, value);
}
}
//设置请求体的长度
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(data.length()));
//获得输出流,向服务器写入数据
if (data != null && !TextUtils.isEmpty(data)) {
byte[] writebytes = data.getBytes();
// 设置文件长度
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(data.getBytes());
outputStream.flush();
}
int response = httpURLConnection.getResponseCode(); //获得服务器的响应码
if(response == HttpURLConnection.HTTP_OK) {
InputStream inptStream = httpURLConnection.getInputStream();
return dealResponseResult(inptStream); //处理服务器的响应结果
}
} catch (IOException e) {
return "err: " e.getMessage().toString();
}
return "-1";
}
/*
* Function : 封装请求体信息
* Param : params请求体内容,encode编码格式
*/
public static StringBuffer getRequestData(Map<String, String> params, String encode) {
StringBuffer stringBuffer = new StringBuffer(); //存储封装好的请求体信息
try {
for(Map.Entry<String, String> entry : params.entrySet()) {
stringBuffer.append(entry.getKey())
.append("=")
.append(URLEncoder.encode(entry.getValue(), encode))
.append("&");
}
stringBuffer.deleteCharAt(stringBuffer.length() - 1); //删除最后的一个"&"
} catch (Exception e) {
e.printStackTrace();
}
return stringBuffer;
}
/*
* Function : 处理服务器的响应结果(将输入流转化成字符串)
* Param : inputStream服务器的响应输入流
*/
public static String dealResponseResult(InputStream inputStream) {
String resultData = null; //存储处理结果
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int len = 0;
try {
while((len = inputStream.read(data)) != -1) {
byteArrayOutputStream.write(data, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
resultData = new String(byteArrayOutputStream.toByteArray());
return resultData;
}
/**
*
*/
private static String HashEncryption(String s) throws Exception {
MessageDigest sha = MessageDigest.getInstance("SHA-256");
sha.update(s.getBytes());
//替换java DatatypeConverter.printHexBinary(d).toLowerCase()
StringBuilder builder = new StringBuilder();
for (byte b : sha.digest()) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' hex;
}
builder.append(hex);
}
return builder.toString().toLowerCase();
}
private static byte[] HashHmacSha256Encryption(byte[] key, String msg) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
mac.init(secretKeySpec);
return mac.doFinal(msg.getBytes("UTF-8"));
}
}
人脸检测数据分析接口(src > main > java > com.xxx > FaceUtilsJson.java)
代码语言:javascript复制package com.example.faceiai;
/**
* 人脸检测与分析
*/
public class FaceUtilsJson{
public static String getGenderName(int Age) {
//性别处理
if (Age > 49) {
return "男性";
} else {
return "女性";
}
}
public static String getExpressionName(int Expression) {
if (Expression < 50) {
return "正常";
} else {
return "微笑";
}
}
public static String getMask(Boolean Mask){
if (Mask) {
return "佩戴口罩";
} else {
return "未佩戴口罩";
}
}
}
四、权限赋予 (src > main > AndroidManifest.xml)
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.faceiai">
<!--网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
<!--相册及拍照权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="com.miui.whetstone.permission.ACCESS_PROVIDER"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>