项目构思
界面构成
主界面布局
activity_main.xml
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="50dp"
tools:context=".MainActivity">
<Button
android:id="@+id/changeFlashBtn"
android:layout_width="80dp"
android:layout_height="140dp"
android:layout_gravity="center"
android:text="开启"
android:textSize="30sp"/>
</LinearLayout>
因为只是一个手电筒项目所以界面比较简单,只需要一个居中的按钮就可以了
自定义Dialog布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/dialogTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="手电筒"
android:textSize="20sp"
android:layout_gravity="center_horizontal"/>
<TextView
android:id="@+id/dialogContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/dialogConfirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="确认"/>
<View
android:layout_width="20dp"
android:layout_height="2dp"/>
<Button
android:id="@+id/dialogCancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="取消"/>
</LinearLayout>
</LinearLayout>
代码逻辑
概览
项目中实现了一个MainActivity一个BaseActivity和一个工具类。MainActivity中实现了逻辑相关的操作,BaseActivity中实现了自定义log相关的功能,工具类中实现了获取闪光灯组件等方法。
BaseActivity
这里面定义了两个自定义Dialog的方法,当点击Dialog的确认按钮的时候就会进行闪光灯开启流程
public class BaseActivity extends AppCompatActivity {
static Button changeFlashBtn;
/**
* 自定义手电筒开启Dialog
* @param context
*/
public void openFlashDialog(Context context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.dialog_custom,null);
TextView dialogContent = view.findViewById(R.id.dialogContent);
dialogContent.setText("是否开启手电筒");
final Dialog dialog = builder.create();
dialog.show();
dialog.getWindow().setContentView(view);
Button confirmBtn = view.findViewById(R.id.dialogConfirm);
Button cancelBtn = view.findViewById(R.id.dialogCancel);
confirmBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
FlashLightUtil.FlashStatus = true;
changeFlashBtn.setText("关闭");
try {
FlashLightUtil.openFlash(context);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
});
cancelBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
/**
* 自定义手电筒关闭Dialog
* @param context
*/
public void closeFlashDialog(Context context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.dialog_custom,null);
TextView dialogContent = view.findViewById(R.id.dialogContent);
dialogContent.setText("是否关闭手电筒");
final Dialog dialog = builder.create();
dialog.show();
dialog.getWindow().setContentView(view);
Button confirmBtn = view.findViewById(R.id.dialogConfirm);
Button cancelBtn = view.findViewById(R.id.dialogCancel);
confirmBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FlashLightUtil.FlashStatus = false;
changeFlashBtn.setText("开启");
dialog.dismiss();
try {
FlashLightUtil.closeFlash(context);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
});
cancelBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
}
MainActivity
public class MainActivity extends BaseActivity{
String TAG = "MainActivity";
static final int REQUEST_CODE = 5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
changeFlashBtn = findViewById(R.id.changeFlashBtn);
//弹窗获取权限
if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},REQUEST_CODE);
}
//初始化
try {
FlashLightUtil.init(MainActivity.this);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
changeFlashBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!FlashLightUtil.FlashStatus){
openFlashDialog(MainActivity.this);
}else {
closeFlashDialog(MainActivity.this);
}
}
});
}
//按返回键关闭摄像头
@Override
public void onBackPressed() {
super.onBackPressed();
try {
FlashLightUtil.closeFlash(MainActivity.this);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
//获取权限弹窗的回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode != REQUEST_CODE ||grantResults[0]!=PackageManager.PERMISSION_GRANTED){
Log.d(TAG, "onRequestPermissionsResult: 获取授权失败");
//若未获取权限则关闭应用
this.finish();
}else if (isSupport()){
//若获取了并且设备支持则初始化CamaraManager
try {
FlashLightUtil.init(MainActivity.this);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
}
}
FlashLightUtil
public class FlashLightUtil {
public FlashLightUtil() {
}
public static CameraManager cameraManager;
private static String cameraId;
static String TAG = "FlashLightUtil";
private static Handler handler;
public static Boolean FlashStatus = false;
//手电筒状态改变回调
private static final CameraManager.TorchCallback torchCallback = new CameraManager.TorchCallback() {
@Override
public void onTorchModeUnavailable(@NonNull String cameraId) {
super.onTorchModeUnavailable(cameraId);
}
@Override
public void onTorchModeChanged(@NonNull String cameraId, boolean enabled) {
super.onTorchModeChanged(cameraId, enabled);
//如果手电筒状态与记录状态不相符则改变
Log.d(TAG, "onTorchModeChanged: 手电筒状态改变了");
if (FlashStatus !=enabled){
if (FlashStatus){
changeFlashBtn.setText("开启");
}else {
changeFlashBtn.setText("关闭");
}
FlashStatus = !FlashStatus;
Log.d(TAG, "onTorchModeChanged: 外界改变手电筒状态");
}
}
};
/**
* 判=断是否API大于26的机型,因为CameraManager是5.0之后支持的
* @return
*/
public static Boolean isSupport(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return true;
else
return false;
}
/**
* 初始化操作,获取CmareManager组件以及CamaraId
* @param context
* @throws CameraAccessException
*/
public static void init(Context context) throws CameraAccessException {
cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
Log.d(TAG, "init: cameraManager"+cameraManager.toString());
for (String id : cameraManager.getCameraIdList()){
if (cameraManager.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE)){
cameraId = id;
}
}
//后台监听闪光灯变化
if (handler ==null){
HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
handler = new Handler(thread.getLooper()){};
}
cameraManager.registerTorchCallback(torchCallback,handler);
Log.d(TAG, "init: cameraId"+cameraId);
}
/**
* 打开摄像头
* @param context
* @throws CameraAccessException
*/
public static void openFlash(Context context) throws CameraAccessException {
Log.d(TAG, "openFlash: entered");
if (cameraId!=null){
cameraManager.setTorchMode(cameraId,true);
Log.d(TAG, "openFlash: setTorchMode Successed");
}
}
/**
* 关闭摄像头
* @param context
* @throws CameraAccessException
*/
public static void closeFlash(Context context) throws CameraAccessException {
if (cameraId!=null){
cameraManager.setTorchMode(cameraId,false);
Log.d(TAG, "openFlash: setTorchMode false Successed");
}
}
}
本文介绍了使用Android开发一个简单的手电筒应用,涉及主界面布局、自定义Dialog的创建和处理,以及FlashLightUtil类中对相机闪光灯的控制,包括权限请求、状态切换和CameraManager的使用。

2876

被折叠的 条评论
为什么被折叠?



