boolean android.app.Activity.isFinishing()函数使用

本文探讨了Android开发中Activity在finish状态下的常见问题,包括如何避免在Activity已finish时仍接收广播导致的bug,以及如何处理finish状态下发送消息引发的问题。

这个函数注释:

Check to see whether this activity is in the process of finishing, either because you called finish on it or someone else has requested that it finished. This is often used in onPause to determine whether the activity is simply pausing or completely finishing.

Returns:
If the activity is finishing, returns true; else returns false.
See Also:
finish
判断this Activity是否finish,自己调用或者某种因素请求finish,经常用在onPause函数里面


这次项目中,遇到这个问题,一个activity在finish时候,还有收到广播,结果导致bug

在广播接收器中先判断一下比较保险。或者在onDestroy里面注销广播

private BroadcastReceiver mIntentReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            Log.d(TAG, intent.toString());    
            final String action = intent.getAction();
            
            if(isFinishing())
            {

                  。。。。。。。              

                return;

            }

}


还有遇到一个问题,在activity  finish时候,这时候handler.sendMessage,这时候也会导致bug

这时候最好在finish函数里面removeAllCallbackAndMessage(this)

package com.android.example.cameraappxjava; import android.Manifest; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.Image; import android.media.ImageReader; import android.media.MediaPlayer; import android.net.Uri; import android.opengl.GLES30; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.SystemClock; import android.provider.MediaStore; import android.util.Log; import android.util.Size; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.Button; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import com.android.example.cameraappxjava.util.CameraRenderer; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class MainActivity extends AppCompatActivity { private static final String TAG = "camera2api"; private static final int REQUEST_CAMERA_PERMISSION = 100; private TextureView textureView; private GLSurfaceView glSurfaceView; private Button captureButton; private CameraDevice cameraDevice; private CameraCaptureSession cameraCaptureSession; private CaptureRequest.Builder captureRequestBuilder; private String cameraId; private Handler backgroundHandler; private boolean isSessionClosed; private HandlerThread backgroundThread; private ImageReader imageReader; private boolean isTextureAvailable = false; // 跟踪Surface状态 private CameraManager manager; private volatile boolean isCapturing = false; private StreamConfigurationMap map; private long lastClickTime = 0; private static final long MIN_CLICK_INTERVAL = 1000; // 最小点击间隔1秒 private File file; private ContentResolver resolver; private ContentValues values; private Uri imageUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate ——————————————————————"); captureButton = findViewById(R.id.btnCapture); // textureView = findViewById(R.id.textureView); glSurfaceView = findViewById(R.id.glsurfaceView); glSurfaceView.setEGLContextClientVersion(3); // 使用 OpenGL ES 3.0 glSurfaceView.setRenderer(new CameraRenderer()); //初始化相机参数 initCamera(); //设置预览监听 glSurfaceView textureView.setSurfaceTextureListener(surfaceTextureListener); //设置拍照预监听 captureButton.setOnClickListener(v -> {//防止 连点抛出异常 long currentTime = SystemClock.elapsedRealtime(); if (currentTime - lastClickTime > MIN_CLICK_INTERVAL) { lastClickTime = currentTime; takePicture(); } else { Log.d(TAG, "点击过快,已忽略"); } }); } @Override protected void onResume() { Log.d(TAG, "onResume —————————————————————— "); Log.d(TAG, Log.getStackTraceString(new Throwable())); super.onResume(); glSurfaceView.onResume(); // 必须添加 // 检查相机权限 // ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA):用于检测this(当前应用)是否有Manifest.permission.CAMERA权限 //有则返回PackageManager.PERMISSION_GRANTED(有权限),没有则返回PackageManager.PERMISSION_DENIED(无权限) if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "没有相机权限——>开始请求相机权限"); //ActivityCompat.requestPermissions():请求权限的方法 //this:当前应用 //new String[]{权限1,权限2,...}:请求的权限集合 //code:对应编码名,发送请求后会调用回调函数 onRequestPermissionsResult(),该回调的第一个参数就是这个code,用于给我们做请求权限后的自定义操作。 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } //注意:以上的权限请求是异步操作 startBackgroundThread(); // 如果Surface已经可用,重新打开相机 if (textureView.isAvailable()) { openCamera(); } } @Override protected void onPause() { super.onPause(); Log.d(TAG, "onPause ——————————————————————"); glSurfaceView.onPause(); // 必须添加 // 1. 仅在“非拍照中”且“会话存在”时,停止预览的重复请求(避免授权时资源被清) if (!isCapturing && cameraCaptureSession != null) { try { // 停止预览的重复请求(暂停预览画面),但不关闭会话和相机设备 cameraCaptureSession.stopRepeating(); Log.d(TAG, "onPause: 暂停预览重复请求(核心资源未释放)"); } catch (CameraAccessException e) { Log.e(TAG, "onPause: 停止预览失败", e); } // 2. 拍照中时,延迟处理(避免中断拍照流程) if (isCapturing) { Log.w(TAG, "onPause: 拍照中,暂不处理预览暂停"); new Handler().postDelayed(() -> { if (!isCapturing && cameraCaptureSession != null) { try { cameraCaptureSession.stopRepeating(); Log.d(TAG, "onPause: 拍照完成后,暂停预览"); } catch (CameraAccessException e) { Log.e(TAG, "onPause: 延迟停止预览失败", e); } } }, 1000); } } } @Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop: Activity 完全不可见(如按Home键),释放核心资源"); // 1. 检查是否正在销毁(如果是销毁,交给 onDestroy 处理,避免重复释放) if (isFinishing()) { Log.d(TAG, "onStop: Activity 正在销毁,核心资源由 onDestroy 处理"); return; } // 2. 释放相机核心资源(会话、设备、ImageReader),但保留后台线程(onResume 可快速恢复) if (cameraCaptureSession != null) { cameraCaptureSession.close(); cameraCaptureSession = null; Log.d(TAG, "onStop: 关闭 CameraCaptureSession"); } if (cameraDevice != null) { cameraDevice.close(); cameraDevice = null; Log.d(TAG, "onStop: 关闭 CameraDevice"); } if (imageReader != null) { imageReader.close(); imageReader = null; Log.d(TAG, "onStop: 关闭 ImageReader"); } isSessionClosed = true; } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy: Activity 彻底销毁,释放所有资源"); // 1. 释放相机相关资源(防止内存泄漏) if (cameraCaptureSession != null) { cameraCaptureSession.close(); cameraCaptureSession = null; } if (cameraDevice != null) { cameraDevice.close(); cameraDevice = null; } if (imageReader != null) { imageReader.close(); imageReader = null; } // 2. 停止后台线程(彻底销毁,避免线程泄漏) stopBackgroundThread(); // 3. 置空所有引用(帮助 GC 回收) textureView = null; captureButton = null; manager = null; resolver = null; values = null; imageUri = null; backgroundHandler = null; backgroundThread = null; Log.d(TAG, "onDestroy: 所有资源释放完成"); } private final TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() { //触发时机:SurfaceTexture 初始化后 @Override public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) { isTextureAvailable = true; // 设置可用标志 Log.d(TAG, "Surface就绪,触发相机初始化"); if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { openCamera(); } } @Override public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) { Log.d(TAG, "onSurfaceTextureSizeChanged: " + width + "x" + height); } @Override public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) { Log.d(TAG, "onSurfaceTextureDestroyed"); isTextureAvailable = false; if (cameraCaptureSession != null) { try { cameraCaptureSession.stopRepeating(); } catch (CameraAccessException e) { Log.e(TAG, "停止预览失败", e); } } return true; } @Override public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) { } }; private void initCamera() { Log.d(TAG, "initCamera: 初始化相机配置"); try { //1.初始化CameraManager,获取相机配置map manager = (CameraManager) getSystemService(CAMERA_SERVICE); cameraId = manager.getCameraIdList()[0]; CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); if (map == null) { Log.e(TAG, "错误: StreamConfigurationMap为空!!"); } //2.图片保存参数配置 resolver = getContentResolver(); values = new ContentValues(); values.put(MediaStore.Images.Media.DISPLAY_NAME, "pic_" + System.currentTimeMillis() + ".jpg"); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES); } catch (CameraAccessException e) { Log.e(TAG, "相机访问异常: " + e.getMessage()); } catch (NullPointerException e) { Log.e(TAG, "NPE: " + e.getMessage()); } } private Size chooseOptimalSize(Size[] choices, int width, int height) { List<Size> bigEnough = new ArrayList<>(); for (Size option : choices) { float ratio = (float) option.getWidth() / option.getHeight(); float viewRatio = (float) width / height; if (Math.abs(ratio - viewRatio) <= 0.1 && option.getWidth() <= width && option.getHeight() <= height) { bigEnough.add(option); } } if (!bigEnough.isEmpty()) { return Collections.max(bigEnough, new CompareSizesByArea()); } Log.w(TAG, "未找到完美匹配尺寸,使用默认"); return choices[0]; } static class CompareSizesByArea implements Comparator<Size> { @Override public int compare(Size lhs, Size rhs) { return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight()); } } private void openCamera() { if (!isTextureAvailable || textureView.getSurfaceTexture() == null) { // 检查Surface是否可用 Log.w(TAG, "Surface不可用,延迟打开相机,100ms后重试"); backgroundHandler.postDelayed(this::openCamera, 10000); return; } Log.d(TAG, "openCamera: 尝试打开相机"); try { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "1.打开相机: " + cameraId); manager.openCamera(cameraId, stateCallback, backgroundHandler); } else { Log.w(TAG, "相机权限未授予"); } } catch (CameraAccessException e) { Log.e(TAG, "打开相机失败: " + e.getMessage()); } catch (SecurityException e) { Log.e(TAG, "安全异常: " + e.getMessage()); } } private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { Log.i(TAG, "相机已打开"); cameraDevice = camera; Log.i(TAG, "2.1 开始配置预览流"); createCameraPreviewSession(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { Log.w(TAG, "相机断开连接"); cameraDevice.close(); } @Override public void onError(@NonNull CameraDevice camera, int error) { Log.e(TAG, "相机错误: " + error); cameraDevice.close(); cameraDevice = null; } }; //2.1 开始配置预览流 private void createCameraPreviewSession() { if (cameraDevice == null || !isTextureAvailable) { // 双重检查 Log.e(TAG, "创建预览会话失败: 相机或Surface不可用"); return; } try { //1.1 配置预览尺寸 // Size previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), textureView.getWidth(), textureView.getHeight()); // Log.i(TAG, "选择预览尺寸: " + previewSize.getWidth() + "x" + previewSize.getHeight()); // // //1.2 配置预览Surface // SurfaceTexture previewTexture = textureView.getSurfaceTexture(); // previewTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); // Surface previewSurface = new Surface(previewTexture); // GLSurfaceView 配置 Surface glSurface = glSurfaceView.getHolder().getSurface(); glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // 创建会话时使用 GLSurfaceView 的 Surface cameraDevice.createCaptureSession( Collections.singletonList(glSurface), // 关键修改 sessionCallback, backgroundHandler ); // 2.配置拍照Surface //优化尺寸选择(兼容性处理) 配置jpegSizes Size[] jpegSizes = map.getOutputSizes(ImageFormat.JPEG); Size captureSize = chooseOptimalSize(jpegSizes); Log.i(TAG, "使用拍照尺寸: " + captureSize.getWidth() + "x" + captureSize.getHeight()); // 优化:检查尺寸变化,仅当尺寸变更时重建 if (imageReader == null || imageReader.getWidth() != captureSize.getWidth()) { if (imageReader != null) imageReader.close(); imageReader = ImageReader.newInstance( captureSize.getWidth(), captureSize.getHeight(), ImageFormat.JPEG, 2 // 缓冲区数量 ); } // 3.配置双输出Surface(预览 + 拍照) List<Surface> outputSurfaces = new ArrayList<>(2); outputSurfaces.add(previewSurface); outputSurfaces.add(imageReader.getSurface()); //3.创建会话 cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { Log.i(TAG, "2.2 预览会话配置成功"); cameraCaptureSession = session; try { //3.下发请求添加预览流 captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureRequestBuilder.addTarget(previewSurface); //配置预览 自动对焦 captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); Log.i(TAG, "3.开始下发预览请求"); cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler); } catch (CameraAccessException e) { Log.e(TAG, "设置预览请求失败: " + e.getMessage()); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Log.e(TAG, "预览会话配置失败"); Toast.makeText(MainActivity.this, "配置失败", Toast.LENGTH_SHORT).show(); } }, backgroundHandler); } catch (CameraAccessException e) { Log.e(TAG, "创建预览会话异常: " + e.getMessage()); } } // 优化尺寸选择 private Size chooseOptimalSize(Size[] choices) { // 优先选择16:9的比例 final double ASPECT_RATIO = 16.0 / 9.0; Size optimalSize = null; for (Size size : choices) { double ratio = (double) size.getWidth() / size.getHeight(); if (Math.abs(ratio - ASPECT_RATIO) <= 0.1) { if (optimalSize == null || size.getWidth() > optimalSize.getWidth()) { optimalSize = size; } } } // 若无匹配则选择最大尺寸 if (optimalSize == null) { for (Size size : choices) { if (optimalSize == null || size.getWidth() > optimalSize.getWidth()) { optimalSize = size; } } } return optimalSize != null ? optimalSize : new Size(1920, 1080); } private void saveImage(byte[] bytes, File file) { Log.d(TAG, "保存图像: " + file.getAbsolutePath()); imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); if (imageUri != null) { try (FileOutputStream output = new FileOutputStream(file)) { output.write(bytes); Log.i(TAG, "图像保存成功, 大小: " + bytes.length + " bytes"); } catch (IOException e) { Log.e(TAG, "保存文件失败: " + e.getMessage()); } } } //触发时机:用户点击授权后调用 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); Log.d(TAG, "权限请求结果: " + requestCode); if (requestCode == REQUEST_CAMERA_PERMISSION) { if (grantResults[0] == PackageManager.PERMISSION_DENIED) { Log.w(TAG, "用户拒绝相机权限"); Toast.makeText(this, "需要相机权限", Toast.LENGTH_SHORT).show(); finish(); } else { Log.i(TAG, "用户授予相机权限"); } } } private void startBackgroundThread() { if (backgroundThread == null) { backgroundThread = new HandlerThread("CameraBackground"); backgroundThread.start(); backgroundHandler = new Handler(backgroundThread.getLooper()); Log.d(TAG, "后台线程启动"); } } private void stopBackgroundThread() { if (backgroundThread != null) { Log.d(TAG, "停止后台线程"); backgroundThread.quitSafely(); try { backgroundThread.join(); backgroundThread = null; backgroundHandler = null; } catch (InterruptedException e) { Log.e(TAG, "停止线程失败: " + e.getMessage()); } } } private void closeCamera() { Log.d(TAG, "关闭相机资源"); if (isCapturing) { Log.w(TAG, "正在拍照中,等待完成或取消..."); // 可以尝试等待一段时间或取消请求 try { cameraCaptureSession.abortCaptures(); // 取消所有进行中的捕获 } catch (CameraAccessException e) { throw new RuntimeException(e); } } if (cameraCaptureSession != null) { cameraCaptureSession.close(); cameraCaptureSession = null; } isSessionClosed = true; } private boolean checkTakePicture() { if (cameraDevice == null) { Log.w(TAG, "拍照失败: 相机未初始化"); return false; } // 1. 检查会话有效性 if (cameraCaptureSession == null) { Log.e(TAG, "拍照错误: CameraCaptureSession为空"); return false; } // 2. 检查后台Handler if (backgroundHandler == null) { Log.e(TAG, "拍照错误: backgroundHandler未初始化"); startBackgroundThread(); // 初始化方法见下方 return false; } if (isSessionClosed) { Log.e(TAG, "当前会话已关闭"); } return true; } private void takePicture() { Log.i(TAG, "4.开始拍照流程——————————"); try { //1.检查是否可以拍照 boolean checkFlag = checkTakePicture(); if (!checkFlag) { Log.i(TAG, "拍照流程————检查未通过!退出拍照!"); return; } // 2. 创建拍照请求 CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); captureBuilder.addTarget(imageReader.getSurface()); //3.设置拍照下发参数 //自动曝光 captureBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); // 图片旋转角度跟随手机默认 int rotation = getWindowManager().getDefaultDisplay().getRotation(); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, rotation); // 4. 图像可用监听器 imageReader.setOnImageAvailableListener(reader -> { Log.d(TAG, "图像数据可用"); try (Image image = reader.acquireLatestImage()) { if (image != null) { // 9. 创建目标文件 file = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "pic_" + System.currentTimeMillis() + ".jpg" ); ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); saveImage(bytes, file); // 发送媒体扫描广播,写入系统相册 Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); mediaScanIntent.setData(Uri.fromFile(file)); sendBroadcast(mediaScanIntent); } } catch (Exception e) { Log.e(TAG, "保存图像错误: " + e.getMessage()); } }, backgroundHandler); // 11. 拍照回调 CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { // 处理拍照完成 isCapturing = false; // 可以在这里进行后续操作,但注意检查资源是否仍然有效 super.onCaptureCompleted(session, request, result); Log.i(TAG, "拍照完成,保存至: " + file.getAbsolutePath()); runOnUiThread(() -> Toast.makeText(MainActivity.this, "保存至: " + file, Toast.LENGTH_SHORT).show() ); createCameraPreviewSession(); // 恢复预览 } @Override public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) { super.onCaptureFailed(session, request, failure); Log.e(TAG, "拍照失败: " + failure.getReason()); } }; // 12. 执行拍照(添加会话状态检查) Log.d(TAG, "停止预览"); cameraCaptureSession.stopRepeating(); Log.d(TAG, "播放黑闪动画"); flash_mode(); Log.d(TAG, "4.下发拍照"); isCapturing = true; cameraCaptureSession.capture(captureBuilder.build(), captureCallback, backgroundHandler); } catch (CameraAccessException | IllegalStateException | SecurityException e) { Log.e(TAG, "拍照过程异常: " + e.getClass().getSimpleName(), e); } } //播放黑闪动画 private void flash_mode() { // 在拍照按钮点击事件中触发 View flashView = findViewById(R.id.flashview); flashView.setVisibility(View.VISIBLE); // 先显示黑色视图 // 创建动画:透明度从0到1再到0,模拟闪烁 AlphaAnimation flashAnim = new AlphaAnimation(0.0f, 1.0f); flashAnim.setDuration(100); // 动画时长100ms,根据需求调整 flashAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { flashView.setVisibility(View.INVISIBLE); // 动画结束后隐藏视图 // 在此处调用实际拍照逻辑(如Camera API) } @Override public void onAnimationRepeat(Animation animation) { } }); flashView.startAnimation(flashAnim); } } class CameraRenderer2 implements GLSurfaceView.Renderer { private SurfaceTexture cameraSurfaceTexture; @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 创建 OES 纹理 int[] texIds = new int[1]; GLES30.glGenTextures(1, texIds, 0); cameraSurfaceTexture = new SurfaceTexture(texIds[0]); // 初始化相机 initCameraWithSurface(new Surface(cameraSurfaceTexture)); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { } @Override public void onDrawFrame(GL10 gl) { cameraSurfaceTexture.updateTexImage(); // 更新纹理 // 执行自定义渲染管线... } private void initCameraWithSurface(Surface surface) { // 使用传入的 Surface 创建相机会话 cameraDevice.createCaptureSession( Collections.singletonList(surface), sessionCallback, backgroundHandler ); } } 我没听懂你让写的,你直接帮我修改
最新发布
09-20
AndroidManifest.xml:<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.diaryapp"> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <application android:allowBackup="true" android:hardwareAccelerated="true" android:largeHeap="true" android:requestLegacyExternalStorage="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.HelloWorld"> <activity android:name=".MainActivity" android:label="@string/title_activity_main" android:exported="false" /> <activity android:name=".DiaryActivity" android:label="@string/title_activity_diary" android:exported="false" /> <activity android:name=".RegisterActivity" android:label="@string/title_activity_register" android:exported="false" /> <activity android:name=".LoginActivity" android:label="@string/title_activity_login" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> DiaryAdapter: package com.example.diaryapp.adapters; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.example.diaryapp.utils.GlideEngine; import com.example.diaryapp.DiaryActivity; import com.example.diaryapp.R; import com.example.diaryapp.models.Diary; import java.util.List; public class DiaryAdapter extends RecyclerView.Adapter<DiaryAdapter.DiaryViewHolder> { private Context context; private List<Diary> diaryList; private int userId; public DiaryAdapter(Context context,List<Diary> diaryList,int userId){ this.context=context; this.diaryList=diaryList; this.userId=userId; // 通过构造函数传递 userId } // 当数据更新时调用此方法 @SuppressLint("NotifyDataSetChanged") public void updateDiaries(List<Diary> newDiaries){ this.diaryList.clear(); this.diaryList.addAll(newDiaries); notifyDataSetChanged(); } @NonNull @Override public DiaryAdapter.DiaryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view= LayoutInflater.from(context).inflate(R.layout.item_diary,parent,false); return new DiaryViewHolder(view); } // 绑定视图持有者方法 @Override public void onBindViewHolder(@NonNull DiaryAdapter.DiaryViewHolder holder, int position) { Diary diary=diaryList.get(position); holder.tvTitle.setText(diary.getTitle()); holder.tvDate.setText(diary.getDate()); holder.tvContent.setText(diary.getContent()); holder.tvWordCount.setText("字数:" + diary.getContent().length()); if (diary.getImagePath() != null && !diary.getImagePath().isEmpty()) { GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(context,diary.getImagePath(),holder.ivImage); } else { holder.ivImage.setBackgroundColor(context.getResources().getColor(android.R.color.darker_gray)); } holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(context, DiaryActivity.class); intent.putExtra("diaryId",diary.getId()); intent.putExtra("userId",userId); // 确保传递正确的 userId context.startActivities(new Intent[]{intent}); } }); } @Override public int getItemCount() { return diaryList.size(); } public static class DiaryViewHolder extends RecyclerView.ViewHolder { private TextView tvTitle,tvDate,tvContent,tvWordCount; private ImageView ivImage; public DiaryViewHolder(@NonNull View itemView) { super(itemView); tvTitle=itemView.findViewById(R.id.tvTitle); tvDate=itemView.findViewById(R.id.tvDate); tvContent=itemView.findViewById(R.id.tvContent); ivImage=itemView.findViewById(R.id.ivImage); tvWordCount=itemView.findViewById(R.id.tvWordCount); } } } Diary:package com.example.diaryapp.models; public class Diary { private int id; private String title; private String content; private String date; private String imagePath; public Diary(){} public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } } DatabaseHelper:package com.example.diaryapp.utils; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import com.example.diaryapp.models.Diary; import java.util.ArrayList; import java.util.List; public class DatabaseHelper extends SQLiteOpenHelper { //数据库信息 private static final String DATABASE_NAME = "DiaryApp.db"; private static final int DATABASE_VERSION = 1; //用户表信息 private static final String TABLE_USER = "user"; private static final String COLUMN_USER_ID = "id"; private static final String COLUMN_USER_USERNAME = "username"; private static final String COLUMN_USER_PASSWORD = "password"; //日记表信息 private static final String TABLE_DIARY = "diary"; private static final String COLUMN_DIARY_ID = "id"; private static final String COLUMN_DIARY_USER_ID = "user_id"; private static final String COLUMN_DIARY_TITLE = "title"; private static final String COLUMN_DIARY_CONTENT = "content"; private static final String COLUMN_DIARY_DATE = "date"; private static final String COLUMN_DIARY_IMAGE_PATH = "image_path"; public DatabaseHelper(Context context) { super(context, DATABASE_NAME,null,DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { //创建用户表 String createUserTable = "CREATE TABLE " + TABLE_USER + " (" + COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_USER_USERNAME + " TEXT UNIQUE, " + COLUMN_USER_PASSWORD + " TEXT)"; db.execSQL(createUserTable); //创建日记表 String createDiaryTable = "CREATE TABLE " + TABLE_DIARY + " (" + COLUMN_DIARY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_DIARY_USER_ID + " INTEGER, " + COLUMN_DIARY_TITLE + " TEXT, " + COLUMN_DIARY_CONTENT + " TEXT, " + COLUMN_DIARY_DATE + " TEXT, " + COLUMN_DIARY_IMAGE_PATH + " TEXT)"; db.execSQL(createDiaryTable); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //升级数据库时的操作 db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER); db.execSQL("DROP TABLE IF EXISTS " + TABLE_DIARY); onCreate(db); } //用户相关操作 public long addUser(String username,String password){ SQLiteDatabase db = null; try { db=this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(COLUMN_USER_USERNAME, username); values.put(COLUMN_USER_PASSWORD,password); return db.insert(TABLE_USER,null,values); }catch (Exception e){ e.printStackTrace(); return -1; }finally { if (db!=null){ db.close(); } } } public boolean checkUser(String username, String password){ SQLiteDatabase db = null; Cursor cursor = null; boolean exists = false; try { db=this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_USER + " WHERE " + COLUMN_USER_USERNAME + "=? AND " + COLUMN_USER_PASSWORD + "=?", new String[]{username,password} ); exists = cursor.getCount() > 0; }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } if (db!=null){ db.close(); } } return exists; // Cursor cursor = db.rawQuery( // "SELECT * FROM " + TABLE_USER + " WHERE " + // COLUMN_USER_USERNAME + "=? AND " + COLUMN_USER_PASSWORD + "=?", // new String[]{username,password} // ); // boolean exists = cursor.getCount() > 0; // Log.d("DatabaseHelper","checkUser: username=" + username + ", exists=" + exists); // cursor.close(); // return exists; } public int getUserId(String username){ SQLiteDatabase db = null; Cursor cursor=null; int userId=-1; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT " + COLUMN_USER_ID + " FROM " + TABLE_USER + " WHERE " + COLUMN_USER_USERNAME + "=?", new String[]{username} ); if (cursor.moveToFirst()) { // 如果cursor不为空且移动到第一条记录,获取用户ID userId = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_USER_ID)); } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor!=null){ cursor.close(); } if (db!=null){ db.close(); } } return userId; } //日记相关操作 public long addDiary(int userId, Diary diary){ SQLiteDatabase db = getWritableDatabase(); try { db.beginTransaction(); ContentValues values = new ContentValues(); values.put(COLUMN_DIARY_USER_ID, userId); values.put(COLUMN_DIARY_TITLE,diary.getTitle()); values.put(COLUMN_DIARY_CONTENT,diary.getContent()); values.put(COLUMN_DIARY_DATE,diary.getDate()); values.put(COLUMN_DIARY_IMAGE_PATH,diary.getImagePath()); long result = db.insert(TABLE_DIARY,null,values); db.setTransactionSuccessful(); return result; }catch (Exception e){ e.printStackTrace(); return -1; }finally { db.endTransaction(); // if (db != null){ // db.endTransaction(); // db.close(); // } } } public List<Diary> getDiariesByUserId(int userId){ List<Diary> diaries = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); Cursor cursor = null; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_DIARY + " WHERE " + COLUMN_DIARY_USER_ID + "=? ORDER BY " + COLUMN_DIARY_DATE + " DESC", new String[]{String.valueOf(userId)} ); while (cursor.moveToNext()) { Diary diary = new Diary(); diary.setId(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIARY_ID))); diary.setTitle(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_TITLE))); diary.setContent(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_CONTENT))); diary.setDate(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_DATE))); diary.setImagePath(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_IMAGE_PATH))); diaries.add(diary); } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } // if (db != null){ // db.close(); // } } return diaries; } public Diary getDiaryById(int diaryId){ SQLiteDatabase db = getReadableDatabase(); Cursor cursor = null; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_DIARY + " WHERE " + COLUMN_DIARY_ID + "=?", new String[]{String.valueOf(diaryId)} ); if (cursor.moveToFirst()) { Diary diary = new Diary(); diary.setId(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIARY_ID))); diary.setTitle(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_TITLE))); diary.setContent(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_CONTENT))); diary.setDate(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_DATE))); diary.setImagePath(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_IMAGE_PATH))); return diary; } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } // if (db != null){ //// db.close(); // 确保关闭数据库连接 // } } // cursor.close(); return null; } public long updateDiary(Diary diary){ SQLiteDatabase db = getWritableDatabase(); try { ContentValues values = new ContentValues(); values.put(COLUMN_DIARY_TITLE,diary.getTitle()); values.put(COLUMN_DIARY_CONTENT,diary.getContent()); values.put(COLUMN_DIARY_DATE,diary.getDate()); values.put(COLUMN_DIARY_IMAGE_PATH,diary.getImagePath()); return db.update(TABLE_DIARY, values, COLUMN_DIARY_ID + "=?", new String[]{String.valueOf(diary.getId())}); // db.close(); // 确保关闭数据库连接 // Log.d("DatabaseHelper","updateDiary: result=" + result); //调试日志 // return result; }catch (Exception e){ e.printStackTrace(); return -1; }finally { // if (db != null){ // db.close(); // } } } public void deleteDiary(int diaryId) { SQLiteDatabase db = getWritableDatabase(); try { db.beginTransaction(); db.delete(TABLE_DIARY, COLUMN_DIARY_ID + "=?", new String[]{ String.valueOf(diaryId) }); db.setTransactionSuccessful(); }catch (Exception e){ e.printStackTrace(); }finally { db.endTransaction(); } // finally { // if (db != null){ // db.close(); // } } // int result=db.delete(TABLE_DIARY, // COLUMN_DIARY_ID + "=?", // new String[]{String.valueOf(diaryId)}); // db.close(); // 确保关闭数据库连接 // Log.d("DatabaseHelper","deleteDiary: result=" + result);//调试日志 // } } GlideEngine:package com.example.diaryapp.utils; import android.content.Context; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.example.diaryapp.R; import com.luck.picture.lib.engine.ImageEngine; import com.luck.picture.lib.utils.ActivityCompatHelper; public class GlideEngine implements ImageEngine { @Override public void loadImage(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } try { Glide.with(context) .load(url) .into(imageView); } catch (Exception e) { e.printStackTrace(); imageView.setBackgroundColor(context.getResources().getColor(android.R.color.darker_gray)); } } @Override public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .load(url) .override(maxWidth, maxHeight) .into(imageView); } @Override public void loadAlbumCover(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .asBitmap() .load(url) .override(180, 180) .sizeMultiplier(0.5f) .transform(new CenterCrop(), new RoundedCorners(8)) .placeholder(R.drawable.ic_launcher_background) .into(imageView); } @Override public void loadGridImage(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .load(url) .override(200, 200) .centerCrop() .placeholder(R.drawable.ic_launcher_background) .into(imageView); } @Override public void pauseRequests(Context context) { Glide.with(context).pauseRequests(); } @Override public void resumeRequests(Context context) { Glide.with(context).resumeRequests(); } private GlideEngine() { } private static final class InstanceHolder { static final GlideEngine instance = new GlideEngine(); } public static GlideEngine createGlideEngine() { return InstanceHolder.instance; } }DiaryActivity:package com.example.diaryapp; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import com.example.diaryapp.models.Diary; import com.example.diaryapp.utils.DatabaseHelper; import com.example.diaryapp.utils.GlideEngine; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; public class DiaryActivity extends AppCompatActivity { // 声明界面组件和相关变量 private EditText etTitle,etContent; private TextView tvDate; private ImageView ivImage; private Button btnSave,btnDelete,btnAddImage; private DatabaseHelper dbHelper; private int userId; private int diaryId = -1; private String imagePath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_diary);// 设置布局文件 // 获取传递过来的用户ID和日记ID userId = getIntent().getIntExtra("userId",-1); diaryId = getIntent().getIntExtra("diaryId",-1); if (userId == -1){ // 检查用户ID是否有效 // 用户ID无效,可能是登录流程的问题 Toast.makeText(this, "用户ID无效", Toast.LENGTH_SHORT).show(); finish(); return; } // 初始化界面组件 initView(); // 如果是编辑日记,加载日记内容 if (diaryId != -1){ Diary diary=dbHelper.getDiaryById(diaryId); if (diary != null){ etTitle.setText(diary.getTitle()); // 设置日记标题 etContent.setText(diary.getContent()); // 设置日记内容 tvDate.setText(diary.getDate()); // 设置日记日期 imagePath=diary.getImagePath(); // 获取图片路径 if (imagePath != null && !imagePath.isEmpty()) { try { // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (Exception e) { e.printStackTrace(); ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); // 设置默认背景 } } // 显示删除按钮 btnDelete.setVisibility(View.VISIBLE); }else { // 日记ID无效,可能是数据库查询的问题 Toast.makeText(this, "日记ID无效", Toast.LENGTH_SHORT).show(); finish(); } }else { // 设置当前日期 tvDate.setText(getCurrentDate()); } // 添加图片按钮监听 btnAddImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //selectImage(); // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } showImageOptions(); // 显示添加图片选项 } }); // 保存按钮监听 btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } saveDiary(); // 保存日记 } }); // 删除按钮监听 btnDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } deleteDiary(); // 删除日记 } }); } // private void selectImage() { // // 创建选择图片的Intent // Intent pickIntent=new Intent(Intent.ACTION_GET_CONTENT); // pickIntent.setType("image/*"); // // // 创建拍照的Intent // Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // if (captureIntent.resolveActivity(getPackageManager()) != null) { // startActivityForResult(captureIntent,2); // } // //intent.setAction(Intent.ACTION_GET_CONTENT); // startActivityForResult(pickIntent,1); // } private void showImageOptions() { // 创建弹出菜单,提供两个选项:从图库选择和拍照 String[] options = {"从图库选择","拍照"}; new AlertDialog.Builder(this) .setTitle("添加图片") .setItems(options,(dialog,which) -> { if (which == 0){ //从图库选择 Intent pickIntent = new Intent(Intent.ACTION_GET_CONTENT); pickIntent.setType("image/*"); startActivityForResult(pickIntent,1); }else if (which == 1){ //拍照 Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (captureIntent.resolveActivity(getPackageManager()) != null){ startActivityForResult(captureIntent,2); }else { Toast.makeText(DiaryActivity.this, "无法调用摄像头", Toast.LENGTH_SHORT).show(); } } }) .show(); } private void saveDiary() { String title=etTitle.getText().toString().trim(); String content=etContent.getText().toString().trim(); String date=tvDate.getText().toString(); if (title.isEmpty() || content.isEmpty()){ // 检查输入是否为空 return; } Diary diary=new Diary(); diary.setTitle(title); diary.setContent(content); diary.setDate(date); diary.setImagePath(imagePath); // 确保图片路径不为空 if (diaryId != -1){ diary.setId(diaryId); dbHelper.updateDiary(diary); // 更新日记 }else { dbHelper.addDiary(userId,diary); // 添加新日记 } //返回主界面 Intent resultIntent = new Intent(); setResult(RESULT_OK,resultIntent); finish(); } private void deleteDiary() { // //删除日记 // dbHelper.deleteDiary(diaryId); new AlertDialog.Builder(this) .setTitle("确认删除") .setMessage("确定要删除这篇日记吗?") .setPositiveButton("删除", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 使用独立的 DatabaseHelper 实例执行删除操作 DatabaseHelper helper=new DatabaseHelper(DiaryActivity.this); helper.deleteDiary(diaryId); // dbHelper.deleteDiary(diaryId); // 删除日记 // 设置结果码为RESULT_OK,表示操作成功,返回主界面MainActivity Intent resultIntent = new Intent(); setResult(RESULT_OK,resultIntent); finish(); } }) .setNegativeButton("取消",null) .show(); } @Override protected void onDestroy() { super.onDestroy(); // 释放可能持有的资源 if (btnSave!=null){ btnSave.setOnClickListener(null); } if (btnDelete!=null){ btnDelete.setOnClickListener(null); } if (btnAddImage!=null){ btnAddImage.setOnClickListener(null); } } @Override protected void onPause() { super.onPause(); // 暂停时释放资源 if (isFinishing()) { // 清理可能的临时资源 } } @Override protected void onResume() { super.onResume(); // 恢复时重新初始化资源 } private String getCurrentDate(){ // 返回当前日期的字符串表示 return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } protected void onActivityResult(int requestCode,int resultCode,Intent data){ super.onActivityResult(requestCode,resultCode,data); if (isFinishing() || isDestroyed()){ return; } // 确保调用super.onActivityResult if (requestCode == 1 && resultCode == RESULT_OK && data != null){ // 处理从图库选择的图片 Uri selectedImage = data.getData(); if (selectedImage != null) { // 检查selectedImage是否为null try { // 将图片保存到应用私有目录 Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage); String filename = "diary_image_" + System.currentTimeMillis() + ".jpg"; File file = new File(getExternalFilesDir(null), filename); // File fileDir = getExternalFilesDir(null); // if (fileDir != null && !fileDir.exists()){ // fileDir.mkdir(); // } // File file = new File(fileDir,filename); FileOutputStream fos = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); imagePath = file.getAbsolutePath(); // 改:ivImage.setImageBitmap(bitmap); // 显示图片 // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (IOException e) { e.printStackTrace(); //改: ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); } } // Glide.with(this).load(imagePath).into(ivImage); // }catch (IOException e){ // e.printStackTrace(); // } }else if (requestCode == 2 && resultCode == RESULT_OK && data != null){ //处理拍照结果 Bundle extras = data.getExtras(); Bitmap imageBitmap = (Bitmap) extras.get("data"); if (extras != null) { // 检查extras是否为null // Bitmap imageBitmap = (Bitmap) extras.get("data"); if (imageBitmap != null) {// 检查photo是否为null try { String filename = "diary_image_" + System.currentTimeMillis() + ".jpg"; File file = new File(getExternalFilesDir(null), filename); FileOutputStream fos = new FileOutputStream(file); imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); imagePath = file.getAbsolutePath(); // 改:ivImage.setImageBitmap(imageBitmap); // 显示图片 // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (IOException e) { e.printStackTrace(); ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); } } } } } private void initView() { // 初始化界面组件 etTitle=findViewById(R.id.etTitle); etContent=findViewById(R.id.etContent); tvDate=findViewById(R.id.tvDate); ivImage=findViewById(R.id.ivImage); btnAddImage=findViewById(R.id.btnAddImage); btnSave=findViewById(R.id.btnSave); btnDelete=findViewById(R.id.btnDelete); dbHelper=new DatabaseHelper(this); // 初始化数据库助手 // userId=getIntent().getIntExtra("userId",-1); // diaryId=getIntent().getIntExtra("diaryId",-1); } } LoginActivity:package com.example.diaryapp; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.example.diaryapp.utils.DatabaseHelper; public class LoginActivity extends AppCompatActivity { private EditText etUsername,etPassword; private CheckBox cbRemember; private DatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_login); // 初始化界面组件 initView(); // 获取SharedPreferences中的保存信息 SharedPreferences prefs=getSharedPreferences("DiaryApp",MODE_PRIVATE); String username=prefs.getString("username",""); String password=prefs.getString("password",""); // 如果用户名存在但密码不存在,删除用户名 if (username.isEmpty() || password.isEmpty()){ prefs.edit().remove("username").remove("password").apply(); } boolean remember=prefs.getBoolean("remember",false); etUsername.setText(username); etPassword.setText(password); cbRemember.setChecked(remember); // 登录按钮监听 Button btnLogin=findViewById(R.id.btnLogin); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { login(); } }); // 注册按钮监听 Button btnRegister=findViewById(R.id.btnRegister); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(LoginActivity.this, RegisterActivity.class); startActivity(intent); } }); } private void login() { String username=etUsername.getText().toString().trim(); String password=etPassword.getText().toString().trim(); boolean remember=cbRemember.isChecked(); // 验证输入 if (username.isEmpty() || password.isEmpty()){ Toast.makeText(this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show(); return; } // 保存登录信息到SharedPreferences SharedPreferences prefs=getSharedPreferences("DiaryApp",MODE_PRIVATE); SharedPreferences.Editor editor=prefs.edit(); // 如果记住密码被勾选,则保存密码;否则清空密码 if (remember){ editor.putString("username",username); editor.putString("password",password); }else { // editor.remove("username"); editor.remove("password"); // 确保未勾选时清空密码 } editor.putBoolean("remember",remember); editor.apply(); // 验证用户 if (dbHelper.checkUser(username,password)){ Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show(); Intent intent=new Intent(LoginActivity.this,MainActivity.class); intent.putExtra("username",username); startActivity(intent); finish(); // 关闭登录界面,避免返回时重复登录 }else { Toast.makeText(this, "用户名或密码错误", Toast.LENGTH_SHORT).show(); } } private void initView() { // 初始化界面组件 etUsername=findViewById(R.id.etUsername); etPassword=findViewById(R.id.etPassword); cbRemember=findViewById(R.id.cbRemember); dbHelper=new DatabaseHelper(this); } }MainActivity:package com.example.diaryapp; import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.example.diaryapp.adapters.DiaryAdapter; import com.example.diaryapp.models.Diary; import com.example.diaryapp.utils.DatabaseHelper; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView rvDiaryList; private DiaryAdapter diaryAdapter; private List<Diary> diaryList; private DatabaseHelper dbHelper; private String username; private int userId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); dbHelper=new DatabaseHelper(this); // 获取传递过来的用户名 username=getIntent().getStringExtra("username"); if (username == null){ // 用户名为空,可能是登录流程的问题 Toast.makeText(this, "用户名为空", Toast.LENGTH_SHORT).show(); finish(); return; } userId=dbHelper.getUserId(username); if (userId == -1){ // 用户ID无效,可能是数据库查询的问题 Toast.makeText(this, "用户ID无效", Toast.LENGTH_SHORT).show(); finish(); return; } // 初始化界面组件 initView(); // 加载日记 loadDiaries(); // 添加日记按钮监听 Button btnAddDiary=findViewById(R.id.btnAddDiary); // 在添加日记的按钮点击事件中 btnAddDiary.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(MainActivity.this,DiaryActivity.class); intent.putExtra("userId",userId); startActivityForResult(intent,1); } }); } protected void onActivityResult(int requestCode,int resultCode,Intent data){ super.onActivityResult(requestCode,resultCode,data); if (requestCode == 1 && resultCode == RESULT_OK){ // List<Diary> diaries = dbHelper.getDiariesByUserId(userId); // diaryAdapter.updateDiaries(diaries); //更新适配器数据 loadDiaries(); // 刷新日记列表 } } @SuppressLint("NotifyDataSetChanged") private void loadDiaries() { diaryList.clear(); // 清空当前列表 diaryList.addAll(dbHelper.getDiariesByUserId(userId)); // 从数据库重新获取数据 diaryAdapter.notifyDataSetChanged(); // 通知适配器数据已更改 } private void initView() { rvDiaryList=findViewById(R.id.rvDiaryList); rvDiaryList.setLayoutManager(new LinearLayoutManager(this)); diaryList=new ArrayList<>(); // 确保传递 userId 给 DiaryAdapter diaryAdapter=new DiaryAdapter(this,diaryList,userId); rvDiaryList.setAdapter(diaryAdapter); } }RegisterActivity:package com.example.diaryapp; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.example.diaryapp.utils.DatabaseHelper; public class RegisterActivity extends AppCompatActivity { private EditText etUsername,etPassword,etConfirmPassword; private Button btnRegister; private DatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_register); // 初始化界面组件 initView(); // 注册按钮监听 btnRegister=findViewById(R.id.btnRegister); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { registerUser(); } }); // 返回登录按钮监听 Button btnBack=findViewById(R.id.btnBack); btnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(RegisterActivity.this, LoginActivity.class); startActivity(intent); } }); } private void registerUser() { String username=etUsername.getText().toString().trim(); String password=etPassword.getText().toString().trim(); String confirmPassword=etConfirmPassword.getText().toString().trim(); // 验证输入 if (username.isEmpty() || password.isEmpty() || confirmPassword.isEmpty()){ Toast.makeText(this, "所有字段不能为空", Toast.LENGTH_SHORT).show(); return; } if (!password.equals(confirmPassword)){ Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); return; } // 检查用户名是否已被注册 if (dbHelper.checkUser(username,password)){ Toast.makeText(this, "该用户名已被注册", Toast.LENGTH_SHORT).show(); return; } // 注册新用户 long result=dbHelper.addUser(username,password); if (result > 0){ Toast.makeText(this, "注册成功", Toast.LENGTH_SHORT).show(); Intent intent=new Intent(RegisterActivity.this,LoginActivity.class); startActivity(intent); finish(); }else { Toast.makeText(this, "注册失败", Toast.LENGTH_SHORT).show(); } } private void initView() { etUsername=findViewById(R.id.etUsername); etPassword=findViewById(R.id.etPassword); etConfirmPassword=findViewById(R.id.etConfirmPassword); dbHelper=new DatabaseHelper(this); } }
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值