本專案完成後的範例效果如下圖所示,左方按鈕可以進行拍照,右方紅色按鈕則可以開始進行直播

下載套件
開啟 settings.gradle.kts,在 dependencyResolutionManagement 新增 jitpack 下載庫,如下藍色設定
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}
開啟 build.gradle.kts(Module),新增藍色部份
android{
..............
buildFeatures{
dataBinding = true
viewBinding = true
}
}
dependencies {
............
implementation ("com.github.pedroSG94.RootEncoder:library:2.5.4")
implementation ("com.github.pedroSG94.RootEncoder:extra-sources:2.5.4")
}
權限
AndroidManifest.xml 新增藍色權限設定
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
.........
Layout
RootEncoder 使用 Android 系統預設的 SurfaceView 來顯示影片,但如果直接在 Layout 置入 SurfaceView 會有問題。所以請在 Layout 中置入 LinearLayout,到了後面才由程式碼把 SurfaceView 加入 LinearLayout 中。
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:background="#000000"
android:orientation="horizontal"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:alpha="0.5"
android:id="@+id/btnVideo"
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@drawable/ic_video_start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:onClick="btnVideo_click"/>
<ImageButton
android:alpha="0.5"
android:id="@+id/btnPicture"
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@drawable/baseline_camera_24"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:onClick="btnPicture_click"/>
</androidx.constraintlayout.widget.ConstraintLayout>
baseline_camera_24.xml
上述的 baseline_camera_24.xml 的代碼如下
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#7755F5" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M9.4,10.5l4.77,-8.26C13.47,2.09 12.75,2 12,2c-2.4,0 -4.6,0.85 -6.32,2.25l3.66,6.35 0.06,-0.1zM21.54,9c-0.92,-2.92 -3.15,-5.26 -6,-6.34L11.88,9h9.66zM21.8,10h-7.49l0.29,0.5 4.76,8.25C21,16.97 22,14.61 22,12c0,-0.69 -0.07,-1.35 -0.2,-2zM8.54,12l-3.9,-6.75C3.01,7.03 2,9.39 2,12c0,0.69 0.07,1.35 0.2,2h7.49l-1.15,-2zM2.46,15c0.92,2.92 3.15,5.26 6,6.34L12.12,15L2.46,15zM13.73,15l-3.9,6.76c0.7,0.15 1.42,0.24 2.17,0.24 2.4,0 4.6,-0.85 6.32,-2.25l-3.66,-6.35 -0.93,1.6z"/>
</vector>
MainActivity.kt
MainActivity.kt 先開啟權限,完整代碼如下
package net.ddns.mahaljsp.travelc
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import net.ddns.mahaljsp.travelc.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var permission:MainPermission
lateinit var ui: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//enableEdgeToEdge()
ui= ActivityMainBinding.inflate(layoutInflater)
setContentView(ui.root)
permission= MainPermission(this)
}
fun init(){
//todo
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults:IntArray){
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
permission.result(this, requestCode)
}
}
Permission.kt
上述的 Permission 完整代碼如下
package net.ddns.mahaljsp.travelc
import android.Manifest
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Build
import android.view.WindowInsets
import android.view.WindowInsetsController
import android.view.WindowManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainPermission(context: Context) {
val REQUEST_CODE = 10
val REQUIRED_PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
)
fun allPermissionsGranted(context: Context) = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
init{
//視窗最大化
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
var controller: WindowInsetsController? = (context as MainActivity).window.insetsController
controller?.hide(WindowInsets.Type.statusBars())
//controller?.hide(WindowInsets.Type.navigationBars())
} else {
@Suppress("DEPRECATION")
(context as MainActivity).window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
}
(context as MainActivity).window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
//取得權限
if(!allPermissionsGranted(context)){
ActivityCompat.requestPermissions(context as MainActivity,
REQUIRED_PERMISSIONS,
REQUEST_CODE
)
}
else{
(context as MainActivity).init()
}
}
fun result(context: Context,requestCode:Int){
if (requestCode== REQUEST_CODE) {
if(!allPermissionsGranted(context)){
(context as MainActivity).init()
val dialog= AlertDialog.Builder(context)
dialog
.setTitle("旅遊記")
.setMessage("因您拒絕授權手機相關權限\n本程式無法提供AI派工服務\n\n若您真有需求, 請移除本程式, 並重新安裝")
.setPositiveButton("離開", DialogInterface.OnClickListener{ _, _->
(context as MainActivity).finish()
})
.show()
}
else{
(context as MainActivity).init()
}
}
}
}
