fengfeilong0529 / android-notes Goto Github PK
View Code? Open in Web Editor NEWAsk myself one question at least every day!
Ask myself one question at least every day!
性能 | SurfaceView | TextureView |
---|---|---|
内存 | 低 | 高 |
绘制 | 及时 | 1-3帧的延迟 |
耗电 | 低 | 高 |
动画和截图 | 不支持 | 支持 |
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceView.setKeepScreenOn(true);
//打开摄像头,并且旋转90度
camera = Camera.open();
camera.setDisplayOrientation(90);
//Camera预览的数据回调:
camera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] bytes, Camera camera) {
//bytes即为相机采集出来的单帧Yuv格式数据,可转为Bitmap等格式使用
}
});
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
//surface创建了,绑定holder并开启预览
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
camera.release();
}
});
//相机的一些设置:
Camera.Parameters parameters = camera.getParameters();
//Camera Preview Callback的YUV420常用数据格式有两种:一个是NV21,一个是YV12。Android一般默认使用YUV_420_SP的格式(NV21)
parameters.setPreviewFormat(ImageFormat.NV21);//设置回调数据的格式
parameters.setPreviewSize(width,height); //对应手机的height和width
camera.setParameters(parameters);//传入参数
camera.setPreviewDisplay(surfaceHolder);
camera.setPreviewCallback(this);
camera.startPreview();
textureView = findViewById(R.id.texture_view);
textureView.setSurfaceTextureListener(this);
// 打开摄像头并将展示方向旋转90度
camera = Camera.open();
camera.setDisplayOrientation(90);
camera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] bytes, Camera camera) {
//这里面的Bytes的数据就是NV21格式的数据。
}
});
//------ Texture 预览 -------
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
try {
camera.setPreviewTexture(surfaceTexture);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
camera.release();//释放相机
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
camera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] bytes, Camera camera) {
//这里面的Bytes的数据就是NV21格式的数据。
//处理data,转为Bitmap显示到ImageView上
mPreviewSize = camera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
//转为YuvImage
YuvImage yuvimage = new YuvImage(
data,
ImageFormat.NV21,
mPreviewSize.width,
mPreviewSize.height,
null);
mBaos = new ByteArrayOutputStream();
//yuvimage 转换成jpg格式
yuvimage.compressToJpeg(new Rect(0, 0, mPreviewSize.width, mPreviewSize.height), 100, mBaos);// 80--JPG图片的质量[0-100],100最高
mImageBytes = mBaos.toByteArray();
//将mImageBytes转换成bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
mBitmap = BitmapFactory.decodeByteArray(mImageBytes, 0, mImageBytes.length, options);
icon.setImageBitmap(rotateBitmap(mBitmap,getDegree()));
}
});
/**
* 顺时针旋转bitmap
*/
public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postRotate(degress);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
/**
* 水平翻转bitmap
*
* @param bitmap
* @return
*/
public static Bitmap horMirrorBitmap(Bitmap bitmap) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postScale(-1, 1);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
/**
* 垂直翻转bitmap
*
* @param bitmap
* @return
*/
public static Bitmap verMirrorBitmap(Bitmap bitmap) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postScale(1, -1);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
if (Camera.getNumberOfCameras() > 1) {
if (camera != null) {
//切换摄像头要释放资源,否则会报错
camera.setPreviewCallback(null);
camera.stopPreview();
camera.lock();
camera.release();
camera = null;
}
if (!mIsFront) {
camera = open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} else {
camera = open(Camera.CameraInfo.CAMERA_FACING_BACK);
}
mIsFront = !mIsFront;
initCamParams();
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
camera.startFaceDetection();//一定要在startPreview()后调用
} else {
Toast.makeText(this, "没有可切换的摄像头", Toast.LENGTH_SHORT).show();
}
public Camera open() {
int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
return Camera.open(i);
}
return null;
}
其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。
public class CompressUtil {
private static final String TAG = "CompressUtil";
/**
* 质量压缩
* <p>
* 质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,
* 图片的长,宽,像素都不会改变,那么bitmap所占内存大小是不会变的
* <p>
* PS:对PNG图片无效,因为png是无损压缩
*
* @param bit
* @param quality 质量
* @return
*/
public static Bitmap qualityCompress(Bitmap bit, int quality) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bit.compress(Bitmap.CompressFormat.JPEG, quality, baos);
byte[] bytes = baos.toByteArray();
Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Log.i(TAG, "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M 宽度为" + bm.getWidth() + " 高度为" + bm.getHeight()
+ " bytes.length=" + (bytes.length / 1024) + "KB"
+ " quality=" + quality);
return bm;
}
/**
* 采样率压缩
* <p>
* 采样率压缩其原理是缩放bitamp的尺寸,通过调节其inSampleSize参数,比如调节为2,宽高会为原来的1/2,内存变回原来的1/4
* <p>
*
* @param context
* @param sampleSize 采样率
* @return
*/
public static Bitmap sampleSizeCompress(Context context, int sampleSize) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.mipmap.animal2, options);
Log.i(TAG, "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M 宽度为" + bm.getWidth() + " 高度为" + bm.getHeight());
return bm;
}
/**
* matrix缩放法压缩
* <p>
* 通过矩阵对图片进行裁剪,也是通过缩放图片尺寸,来达到压缩图片的效果,和采样率的原理一样
* <p>
*
* @param bit
* @param sx
* @param sy
* @return
*/
public static Bitmap matrixScaleCompress(Bitmap bit, float sx, float sy) {
Matrix matrix = new Matrix();
matrix.setScale(sx, sy);
Bitmap bm = Bitmap.createBitmap(bit, 0, 0, bit.getWidth(),
bit.getHeight(), matrix, true);
Log.i(TAG, "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M 宽度为" + bm.getWidth() + " 高度为" + bm.getHeight());
return bm;
}
/**
* RGB_565压缩
* <p>
* RGB_565压缩是通过改用内存占用更小的编码格式来达到压缩的效果。Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。
* 一般不建议使用ARGB_4444,因为画质实在是辣鸡,如果对透明度没有要求,建议可以改成RGB_565,相比ARGB_8888将节省一半的内存开销
* <p>
*
* @param context
* @return
*/
public static Bitmap RGB565Compress(Context context) {
BitmapFactory.Options options2 = new BitmapFactory.Options();
options2.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.mipmap.animal2, options2);
Log.i(TAG, "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
+ "M 宽度为" + bm.getWidth() + " 高度为" + bm.getHeight());
return bm;
}
/**
* 创建缩放Bitmap
* <p>
* 将图片压缩成用户所期望的长度和宽度,但是这里要说,如果用户期望的长度和宽度和原图长度宽度相差太多的话,图片会很不清晰
* <p>
*
* @param bit
* @param dstWidth
* @param dstHeight
* @return
*/
public static Bitmap createScaledBitmapCompress(Bitmap bit, int dstWidth, int dstHeight) {
Bitmap bm = Bitmap.createScaledBitmap(bit, dstWidth, dstHeight, true);
Log.i(TAG, "压缩后图片的大小" + (bm.getByteCount() / 1024) + "KB 宽度为"
+ bm.getWidth() + " 高度为" + bm.getHeight());
return bm;
}
/**
* 将图片压缩到指定size
* <p>
* 动态降低图片quality
*
* @param bit
* @param maxFileSize 最大文件大小,单位KB
*/
public static Bitmap compressBmp2LimitSize(Bitmap bit, int maxFileSize) {
//进行有损压缩
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
bit.compress(Bitmap.CompressFormat.JPEG, quality, baos); //质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小)
int baosLength = baos.toByteArray().length;
while (baosLength / 1024 > maxFileSize) { //循环判断如果压缩后图片是否大于maxMemmorrySize,大于继续压缩
baos.reset(); //重置baos即让下一次的写入覆盖之前的内容
quality = Math.max(0, quality - 10); //图片质量每次减少10
bit.compress(Bitmap.CompressFormat.JPEG, quality, baos); //将压缩后的图片保存到baos中
baosLength = baos.toByteArray().length;
if (quality == 0) //如果图片的质量已降到最低,则不再进行压缩
break;
}
Bitmap bm = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.toByteArray().length);
String tip = "压缩后图片的大小" + ((float) bm.getByteCount() / 1024 / 1024)
+ "M 宽度为" + bm.getWidth() + " 高度为" + bm.getHeight()
+ " bytes.length=" + (baos.toByteArray().length / 1024) + "KB"
+ " quality=" + quality;
Log.i(TAG, tip);
return bm;
}
}
参考:
private File cameraSavePath;//拍照照片路径
private Uri mUri;
private String photoName = System.currentTimeMillis() + ".jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
cameraSavePath = new File(Environment.getExternalStorageDirectory().getPath() + "/" + photoName);
}
/**
* 从相册获取照片
*/
public void takePhotoByAlbum() {
checkReadStoragePermission();
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, ALBUM_REQUEST_CODE);
}
/**
* 拍照获取照片
*/
private void takePhotoByCamera() {
checkCameraPermission();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mUri = FileProvider.getUriForFile(MainActivity.this, "com.example.hxd.pictest.fileprovider", cameraSavePath);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
mUri = Uri.fromFile(cameraSavePath);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
MainActivity.this.startActivityForResult(intent, CAMERA_REQUEST_CODE);
}
/**
* 裁剪照片
*
* @param uri
*/
public void cropImg(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", true);
// 裁剪框的比例,1:1
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// 裁剪后输出图片的尺寸大小
intent.putExtra("outputX", 250);
intent.putExtra("outputY", 250);
intent.putExtra("outputFormat", "JPEG");// 图片格式
intent.putExtra("noFaceDetection", true);// 取消人脸识别
intent.putExtra("return-data", true);
startActivityForResult(intent, REQUEST_CUT_PHOTO);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == ALBUM_REQUEST_CODE) {
try {
cropImg(data.getData());
} catch (Exception e) {
e.printStackTrace();
}
} else if (requestCode == CAMERA_REQUEST_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
cropImg(Uri.fromFile(cameraSavePath));
} else {
cropImg(mUri);
}
} else if (requestCode == REQUEST_CUT_PHOTO) {
try {
Bundle bundle = data.getExtras();
if (bundle != null) {
//在这里获得了剪裁后的Bitmap对象,可以用于上传
Bitmap image = bundle.getParcelable("data");
mIvCropedImg.setImageBitmap(image);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
参考:
https://www.jianshu.com/p/e97d55262bd4
https://www.jianshu.com/p/05f85f2f74c1
/**
* 调用本地GPS来获取经纬度
* @param context
*/
private void getLocation(Context context) {
//1.获取位置管理器
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//2.获取位置提供器,GPS或是NetWork
List<String> providers = locationManager.getProviders(true);
if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
//如果是网络定位
locationProvider = LocationManager.NETWORK_PROVIDER;
} else if (providers.contains(LocationManager.GPS_PROVIDER)) {
//如果是GPS定位
locationProvider = LocationManager.GPS_PROVIDER;
} else if (providers.contains(LocationManager.PASSIVE_PROVIDER)) {
//如果是PASSIVE定位
locationProvider = LocationManager.PASSIVE_PROVIDER;
}
else {
Toast.makeText(this, "没有可用的位置提供器", Toast.LENGTH_SHORT).show();
return;
}
//3.获取上次的位置,一般第一次运行,此值为null
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
Location location = locationManager.getLastKnownLocation(locationProvider);
if (location != null) {
showLocation(location);
} else {
// 监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
locationManager.requestLocationUpdates(locationProvider, MIN_TIME, MIN_DISTANCE, mListener);
}
}
LocationListener mListener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
// 如果位置发生变化,重新显示
@Override
public void onLocationChanged(Location location) {
showLocation(location);
}
};
/**
* 获取经纬度
* @param location
*/
private void showLocation(Location location) {
longtitude=String.valueOf(location.getLongitude());
latitude=String.valueOf(location.getLatitude());
Log.e("经纬度信息:",longtitude+" "+latitude);
}
待做......
https://www.jianshu.com/p/3c2399964135
http://c.biancheng.net/view/3217.html
https://github.com/fengfeilong0529/LinphoneDemo
https://github.com/BelledonneCommunications/linphone-android (sample)
线程池中的execute方法大家都不陌生,即开启线程执行池中的任务。还有一个方法submit也可以做到,它的功能是提交指定的任务去执行并且返回Future对象,即执行的结果。下面简要介绍一下两者的三个区别:
用到返回值的例子,比如说我有很多个做validation的task,我希望所有的task执行完,然后每个task告诉我它的执行结果,是成功还是失败,如果是失败,原因是什么。
然后我就可以把所有失败的原因综合起来发给调用者。
个人觉得cancel execution这个用处不大,很少有需要去取消执行的。
而最大的用处应该是第二点。
意思就是如果你在你的task里会抛出checked或者unchecked exception,
而你又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过捕获Future.get抛出的异常。
下面一个小程序演示一下submit方法
public class RunnableTestMain {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
/**
* execute(Runnable x) 没有返回值。可以执行任务,但无法判断任务是否成功完成。
*/
pool.execute(new RunnableTest("Task1"));
/**
* submit(Runnable x) 返回一个future。可以用这个future来判断任务是否成功完成。请看下面:
*/
Future future = pool.submit(new RunnableTest("Task2"));
try {
if(future.get()==null){//如果Future's get返回null,任务完成
System.out.println("任务完成");
}
} catch (InterruptedException e) {
} catch (ExecutionException e) {
//否则我们可以看看任务失败的原因是什么
System.out.println(e.getCause().getMessage());
}
}
}
public class RunnableTest implements Runnable {
private String taskName;
public RunnableTest(final String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
System.out.println("Inside "+taskName);
throw new RuntimeException("RuntimeException from inside " + taskName);
}
}
1、键值对
2、json数据
3、表单数据
4、文件
参考:https://blog.csdn.net/My_TrueLove/article/details/52240558
如果我们很关心某个变变量的变化过程,一般会使用Log打印一堆值来观察,观察完了再删除,说真的有点麻烦。这时候,你需要日志断点,看图:
参考:https://www.jianshu.com/p/3bb301c302e8
demo:https://github.com/fengfeilong0529/Fig-FaceDetection
调用camera.startFaceDetection()开启人脸检测;
调用camera.stopFaceDetection()停止人脸检测;
调用camera.setFaceDetectionListener()监听人脸,会返回face,包含人脸框坐标,眼睛嘴巴等Point,可根据坐标进行人脸画框,Camera.Face属性如图:
Rect:人脸的边界。它所使用的坐标系中,左上角的坐标是(-1000,-1000),右下角的坐标是(1000,1000)
例如:假设屏幕的尺寸是1280 * 720,有一个矩形在相机的坐标系中的位置是(-1000,-1000,0,0),它相对应的在安卓屏幕坐标系中的位置就是(0,0,360,640),如下图:
List<RectF> rects = new ArrayList<>();
//返回的face.rect坐标需做转换
Matrix matrix = new Matrix();
boolean mirror = mIsFront;//前置摄像头需做镜像翻转
matrix.setScale(mirror ? -1 : 1, 1);
matrix.postRotate(90);//setDisplayOrientation的角度
matrix.postScale(mSurfaceview.getWidth() / 2000f, mSurfaceview.getHeight() / 2000f);
matrix.postTranslate(mSurfaceview.getWidth() / 2f, mSurfaceview.getHeight() / 2f);
for (Camera.Face face : faces) {
RectF srcRect = new RectF(face.rect);
RectF dstRect = new RectF(0f, 0f, 0f, 0f);
matrix.mapRect(dstRect, srcRect);
rects.add(dstRect);
}
mDetectView.onDetectFace(rects);
public class DetectView extends View {
private Paint mPaint;
private Paint mEyePaint;
private List<Point> leftEyes;
private List<Point> rightEyes;
private List<RectF> rects;
public DetectView(Context context) {
this(context, null);
}
public DetectView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.GREEN);
float mStrokeWidth = 6;
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mEyePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mEyePaint.setColor(Color.RED);
mEyePaint.setStrokeWidth(mStrokeWidth);
mEyePaint.setDither(true);
mEyePaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
try {
for (Point leftEye : leftEyes) {
canvas.drawPoint(leftEye.x, leftEye.y, mEyePaint);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
for (Point rightEye : rightEyes) {
canvas.drawPoint(rightEye.x, rightEye.y, mEyePaint);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
for (RectF rect : rects) {
canvas.drawRect(rect, mPaint);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void onDetectEyes(List<Point> leftEyes, List<Point> rightEyes) {
this.leftEyes = leftEyes;
this.rightEyes = rightEyes;
invalidate();
}
public void onDetectFace(List<RectF> rects) {
this.rects = rects;
invalidate();
}
}
参考:http://c.biancheng.net/view/3190.html
demo:https://github.com/fengfeilong0529/WifiDirectDemo
官方:https://developer.android.google.cn/jetpack/androidx/releases/viewpager2
参考:
public interface Fruit{
String name();
}
public class Apple implements Fruit{
@Override
private String name() {
return "Apple";
}
}
public class Orange implements Fruit{
@Override
private String name() {
return "Orange";
}
}
public class Pear implements Fruit{
@Override
private String name() {
return "Pear";
}
}
public class FruitFactory {
//根据传入类型生产不同水果
public static Fruit newInstance(String type) {
if (type.equals("apple")) {
Fruit apple= new Apple();
return apple;
} else if(type.equals("orange")) {
Fruit orange= new Orange();
return orange;
} else if(type.equals("pear")) {
Fruit pear= new Pear();
return pear;
} else {
System.out.println("生产不出来");
return null;
}
}
}
public class SampleFactory1 {
//传入class
public static Fruit newInstance(Class c) {
Fruit fruit = null;
try {
fruit = (Fruit) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
System.out.println("不支持抽象类或接口");
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
System.out.println("没有足够权限,即不能访问私有对象");
} catch (ClassNotFoundException e) {
System.out.println("类不存在");
e.printStackTrace();
}
return fruit;
}
}
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
/**
* Https 证书工具类
*/
public class SSLUtil {
//使用命令keytool -printcert -rfc -file srca.cer 导出证书为字符串,然后将字符串转换为输入流,如果使用的是okhttp可以直接使用new Buffer().writeUtf8(s).inputStream()
/**
* 返回SSLSocketFactory
*
* @param certificates 证书的输入流
* @return SSLSocketFactory
*/
public static SSLSocketFactory getSSLSocketFactory(InputStream... certificates) {
return getSSLSocketFactory(null, certificates);
}
/**
* 双向认证
*
* @param keyManagers KeyManager[]
* @param certificates 证书的输入流
* @return SSLSocketFactory
*/
public static SSLSocketFactory getSSLSocketFactory(KeyManager[] keyManagers, InputStream... certificates) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
try {
if (certificate != null)
certificate.close();
} catch (IOException e) {
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(keyManagers, trustManagerFactory.getTrustManagers(), new SecureRandom());
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
return socketFactory;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获得双向认证所需的参数
*
* @param bks bks证书的输入流
* @param keystorePass 秘钥
* @return KeyManager[]对象
*/
public static KeyManager[] getKeyManagers(InputStream bks, String keystorePass) {
KeyStore clientKeyStore = null;
try {
clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(bks, keystorePass.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, keystorePass.toCharArray());
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
return keyManagers;
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public RequestManager() {
try {
mSslSocketFactory = SSLUtil.getSSLSocketFactory(MyApp.getInstance().getAssets().open("abc.cer")); //SSL证书
} catch (IOException e) {
e.printStackTrace();
}
}
private OkHttpClient getHttpClient() {
if (mOkHttpClient == null){
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(5, TimeUnit.SECONDS);
builder.readTimeout(5, TimeUnit.SECONDS);
builder.writeTimeout(5, TimeUnit.SECONDS);
if (mSslSocketFactory != null){
builder.sslSocketFactory(mSslSocketFactory);
}
mOkHttpClient = builder.build();
}
return mOkHttpClient;
}
byte[] data = preSurfaceView.takePhoto(); //相机抓拍的单帧数据
if (data != null) {
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, PreviewHandle.CAMERA_WIDTH, PreviewHandle.CAMERA_HEIGHT, null);
mBitmap = YuvUtil.compressYuvToBitmap(yuvImage, 100);
ivAvatar.setImageBitmap(mBitmap);
}
public static Bitmap compressYuvToBitmap(YuvImage yuvImage, int quality) {
Rect fullRect = new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight());
byte[] bytes = compressYuvToJpg(yuvImage, fullRect, quality);
return bytes2Bimap(bytes);
}
public static byte[] compressYuvToJpg(YuvImage yuvImage, int quality) {
Rect fullRect = new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight());
return compressYuvToJpg(yuvImage, fullRect, quality);
}
public static byte[] compressYuvToJpg(YuvImage yuvImage, Rect cutRect, int quality) {
if (yuvImage != null) {
ByteArrayOutputStream baos = null;
byte[] datas = null;
;
try {
baos = new ByteArrayOutputStream();
yuvImage.compressToJpeg(cutRect, quality, baos);
datas = baos.toByteArray();
baos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return datas;
}
return null;
}
参考:https://www.jianshu.com/p/7436d6ccc7bf
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
/**
* 使用RenderScript将视频YUV流转换为BMP
* 注:这个类适用于CameraPreview不变的情况
*/
public class FastYUVtoRGB {
private RenderScript rs;
private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
private Type.Builder yuvType, rgbaType;
private Allocation in, out;
public FastYUVtoRGB(Context context) {
rs = RenderScript.create(context);
yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
}
public Bitmap convertYUVtoRGB(byte[] yuvData, int width, int height) {
if (yuvType == null) {
yuvType = new Type.Builder(rs, Element.U8(rs)).setX(yuvData.length);
in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
}
in.copyFrom(yuvData);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
out.copyTo(bmpout);
return bmpout;
}
}
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
View viewById = group.findViewById(checkedId);
if (viewById != null && viewById.isPressed()) {
//点击触发的回调
} else {
//调用check()方法触发的回调
}
}
});
implementation 'com.yanzhenjie:andserver:1.1.4'
public class HttpServer {
private static final String TAG = "HttpServer";
private static final String URL_ADD_CARD = "/addCard";
private static final String URL_DELETE_CARD = "/deleteCard";
private Server server;
private static final class Holder {
private static final HttpServer INSTANCE = new HttpServer();
}
public static HttpServer getInstance() {
return HttpServer.Holder.INSTANCE;
}
private HttpServer() {
RxBus.get().register(this);
}
public void init() {
InetAddress addr = NetUtils.getLocalIPAddress();
if (addr != null) {
init(addr);
}
}
public void reInit() {
deinit();
init();
}
private void init(InetAddress addr) {
synchronized (this) {
server = AndServer.serverBuilder()
.port(6666)
.timeout(10, TimeUnit.SECONDS)
.inetAddress(addr)
.listener(serverListener)
.registerHandler(URL_ADD_CARD, new AddCardHandler())
.registerHandler(URL_DELETE_CARD, new DeleteCardHandler())
.build();
if (!server.isRunning()){
server.startup();
}
}
}
private void deinit() {
synchronized (this) {
if (server != null) {
server.shutdown();
}
}
}
private Server.ServerListener serverListener = new Server.ServerListener() {
@Override
public void onStarted() {
Log.d(TAG, "HttpServer started");
}
@Override
public void onStopped() {
Log.d(TAG, "HttpServer onStopped");
}
@Override
public void onError(Exception e) {
Log.d(TAG, "HttpServer onError:" + e.getMessage());
}
};
}
public class AddCardHandler implements RequestHandler {
private static final String TAG = "AddCardHandler";
@RequestMapping(method = {RequestMethod.POST})
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
StringBuilder builder = new StringBuilder();
BaseResponse baseResponse = new BaseResponse(0, "添加成功");
String content = HttpRequestParser.getContent(request);
AddCardBean addCardBean = new Gson().fromJson(content, AddCardBean.class);
if (addCardBean != null) {
String name = addCardBean.getName();
String idNum = addCardBean.getIdnum();
String photo = addCardBean.getPhoto();
String gender = addCardBean.getGender();
String nation = addCardBean.getNation();
String address = addCardBean.getAddress();
String validStart = addCardBean.getValid_start();
String validEnd = addCardBean.getValid_end();
if (TextUtils.isEmpty(name)) {
builder.append("name不能为空,");
}
if (TextUtils.isEmpty(idNum)) {
builder.append("idNum不能为空,");
}
if (TextUtils.isEmpty(photo)) {
builder.append("photo不能为空,");
}
if (TextUtils.isEmpty(validStart)) {
builder.append("validStart不能为空,");
}
if (TextUtils.isEmpty(validEnd)) {
builder.append("validEnd不能为空,");
}
if (!TextUtils.isEmpty(builder.toString())) {
baseResponse.code = 1;
baseResponse.msg = builder.toString();
} else {
//添加名单
CardBean cardBean = new CardBean();
cardBean.setName(name);
cardBean.setSex(gender);
cardBean.setNation(nation);
cardBean.setIdNum(idNum);
cardBean.setAddress(address);
cardBean.setUserType(UserType.TYPE_WHITE);
cardBean.setValidStart(validStart);
cardBean.setValidEnd(validEnd);
Log.i(TAG, "handle: " + cardBean.toString());
//解析base64图片
Bitmap bitmap = FileUtil.base64StringToBitmap(photo);
String error = CardManager.getInstance().addCard(bitmap, idNum + Constants.JPG, cardBean);
RxBus.get().post(new RxUserChange());
if (!TextUtils.isEmpty(error)) {
baseResponse.code = 1;
baseResponse.msg = error;
}
}
} else {
baseResponse.code = 1;
baseResponse.msg = "参数错误";
}
response.setEntity(new StringEntity(new Gson().toJson(baseResponse), "utf-8"));
}
}
public class DeleteCardHandler implements RequestHandler {
private static final String TAG = "DeleteCardHandler";
@RequestMapping(method = {RequestMethod.POST})
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
StringBuilder builder = new StringBuilder();
BaseResponse baseResponse = new BaseResponse(0, "删除成功");
String content = HttpRequestParser.getContent(request);
DeleteCardBean deleteCardBean = new Gson().fromJson(content, DeleteCardBean.class);
if (deleteCardBean != null) {
List<String> idnums = deleteCardBean.getIdnum();
if (idnums.size() == 0) {
builder.append("idnum不能为空");
}
if (!TextUtils.isEmpty(builder.toString())) {
baseResponse.code = 1;
baseResponse.msg = builder.toString();
} else {
//删除名单
for (String idnum : idnums) {
CardManager.getInstance().deleteCard(idnum);
RxBus.get().post(new RxUserChange());
}
}
} else {
baseResponse.code = 1;
baseResponse.msg = "参数错误";
}
response.setEntity(new StringEntity(new Gson().toJson(baseResponse), "utf-8"));
}
}
HttpServer.getInstance().init();// 开启http服务
adb shell dumpsys activity---------------查看ActvityManagerService 所有信息
adb shell dumpsys activity activities----------查看Activity组件信息
adb shell dumpsys activity services-----------查看Service组件信息
adb shell dumpsys activity providers----------产看ContentProvider组件信息
adb shell dumpsys activity broadcasts--------查看BraodcastReceiver信息
adb shell dumpsys activity intents--------------查看Intent信息
adb shell dumpsys activity processes---------查看进程信息
adb shell dumpsys activity activities | findstr mResumedActivity---------查看当前获取焦点的Activity
......
private class myBackRunnable implements Runnable{
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mainHandler.post(new myUIRunnable());
}
}
private class myUIRunnable implements Runnable{
@Override
public void run() {
btnStart.setText("线程结束");
}
}
backHandler = new Handler(handlerThread.getLooper());
mainHandler = new Handler(getMainLooper());
backHandler.post(new myBackRunnable());
public class MyAsyncTask extends AsyncTask<Integer, String, String> {
private Button btn;
public MyAsyncTask(Button btn) {
super();
this.btn = btn;
}
//该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置
@Override
protected void onPreExecute() {
btn.setText("开始执行异步线程");
}
@Override
protected String doInBackground(Integer... integers) {
Log.e("xxxxxx","xxxxxxexecute传入参数="+integers[0]);
try {
Thread.sleep(1000);
publishProgress("过了一秒");
Thread.sleep(1000);
publishProgress("过了两秒");
Thread.sleep(1000);
publishProgress("过了三秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "doInBackground的返回";
}
/**
* 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)
* 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置
*/
@Override
protected void onPostExecute(String result) {
btn.setText("线程结束" + result);
}
/**
* 这里的Intege参数对应AsyncTask中的第二个参数
* 在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行
* onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作
*/
@Override
protected void onProgressUpdate(String... values) {
String vlaue = values[0]+"";
Log.e("xxxxxx","xxxxxx vlaue="+vlaue);
btn.setText(vlaue+"");
}
}
//调用
myAsyncTask.execute(1000);
AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。
AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。
对应到上面的demo就是Integer, String, String。
onPreExecute() 这里相当于线程的开始,可以进行UI的处理
doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
onProgressUpdate(String... Progress) 这里对应的是doInBackground中调用的publicProgress,在这里进行处理,这里是UI主线程可以进行界面的更新
onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回。
public class MyIntentService extends IntentService {
public MyIntentService() {
super("");
}
@Override
protected void onHandleIntent(Intent intent) {
try {
Thread.sleep(3*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent intentresult = new Intent(IntentServiceActivity.RESULT);
sendBroadcast(intentresult);
}
public void onDestroy()
{
super.onDestroy();
}
}
//调用
Intent intent=new Intent(IntentServiceActivity.this,MyIntentService.class);
startService(intent);
Observable.create(new ObservableOnSubscribe<BaseResponse>() {
@Override
public void subscribe(ObservableEmitter<BaseResponse> e) throws Exception {
}
})
.subscribeOn(Schedulers.io()) //执行在子线程
.observeOn(AndroidSchedulers.mainThread()) //回调在主线程
.subscribe(new Consumer<BaseResponse>() {
@Override
public void accept(BaseResponse baseResponse) throws Exception {
}
});
https://www.jianshu.com/p/00b130319864
https://blog.csdn.net/xiankog/article/details/83111766
“CMake”即“cross platform make”,跨平台安装工具,可以通过简单的命令语句来执行构建,编译,生成的操作,他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。构建的组态档为CMakeLists.txt文件,CMake 支持 in-place 建构(二进档和源代码在同一个目录树中)和 out-of-place 建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake 也支持静态与动态程式库的建构。
参考:https://www.runoob.com/design-pattern/builder-pattern.html
相关参考:https://blog.csdn.net/zcn596785154/article/details/77088517
命令:java -jar signapk.jar cert.x509.pem private.pk8 unsigned.apk signed.apk
jar和脚本地址:https://github.com/fengfeilong0529/Android-Notes/blob/master/platform_sign_shellAndjar.zip
实现方式:
/**
* android 8.0前 创建Wifi热点
*/
public boolean createWifiApBeforeAndroidO(Context context, String ssid, String psk) {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
//如果wifi处于打开状态,则关闭wifi,
if (wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(false);
}
if (isWifiApEnable(context)) {
closeWifiAp(context);
}
WifiConfiguration config = new WifiConfiguration();
if (TextUtils.isEmpty(psk)) {
config.SSID = ssid;
config.hiddenSSID = false;
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
} else {
config.SSID = ssid;
config.hiddenSSID = false;
config.preSharedKey = psk;
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);//开放系统认证
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
}
try {
//通过反射调用设置热点
Method method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
boolean result = (Boolean) method.invoke(wifiManager, config, true);
return result;
} catch (Exception e) {
CatchUtil.handle(e);
return false;
}
}
/**
* 8.0前 关闭WiFi热点
*/
public boolean closeWifiAp(Context context) {
try {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);
Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
boolean result = (Boolean) method2.invoke(wifiManager, config, false);
return result;
} catch (Exception e) {
CatchUtil.handle(e);
return false;
}
}
/**
* Android 8.0以上开启热点
*
* @param context
*/
public void openApAfterAndroidO(Context context) {
try {
WifiUtil.getWifiManager(context).startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
mReservantion = reservation;
String ssid = reservation.getWifiConfiguration().SSID;
String psk = reservation.getWifiConfiguration().preSharedKey;
Log.d(TAG, "onStarted: " + ssid + " psk:" + psk);
RxBus.get().post(new RxApInfo(ssid, psk));
}
@Override
public void onStopped() {
super.onStopped();
Log.d(TAG, "onStopped: ");
}
@Override
public void onFailed(int reason) {
super.onFailed(reason);
Log.d(TAG, "onFailed: " + reason);
}
}, new Handler());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Android 8.0以上关闭热点
*
* @param context
*/
public void closeWifiApAfterAndroidO(Context context) {
try {
WifiManager wifiManager = WifiUtil.getWifiManager(context);
//如果wifi处于打开状态,则关闭wifi,
if (wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(false);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mReservantion != null) {
mReservantion.close();
mReservantion = null;
}
}
Method method = wifiManager.getClass().getMethod("cancelLocalOnlyHotspotRequest");
method.setAccessible(true);
method.invoke(wifiManager);
System.out.println("已关闭热点");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
//WRITE_SETTINGS需跳转界面用户手动打开:
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
/**
* 请求权限
*/
private boolean checkApPremission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.System.canWrite(this)) {
return true;
} else {
return false;
}
} else {
return true;
}
}
//请求write_settings权限
public static void goManageWriteSettings(Activity context) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + context.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
//开启热点
if (checkApPremission()) {
//todo 开启热点
} else {
goManageWriteSettings(this);
}
在调Camera的时候有个回调方法onPreviewFrame是返回摄像头每一帧的图像数据的,当我们需要对图像数据做处理时就需要Nv21转Bitmap,下面介绍两种方式第一种方式只需要几毫秒时间,第二种方式需要几十毫秒。
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
public class NV21ToBitmap {
private RenderScript rs;
private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
private Type.Builder yuvType, rgbaType;
private Allocation in, out;
public NV21ToBitmap(Context context) {
rs = RenderScript.create(context);
yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
}
public Bitmap nv21ToBitmap(byte[] nv21, int width, int height){
if (yuvType == null){
yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
}
in.copyFrom(nv21);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
out.copyTo(bmpout);
return bmpout;
}
}
private static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
Bitmap bitmap = null;
try {
YuvImage image = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, width, height), 80, stream);
bitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
参考:
https://blog.csdn.net/bluegodisplay/article/details/53431798
https://blog.csdn.net/qq1137830424/article/details/81980673
Wiegand协议是国际上统一的标准,是由摩托罗拉公司制定的一种通讯协议。它适用于涉及门禁控制系统的读卡器和卡片的许多特性。 它有很多格式,标准的26-bit 应该是最常用的格式。此外,还有34-bit 、37-bit 等格式。 而标准26-bit 格式是一个开放式的格式,这就意味着任何人都可以购买某一特定格式的IC卡,并且这些特定格式的种类是公开可选的。26-Bit格式就是一个广泛使用的工业标准,并且对所有IC卡的用户开放。几乎所有的门禁控制系统都接受标准的26-Bit格式。
参考:
//静默安装
private void installSlient() {
String cmd = "pm install -r /mnt/sdcard/test.apk";
Process process = null;
DataOutputStream os = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;
try {
//静默安装需要root权限
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.write(cmd.getBytes());
os.writeBytes("\n");
os.writeBytes("exit\n");
os.flush();
//执行命令
process.waitFor();
//获取返回结果
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s;
while ((s = successResult.readLine()) != null) {
successMsg.append(s);
}
while ((s = errorResult.readLine()) != null) {
errorMsg.append(s);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
if (process != null) {
process.destroy();
}
if (successResult != null) {
successResult.close();
}
if (errorResult != null) {
errorResult.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//显示结果
tvTest.setText("成功消息:" + successMsg.toString() + "\n" + "错误消息: " + errorMsg.toString());
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.