ZXing Android Embedded 实现二维码扫描
1.添加库
首先添加库的集成,在app/build.gradle中添加如下:
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
implementation 'com.google.zxing:core:3.3.0'
2.布局
布局文件主要有三个:
activity_main.xml:主活动
activity_scan.xml:扫描活动
content_scan.xml:扫描布局
主活动里就简单放了一个按键和Textview:
<?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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/text_result"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始"
android:id="@+id/button1"/>
</LinearLayout>
content_scan.xml如下:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.journeyapps.barcodescanner.BarcodeView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/zxing_barcode_surface"
app:zxing_framing_rect_width="250dp"
app:zxing_framing_rect_height="250dp"/>
<com.journeyapps.barcodescanner.ViewfinderView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/zxing_viewfinder_view"
app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
app:zxing_result_view="@color/zxing_custom_result_view"
app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask"/>
<TextView
android:id="@+id/zxing_status_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="@color/zxing_transparent"
android:text="@string/zxing_msg_default_status"
android:textColor="@color/zxing_status_text"/>
</merge>
在activity_scan.xml中添加com.journeyapps.barcodescanner.DecoratedBarcodeView,该DecoratedBarcodeView引用上述content_scan布局。另外还增加了一个用于开关闪光灯的ImageButton。如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/dbv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
app:zxing_scanner_layout="@layout/content_scan">
</com.journeyapps.barcodescanner.DecoratedBarcodeView>
<ImageButton
android:id="@+id/button_led"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:background="@drawable/image_bg_off"
/>
</RelativeLayout>
3. 权限
在AndroidManifest.xml中添加如下:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT" />
对于Android6.0以后的版本还需动态申请权限,在MainActivity中添加申请权限代码:
private void requsetPermission(){
if (Build.VERSION.SDK_INT>22){
if (ContextCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
//先判断有没有权限 ,没有就在这里进行权限的申请
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.CAMERA},1);
}else {
}
}else {
}
}
@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){
//这里已经获取到了摄像头的权限,想干嘛干嘛了可以
}else {
//这里是拒绝给APP摄像头权限,给个提示什么的说明一下都可以。
Toast.makeText(MainActivity.this,"请手动打开相机权限",Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
以下是是获取扫描结果,并显示:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if(result != null) {
if(result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
testResult.setText(result.getContents());
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
阿里oss
安装
- 在Maven项目中加入依赖项
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.5'
- 所需的Android权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- 混淆配置
-keep class com.alibaba.sdk.android.oss.** { *; }
-dontwarn okio.**
-dontwarn org.apache.commons.codec.binary.**
初始化
初始化一个 OSSClient 实例, OSSClient 的生命周期和应用程序的生命周期保持一致即可。在应用程序启动时创建一个ossClient,在应用程序结束时销毁即可。
- 设置EndPoint和凭证
使用STS鉴权模式,推荐使用OSSAuthCredentialProvider方式直接访问鉴权应用服务器,token过期后可以自动更新。
设置EndPoint和CredentialProvider示例如下:
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
String stsServer = "STS应用服务器地址,例如http://abc.com"
// 推荐使用OSSAuthCredentialsProvider。token过期可以及时更新。
OSSCredentialProvider credentialProvider = new OSSAuthCredentialsProvider(stsServer);
OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);
- 启用日志
通过调用OSSLog.enableLog()开启可以在控制台看到日志,并且会支持写入手机sd卡中的一份日志文件位置在内置sd卡路径\OSSLog\logs.csv 默认不开启,日志会记录oss操作行为中的请求数据,返回数据,异常信息,例如requestId,response header等
OSSLog.enableLog(); //调用此方法即可开启日志
- 设置网络参数
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 在移动端建议使用STS的方式初始化OSSClient。
OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider("<StsToken.AccessKeyId>", "<StsToken.SecretKeyId>", "<StsToken.SecurityToken>");
ClientConfiguration conf = new ClientConfiguration();
conf.setConnectionTimeout(15 * 1000); // 连接超时,默认15秒。
conf.setSocketTimeout(15 * 1000); // socket超时,默认15秒。
conf.setMaxConcurrentRequest(5); // 最大并发请求书,默认5个。
conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次。
OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider, conf);
- 对 SDK 中同步接口、异步接口的一些说明
同步接口调用后会阻塞等待结果返回,而异步接口需要在请求时传入回调函数,请求的执行结果将在回调中处理。
同步接口不能在UI线程调用。遇到异常时,将直接抛出ClientException或者ServiceException异常,前者指本地遇到的异常如网络异常、参数非法等;后者指OSS返回的服务异常,如鉴权失败、服务器错误等。
异步请求遇到异常时,异常会在回调函数中处理。
调用异步接口时,函数会直接返回一个Task,Task可以取消、等待直到完成、或者直接获取结果。如:
OSSAsyncTask task = oss.asyncGetObejct(...);
task.cancel(); // 可以取消任务
task.waitUntilFinished(); // 等待直到任务完成
GetObjectResult result = task.getResult(); // 阻塞等待结果返回
- 上传文件 以下代码用于将指定的本地文件上传到OSS:
// 构造上传请求。
PutObjectRequest put = new PutObjectRequest("<bucketName>", "<objectName>", "<uploadFilePath>");
// 异步上传时可以设置进度回调。
put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
@Override
public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
Log.d("PutObject", "UploadSuccess");
Log.d("ETag", result.getETag());
Log.d("RequestId", result.getRequestId());
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 请求异常。
if (clientExcepion != null) {
// 本地异常,如网络异常等。
clientExcepion.printStackTrace();
}
if (serviceException != null) {
// 服务异常。
Log.e("ErrorCode", serviceException.getErrorCode());
Log.e("RequestId", serviceException.getRequestId());
Log.e("HostId", serviceException.getHostId());
Log.e("RawMessage", serviceException.getRawMessage());
}
}
});
// task.cancel(); // 可以取消任务。
// task.waitUntilFinished(); // 等待上传完成。
- 下载指定文件 以下代码用于将指定的OSS文件下载到本地文件:
// 构造下载文件请求。
GetObjectRequest get = new GetObjectRequest("<bucketName>", "<objectName>");
OSSAsyncTask task = oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
@Override
public void onSuccess(GetObjectRequest request, GetObjectResult result) {
// 请求成功。
Log.d("asyncGetObject", "DownloadSuccess");
Log.d("Content-Length", "" + result.getContentLength());
InputStream inputStream = result.getObjectContent();
byte[] buffer = new byte[2048];
int len;
try {
while ((len = inputStream.read(buffer)) != -1) {
// 您可以在此处编写代码来处理下载的数据。
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
// GetObject请求成功,将返回GetObjectResult,其持有一个输入流的实例。返回的输入流,请自行处理。
public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 请求异常。
if (clientExcepion != null) {
// 本地异常,如网络异常等。
clientExcepion.printStackTrace();
}
if (serviceException != null) {
// 服务异常。
Log.e("ErrorCode", serviceException.getErrorCode());
Log.e("RequestId", serviceException.getRequestId());
Log.e("HostId", serviceException.getHostId());
Log.e("RawMessage", serviceException.getRawMessage());
}
}
});
// task.cancel(); // 可以取消任务。
// task.waitUntilFinished(); // 等待任务完成。
上传文件
- 分片上传流程
-
初始化一个分片上传事件。 调用oss.initMultipartUpload方法返回OSS创建的全局唯一的uploadId。
-
上传分片。 调用oss.uploadPart方法上传分片数据。
-
完成分片上传。 所有分片上传完成后,调用oss.CompleteMultipartUpload方法将所有分片合并成完整的文件。
- 分片上传完整示例
//初始化分片上传。
//InitiateMultipartUploadRequest用于指定上传文件的名称以及上传文件所属的存储空间的名称。
//objectKey等同于objectName,表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
InitiateMultipartUploadRequest init = new InitiateMultipartUploadRequest("<bucketName>", "<objectKey>");
InitiateMultipartUploadResult initResult = oss.initMultipartUpload(init);
//initResult返回的结果中包含UploadId,UploadId用于唯一标识本次Multipart Upload事件。
String uploadId = initResult.getUploadId();
//设置单个Part的大小,单位为Byte,取值范围为100 KB~5 GB。
int partCount = 100*1024;
//分片上传。
for (int i = 1; i < 5; i++) {
byte[] data = new byte[partCount];
RandomAccessFile raf = new RandomAccessFile("path", "r");
long skip = (i-1) * partCount;
raf.seek(skip);
raf.readFully(data, 0, partCount);
UploadPartRequest uploadPart = new UploadPartRequest();
uploadPart.setBucketName(mBucketName);
uploadPart.setObjectKey(objectKey);
uploadPart.setUploadId(uploadId);
uploadPart.setPartNumber(i); //上传的Part对应的PartNumber,从1开始标识。
uploadPart.setPartContent(data);
try {
oss.uploadPart(uploadPart);
} catch (ServiceException serviceException) {
OSSLog.logError(serviceException.getErrorCode());
}
}
//完成分片上传。
CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest("<bucketName>", "<objectName>", "<uploadId>", "<partETagList>";
//上传回调。完成分片上传请求时可以设置CALLBACK_SERVER参数,请求完成后会向指定的Server Address发送回调请求。可通过返回结果的completeResult.getServerCallbackReturnBody()查看servercallback结果。
complete.setCallbackParam(new HashMap<String, String>() {
{
put("callbackUrl", CALLBACK_SERVER); //修改为您的服务器地址。
put("callbackBody", "test");
}
});
CompleteMultipartUploadResult completeResult = oss.completeMultipartUpload(complete);
OSSLog.logError("-------------- serverCallback: " + completeResult.getServerCallbackReturnBody());
网易云信IM
网易云信IM 集成&关键类 总结
虹软
基于虹软SDK,适配Camera1、Camera2、CameraX,实现人脸识别(Android)
基于虹软公司的人脸识别引擎封装(.dll)
虹软人脸识别 C++ demo (vs)
虹软人脸识别 C++ SDK 2.0二次开发
虹软人脸识别 Android Demo --1:N比对实现
虹软人脸识别 C# demo --摄像头多人脸10万特征库
ai.arcsoft.com.cn/bbs/forum.p…