HTTP和HTTPS的区别
HTTP 超文本传输协议
HTTPS 安全套接字超文本传输协议
在布局文件中加入TextureView,然后对其进行监听
textureview = (TextureView) findViewById(R.id.textureView);
textureview.setSurfaceTextureListener(surfaceTextureListener);
当Textureview准备好,会回调surfacetexturelistener的onSurfaceAvailabale(),我们在预览之前给相机设置参数,然后打开相机
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//当SurefaceTexture可用的时候,设置相机参数并打开相机
setupCamera(width, height);
openCamera();
}
};
设置相机参数,主要是根据textureview的尺寸设置预览尺寸。
private void setupCamera(int width, int height) {
//获取摄像头的管理者CameraManager
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
//遍历所有摄像头
for (String cameraId: manager.getCameraIdList()) {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
//默认打开后置摄像头
if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT)
continue;
//获取StreamConfigurationMap,它是管理摄像头支持的所有输出格式和尺寸
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//根据TextureView的尺寸设置预览尺寸
mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);
mCameraId = cameraId;
break;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
打开相机,通过cameramanager打开相机,在状态回调中打开相机预览。
private void openCamera() {
//获取摄像头的管理者CameraManager
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
//检查权限
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
//打开相机,第一个参数指示打开哪个摄像头,第二个参数stateCallback为相机的状态回调接口,第三个参数用来确定Callback在哪个线程执行,为null的话就在当前线程执行
manager.openCamera(mCameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
//开启预览
startPreview();
}
}
通过textureview显示相机预览数据,camera2的拍照数据和预览数据都是通过cameracapturesession实现的。
private void startPreview() {
SurfaceTexture mSurfaceTexture = mTextureView.getSurfaceTexture();
//设置TextureView的缓冲区大小
mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
//获取Surface显示预览数据
Surface mSurface = new Surface(mSurfaceTexture);
try {
//创建CaptureRequestBuilder,TEMPLATE_PREVIEW比表示预览请求
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//设置Surface作为预览数据的显示界面
mCaptureRequestBuilder.addTarget(mSurface);
//创建相机捕获会话,第一个参数是捕获数据的输出Surface列表,第二个参数是CameraCaptureSession的状态回调接口,当它创建好后会回调onConfigured方法,第三个参数用来确定Callback在哪个线程执行,为null的话就在当前线程执行
mCameraDevice.createCaptureSession(Arrays.asList(mSurface), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
try {
//创建捕获请求
mCaptureRequest = mCaptureRequestBuilder.build();
mPreviewSession = session;
//设置反复捕获数据的请求,这样预览界面就会一直有数据显示
mPreviewSession.setRepeatingRequest(mCaptureRequest, mSessionCaptureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
S3 挂起到内存,就是常说的待机。计算机将目前的运行状态等数据存放在内存,关闭硬盘、外设等设备,进入等待状态。此时内存仍然需要电力维持其数据,但整机耗电很少。恢复时计算机从内存读出数据,回到挂起前的状态,恢复速度较快。对DDR的耗电情况进行优化是S3性能的关键,大多数手持设备都是用S3待机。
S4 挂起到硬盘,就是常说的休眠。把运行状态等数据存放在硬盘上某个文件或者某个特定的区域,关闭硬盘、外设等设备,进入关机状态。此时计算机完全关闭,不耗电。恢复时计算机从休眠文件/分区中读出数据,回到休眠前的状态,恢复速度较慢。电子书项目中,见过一款索尼的电子书,没有定义关机状态,只定义了S4,从而提高开机速度。
linux把电源接口框架都纳入了设备模型中,通过power_kobj对象的属性文件提供操作电源策略的接口。
linux的世界里,一切皆文件。通过state文件写入不同的值来让系统进入不同的电源状态,接收状态值的函数是state_store.
autosleep是Android内核为了跟主线内核兼容引入的,切换电源状态的入口函数是pm_suspend。针对嵌入式系统,s3是一种常见的节电状态,俗称待机。待机可以粗略分为5个阶段。
本人也是刚接触组件化不久,原项目是由几个分开的系统应用组成,目前做的只是将几个应用合并到同一项目下,将这几个应用拆分为几个模块并将其中通用的地方抽出来新建了几个基础组件和lib组件。
在这个过程中也踩了很多坑。总结下来主要是:
创建BaseApplication类,ModuleConfig类以及BaseApplicationImpl类。BaseApplication类的onCreate()方法中初始化一些全局配置并且初始化模块配置。BaseApplicationImpl类是一个接口类,需要各模块自己去实现各个模块的配置。这些配置的类是定义在ModuleConfig中,在初始化的时候会通过反射创建这些类。
// ------------BaseApplication------------
public class BaseApplication extends MultiDexApplication {
@Override
public void onCreate() {
super.onCreate();
// 初始化全局配置
initGlobalConfig();
// 初始化模块配置
initModuleConfit();
}
private void initGlobalConfig() {
// 初始化ARouter
initARouter();
}
private void initModuleConfit() {
for (String modules : ModuleConfig.MODULELIST){
try {
Class clz = Class.forName(modules);
Object obj = clz.newInstance();
if (obj instanceof BaseApplicationImp){
((BaseApplicationImp) obj).onCreate(this);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
private void initARouter() {
ARouter.openLog();
ARouter.openDebug();
ARouter.init(this);
}
}
// ------------BaseApplicationImp------------
public interface BaseApplicationImp{
void onCreate(Application application);
}
// ------------ModuleConfig-------------
public interface ModuleConfig {
static final String MODULE_PDFREADER = "com.dou.sample.mupdf_demo.BaseApplication";
static final String MODULE_LAUNCHER = "com.guowen.luncher.guowenreaderapp.app.AppContext";
public static final String[] MODULELIST = {
MODULE_LAUNCHER,
MODULE_PDFREADER
};
}
在各个子module中实现BaseApplicationImpl,这个类可以提供模块化的配置以及application context对象。清单文件都设置为BaseApplication即可。
原来的项目是每个应用都有一个application和baseapplication,现在baseapplication抽出来了,但是集成状态下只能用同一个application,组件状态下application也不同。
所以这里做了统一处理。不管是集成状态还是组件状态都设置application为baseapplication。baseapplication的oncreate方法主要有两个方法,加载全局配置和加载组件配置。加载全局配置比较简单,加载组件配置就是将组件的配置类在moduleconfig类中声明,然后通过遍历这些配置列表,通过反射加载baseapplicationimpl的实现类。如果是组件状态下直接会报找不到类异常也就不会加载别的module的配置。
因为之前项目的application类(单例模式)不仅会初始化配置还会提供一些静态成员和全局context,如果改动,项目代码也要修改很多。所以这里直接用这个类实现BaseApplicationImpl,将这个类的单例context设置baseapplication传递的对象。
集成测试主要针对不直接用用户交互的组件,比如service和contentprovider。
编写测试方法
@Test
public void testWithBoundService() throws TimeoutException {
// Create the service Intent.
Intent serviceIntent =
new Intent(InstrumentationRegistry.getTargetContext(),
LocalService.class);
// Data can be passed to the service via the Intent.
serviceIntent.putExtra(LocalService.SEED_KEY, 42L);
// Bind the service and grab a reference to the binder.
IBinder binder = mServiceRule.bindService(serviceIntent);
// Get the reference to the service, or you can call
// public methods on the binder directly.
LocalService service =
((LocalService.LocalBinder) binder).getService();
// Verify that the service is working correctly.
assertThat(service.getRandomInt(), is(any(Integer.class)));
}