Add SimpleCameraActivity for crash debugging - minimal camera with only preview and capture
This commit is contained in:
@@ -26,6 +26,10 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".SimpleCameraActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -49,6 +49,7 @@ class CameraActivity : AppCompatActivity() {
|
|||||||
private lateinit var photoPreviewLayout: LinearLayout
|
private lateinit var photoPreviewLayout: LinearLayout
|
||||||
private var imageCapture: ImageCapture? = null
|
private var imageCapture: ImageCapture? = null
|
||||||
private lateinit var cameraExecutor: ExecutorService
|
private lateinit var cameraExecutor: ExecutorService
|
||||||
|
private var cameraProvider: ProcessCameraProvider? = null
|
||||||
|
|
||||||
// 存储拍摄的图片URI
|
// 存储拍摄的图片URI
|
||||||
private val capturedImageUris = mutableListOf<Uri>()
|
private val capturedImageUris = mutableListOf<Uri>()
|
||||||
@@ -65,6 +66,9 @@ class CameraActivity : AppCompatActivity() {
|
|||||||
settingsButton = findViewById(R.id.settingsButton)
|
settingsButton = findViewById(R.id.settingsButton)
|
||||||
photoPreviewLayout = findViewById(R.id.photoPreviewLayout)
|
photoPreviewLayout = findViewById(R.id.photoPreviewLayout)
|
||||||
|
|
||||||
|
// 初始化线程池
|
||||||
|
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
// 请求权限
|
// 请求权限
|
||||||
if (allPermissionsGranted()) {
|
if (allPermissionsGranted()) {
|
||||||
startCamera()
|
startCamera()
|
||||||
@@ -77,9 +81,12 @@ class CameraActivity : AppCompatActivity() {
|
|||||||
// 设置点击监听器
|
// 设置点击监听器
|
||||||
captureButton.setOnClickListener { takePhoto() }
|
captureButton.setOnClickListener { takePhoto() }
|
||||||
settingsButton.setOnClickListener { openSettings() }
|
settingsButton.setOnClickListener { openSettings() }
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化线程池
|
override fun onDestroy() {
|
||||||
cameraExecutor = Executors.newSingleThreadExecutor()
|
super.onDestroy()
|
||||||
|
cameraExecutor.shutdown()
|
||||||
|
cameraProvider?.unbindAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
|
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
|
||||||
@@ -90,35 +97,39 @@ class CameraActivity : AppCompatActivity() {
|
|||||||
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
||||||
|
|
||||||
cameraProviderFuture.addListener({
|
cameraProviderFuture.addListener({
|
||||||
val cameraProvider = cameraProviderFuture.get()
|
|
||||||
|
|
||||||
// 预览
|
|
||||||
val preview = Preview.Builder()
|
|
||||||
.build()
|
|
||||||
.also {
|
|
||||||
it.setSurfaceProvider(viewFinder.surfaceProvider)
|
|
||||||
}
|
|
||||||
|
|
||||||
imageCapture = ImageCapture.Builder()
|
|
||||||
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cameraProvider.unbindAll()
|
cameraProvider = cameraProviderFuture.get()
|
||||||
cameraProvider.bindToLifecycle(
|
|
||||||
|
// 预览
|
||||||
|
val preview = Preview.Builder()
|
||||||
|
.build()
|
||||||
|
.also {
|
||||||
|
it.setSurfaceProvider(viewFinder.surfaceProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
imageCapture = ImageCapture.Builder()
|
||||||
|
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||||
|
|
||||||
|
cameraProvider?.unbindAll()
|
||||||
|
cameraProvider?.bindToLifecycle(
|
||||||
this, cameraSelector, preview, imageCapture
|
this, cameraSelector, preview, imageCapture
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "相机绑定失败", e)
|
Log.e(TAG, "相机初始化失败: ${e.message}", e)
|
||||||
|
Toast.makeText(this, "相机启动失败: ${e.message}", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}, ContextCompat.getMainExecutor(this))
|
}, ContextCompat.getMainExecutor(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
private fun takePhoto() {
|
private fun takePhoto() {
|
||||||
val imageCapture = this.imageCapture ?: return
|
val imageCapture = this.imageCapture ?: run {
|
||||||
|
Toast.makeText(this, "相机未准备好", Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val outputOptions = createOutputFileOptions()
|
val outputOptions = createOutputFileOptions()
|
||||||
|
|
||||||
@@ -143,7 +154,7 @@ class CameraActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onError(exception: ImageCaptureException) {
|
override fun onError(exception: ImageCaptureException) {
|
||||||
Log.e(TAG, "拍照失败: ${exception.message}", exception)
|
Log.e(TAG, "拍照失败: ${exception.message}", exception)
|
||||||
Toast.makeText(baseContext, "拍照失败", Toast.LENGTH_SHORT).show()
|
Toast.makeText(baseContext, "拍照失败: ${exception.message}", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -308,8 +319,9 @@ class CameraActivity : AppCompatActivity() {
|
|||||||
if (allPermissionsGranted()) {
|
if (allPermissionsGranted()) {
|
||||||
startCamera()
|
startCamera()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "权限被拒绝,相机功能不可用", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "相机权限被拒绝,应用无法使用相机功能", Toast.LENGTH_LONG).show()
|
||||||
// 可以在这里提供降级功能,比如手动输入位置信息
|
// 可以选择关闭应用或提供替代功能
|
||||||
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
// 直接启动相机Activity
|
// 启动极简相机Activity
|
||||||
startActivity(Intent(this, CameraActivity::class.java))
|
startActivity(Intent(this, SimpleCameraActivity::class.java))
|
||||||
finish() // 关闭MainActivity,避免返回键回到空白页面
|
finish() // 关闭MainActivity,避免返回键回到空白页面
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
170
app/src/main/java/com/example/app/SimpleCameraActivity.kt
Normal file
170
app/src/main/java/com/example/app/SimpleCameraActivity.kt
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
package com.example.app
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.MediaStore
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.camera.core.CameraSelector
|
||||||
|
import androidx.camera.core.ImageCapture
|
||||||
|
import androidx.camera.core.ImageCaptureException
|
||||||
|
import androidx.camera.core.Preview
|
||||||
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
|
import androidx.camera.view.PreviewView
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
class SimpleCameraActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "SimpleCamera"
|
||||||
|
private const val REQUEST_CODE_PERMISSIONS = 10
|
||||||
|
private val REQUIRED_PERMISSIONS = arrayOf(
|
||||||
|
Manifest.permission.CAMERA
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var viewFinder: PreviewView
|
||||||
|
private lateinit var captureButton: FloatingActionButton
|
||||||
|
private var imageCapture: ImageCapture? = null
|
||||||
|
private lateinit var cameraExecutor: ExecutorService
|
||||||
|
private var cameraProvider: ProcessCameraProvider? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_simple_camera)
|
||||||
|
|
||||||
|
// 初始化视图
|
||||||
|
viewFinder = findViewById(R.id.viewFinder)
|
||||||
|
captureButton = findViewById(R.id.captureButton)
|
||||||
|
|
||||||
|
// 初始化线程池
|
||||||
|
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
|
// 请求权限
|
||||||
|
if (allPermissionsGranted()) {
|
||||||
|
startCamera()
|
||||||
|
} else {
|
||||||
|
ActivityCompat.requestPermissions(
|
||||||
|
this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置拍照按钮点击监听器
|
||||||
|
captureButton.setOnClickListener { takePhoto() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
cameraExecutor.shutdown()
|
||||||
|
cameraProvider?.unbindAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
|
||||||
|
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startCamera() {
|
||||||
|
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
||||||
|
|
||||||
|
cameraProviderFuture.addListener({
|
||||||
|
try {
|
||||||
|
cameraProvider = cameraProviderFuture.get()
|
||||||
|
|
||||||
|
// 预览
|
||||||
|
val preview = Preview.Builder()
|
||||||
|
.build()
|
||||||
|
.also {
|
||||||
|
it.setSurfaceProvider(viewFinder.surfaceProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
imageCapture = ImageCapture.Builder()
|
||||||
|
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||||
|
|
||||||
|
cameraProvider?.unbindAll()
|
||||||
|
cameraProvider?.bindToLifecycle(
|
||||||
|
this, cameraSelector, preview, imageCapture
|
||||||
|
)
|
||||||
|
|
||||||
|
Log.d(TAG, "相机启动成功")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "相机初始化失败: ${e.message}", e)
|
||||||
|
Toast.makeText(this, "相机启动失败: ${e.message}", Toast.LENGTH_LONG).show()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}, ContextCompat.getMainExecutor(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun takePhoto() {
|
||||||
|
val imageCapture = this.imageCapture ?: run {
|
||||||
|
Toast.makeText(this, "相机未准备好", Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
|
||||||
|
|
||||||
|
val contentValues = ContentValues().apply {
|
||||||
|
put(MediaStore.MediaColumns.DISPLAY_NAME, "巡检_$timestamp")
|
||||||
|
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/LogCam")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val contentResolver = contentResolver
|
||||||
|
val uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
Toast.makeText(this, "创建文件失败", Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver, uri, contentValues).build()
|
||||||
|
|
||||||
|
imageCapture.takePicture(
|
||||||
|
outputOptions,
|
||||||
|
ContextCompat.getMainExecutor(this),
|
||||||
|
object : ImageCapture.OnImageSavedCallback {
|
||||||
|
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||||
|
val savedUri = outputFileResults.savedUri ?: return
|
||||||
|
val msg = "照片已保存: ${savedUri.lastPathSegment}"
|
||||||
|
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
|
||||||
|
Log.d(TAG, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(exception: ImageCaptureException) {
|
||||||
|
Log.e(TAG, "拍照失败: ${exception.message}", exception)
|
||||||
|
Toast.makeText(baseContext, "拍照失败: ${exception.message}", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(
|
||||||
|
requestCode: Int,
|
||||||
|
permissions: Array<String>,
|
||||||
|
grantResults: IntArray
|
||||||
|
) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
if (requestCode == REQUEST_CODE_PERMISSIONS) {
|
||||||
|
if (allPermissionsGranted()) {
|
||||||
|
startCamera()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "相机权限被拒绝,应用无法使用相机功能", Toast.LENGTH_LONG).show()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
app/src/main/res/layout/activity_simple_camera.xml
Normal file
46
app/src/main/res/layout/activity_simple_camera.xml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".SimpleCameraActivity">
|
||||||
|
|
||||||
|
<!-- 相机预览视图 -->
|
||||||
|
<androidx.camera.view.PreviewView
|
||||||
|
android:id="@+id/viewFinder"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<!-- 拍照按钮 -->
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/captureButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="32dp"
|
||||||
|
android:src="@android:drawable/ic_menu_camera"
|
||||||
|
app:backgroundTint="@color/primary"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<!-- 状态提示 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/statusText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="极简相机 - 点击下方按钮拍照"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:background="#80000000"
|
||||||
|
android:padding="8dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -7,4 +7,5 @@
|
|||||||
<color name="teal_700">#FF018786</color>
|
<color name="teal_700">#FF018786</color>
|
||||||
<color name="black">#FF000000</color>
|
<color name="black">#FF000000</color>
|
||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
<color name="primary">#FF6200EE</color>
|
||||||
</resources>
|
</resources>
|
||||||
83
create-signing.sh
Normal file
83
create-signing.sh
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 创建Android应用签名文件并生成Base64字符串
|
||||||
|
|
||||||
|
echo "=== Android应用签名生成工具 ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 检查keytool是否可用
|
||||||
|
if ! command -v keytool &> /dev/null; then
|
||||||
|
echo "❌ keytool命令未找到,请安装Java JDK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 签名配置
|
||||||
|
KEYSTORE_NAME="logcam-release.jks"
|
||||||
|
ALIAS="logcam-release-key"
|
||||||
|
STORE_PASS="android123"
|
||||||
|
KEY_PASS="android123"
|
||||||
|
DNAME="CN=LogCam, OU=Development, O=Example, L=Beijing, ST=Beijing, C=CN"
|
||||||
|
|
||||||
|
echo "📋 签名配置:"
|
||||||
|
echo " - 密钥库文件: $KEYSTORE_NAME"
|
||||||
|
echo " - 别名: $ALIAS"
|
||||||
|
echo " - 密钥库密码: $STORE_PASS"
|
||||||
|
echo " - 密钥密码: $KEY_PASS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 生成签名文件
|
||||||
|
echo "🔑 生成签名文件..."
|
||||||
|
keytool -genkeypair -v \
|
||||||
|
-keystore "$KEYSTORE_NAME" \
|
||||||
|
-keyalg RSA -keysize 2048 \
|
||||||
|
-validity 10000 \
|
||||||
|
-alias "$ALIAS" \
|
||||||
|
-storepass "$STORE_PASS" \
|
||||||
|
-keypass "$KEY_PASS" \
|
||||||
|
-dname "$DNAME"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ 签名文件生成成功: $KEYSTORE_NAME"
|
||||||
|
ls -la "$KEYSTORE_NAME"
|
||||||
|
else
|
||||||
|
echo "❌ 签名文件生成失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔄 生成Base64字符串..."
|
||||||
|
# 生成Base64字符串
|
||||||
|
SIGNING_KEY_BASE64=$(base64 -w 0 "$KEYSTORE_NAME")
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ Base64字符串生成成功"
|
||||||
|
else
|
||||||
|
echo "❌ Base64转换失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📋 GitHub Secrets配置信息:"
|
||||||
|
echo "========================================"
|
||||||
|
echo "SIGNING_KEY (密钥文件Base64):"
|
||||||
|
echo "$SIGNING_KEY_BASE64"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
echo "ALIAS (别名): $ALIAS"
|
||||||
|
echo "KEYSTORE_PASSWORD (密钥库密码): $STORE_PASS"
|
||||||
|
echo "KEY_PASSWORD (密钥密码): $KEY_PASS"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
echo "📱 后续步骤:"
|
||||||
|
echo "1. 访问 https://github.com/xiajid/logcam/settings/secrets/actions"
|
||||||
|
echo "2. 创建以下Secrets:"
|
||||||
|
echo " - SIGNING_KEY: 粘贴上面的Base64字符串"
|
||||||
|
echo " - ALIAS: \"$ALIAS\""
|
||||||
|
echo " - KEYSTORE_PASSWORD: \"$STORE_PASS\""
|
||||||
|
echo " - KEY_PASSWORD: \"$KEY_PASS\""
|
||||||
|
echo "3. 提交新工作流文件"
|
||||||
|
echo "4. 触发构建获得签名版APK"
|
||||||
|
echo ""
|
||||||
|
echo "🔧 签名文件信息:"
|
||||||
|
keytool -list -v -keystore "$KEYSTORE_NAME" -storepass "$STORE_PASS" | grep -E "别名|有效期|指纹"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ 签名流程完成"
|
||||||
Reference in New Issue
Block a user