desc:摄像头视频预览

main
xiaowusky 2 years ago
parent 65cc6c2d5f
commit e0feb94d2a

@ -26,8 +26,11 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
var lifeCycle_version = '2.5.1'
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifeCycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifeCycle_version"
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.activity:activity-compose:1.5.1'
implementation 'androidx.compose.ui:ui'
@ -36,4 +39,15 @@ dependencies {
implementation 'androidx.compose.material3:material3'
implementation 'androidx.navigation:navigation-runtime-ktx:2.5.2'
implementation "androidx.navigation:navigation-compose:2.4.0-rc01"
implementation 'io.reactivex.rxjava2:rxjava:2.1.6'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
var accompanist_version = '0.30.1'
implementation "com.google.accompanist:accompanist-permissions:$accompanist_version"
implementation project(path: ':library-push')
implementation(name: 'libuvccamera-release', ext: 'aar') {
exclude module: 'support-v4'
exclude module: 'appcompat-v7'
}
}

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature
android:name="android.hardware.usb.host"
android:required="true" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<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" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"

@ -1,5 +1,6 @@
package com.yinuo.safetywatcher
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
@ -15,12 +16,14 @@ import com.yinuo.safetywatcher.navi.NavigationUtil
import com.yinuo.safetywatcher.navi.NavigationView
import com.yinuo.safetywatcher.ui.SplashView
import com.yinuo.safetywatcher.ui.theme.EasypusherTheme
import org.easydarwin.push.MediaStream
class MainActivity : ComponentActivity() {
var exitTime = 0L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startMediaService()
setContent {
EasypusherTheme {
// A surface container using the 'background' color from the theme
@ -41,6 +44,12 @@ class MainActivity : ComponentActivity() {
addBackListener()
}
private fun startMediaService() {
// 启动服务...
val intent = Intent(this, MediaStream::class.java)
startService(intent)
}
private fun addBackListener() {
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {

@ -1,21 +1,64 @@
package com.yinuo.safetywatcher.ui.home
import android.view.TextureView
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.viewmodel.compose.viewModel
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import com.yinuo.safetywatcher.navi.ModelPath
import com.yinuo.safetywatcher.navi.NavigationUtil
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun HomeView() {
Column(modifier = Modifier.fillMaxSize()) {
Text(text = "Home")
// 权限
val permissionsState = rememberMultiplePermissionsState(
permissions = listOf(
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.CAMERA,
)
)
if (permissionsState.allPermissionsGranted) {
val viewModel: HomeViewModel = viewModel()
val context = LocalContext.current
Row(modifier = Modifier.fillMaxSize()) {
AndroidView(factory = {
TextureView(it)
}, modifier = Modifier
.fillMaxHeight()
.width(200.dp), update = {
viewModel.setTextureView(it, context);
})
Button(onClick = { NavigationUtil.to(ModelPath.Setting) }) {
Text(text = "设置")
Column(
modifier = Modifier
.width(150.dp)
.fillMaxHeight()
.background(Color.Red)
) {
Button(onClick = { NavigationUtil.to(ModelPath.Setting) }) {
Text(text = "设置")
}
}
}
} else {
LaunchedEffect(Unit) {
permissionsState.launchMultiplePermissionRequest()
}
}
}

@ -0,0 +1,61 @@
package com.yinuo.safetywatcher.ui.home
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.SurfaceTexture
import android.util.Log
import android.view.TextureView
import androidx.activity.ComponentActivity
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import com.yinuo.safetywatcher.utils.RxHelper
import com.yinuo.safetywatcher.utils.SurfaceTextureListenerWrapper
import io.reactivex.Single
import org.easydarwin.push.MediaStream
class HomeViewModel : ViewModel() {
@SuppressLint("StaticFieldLeak")
private var mediaStream: MediaStream? = null
private fun getMediaStream(context: Context, owner: LifecycleOwner): Single<MediaStream?>? {
val single: Single<MediaStream?> =
RxHelper.single(MediaStream.getBindedMediaStream(context, owner), mediaStream)
return if (mediaStream == null) {
single.doOnSuccess { ms -> mediaStream = ms }
} else {
single
}
}
@SuppressLint("CheckResult")
fun setTextureView(it: TextureView, context: Context) {
if (context is ComponentActivity) {
val activity: ComponentActivity = context
getMediaStream(context, activity)?.subscribe(
{ ms ->
if (it.isAvailable) {
ms?.setSurfaceTexture(it.surfaceTexture)
} else {
it.surfaceTextureListener = object : SurfaceTextureListenerWrapper() {
override fun onSurfaceTextureAvailable(
surfaceTexture: SurfaceTexture,
i: Int,
i1: Int
) {
ms?.setSurfaceTexture(surfaceTexture)
}
override fun onSurfaceTextureDestroyed(surfaceTexture: SurfaceTexture): Boolean {
ms?.setSurfaceTexture(null)
return true
}
}
}
},
{
Log.w("HomeViewModel", "创建服务出错!" + it.message)
})
}
}
}

@ -0,0 +1,47 @@
package com.yinuo.safetywatcher.utils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.easydarwin.util.AbstractSubscriber;
import org.reactivestreams.Publisher;
import io.reactivex.Single;
import io.reactivex.subjects.PublishSubject;
/**
* Created by apple on 2017/12/22.
*/
public class RxHelper {
static boolean IGNORE_ERROR = false;
public static <T> Single<T> single(@NonNull Publisher<T> t, @Nullable T defaultValueIfNotNull){
if (defaultValueIfNotNull != null) return Single.just(defaultValueIfNotNull);
final PublishSubject sub = PublishSubject.create();
t.subscribe(new AbstractSubscriber<T>() {
@Override
public void onNext(T t) {
super.onNext(t);
sub.onNext(t);
}
@Override
public void onError(Throwable t) {
if (IGNORE_ERROR) {
super.onError(t);
sub.onComplete();
}else {
sub.onError(t);
}
}
@Override
public void onComplete() {
super.onComplete();
sub.onComplete();
}
});
return sub.firstOrError();
}
}

@ -0,0 +1,27 @@
package com.yinuo.safetywatcher.utils;
import android.graphics.SurfaceTexture;
import android.view.TextureView;
/**
* Created by apple on 2017/9/11.
*/
public abstract class SurfaceTextureListenerWrapper implements TextureView.SurfaceTextureListener{
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
}

@ -18,6 +18,9 @@ allprojects {
jcenter()
maven { url "https://jitpack.io" }
flatDir {
dirs 'libs'
}
}
}

@ -175,7 +175,7 @@ public class MediaStream extends Service implements LifecycleObserver {
private EasyMuxer mMuxer;
private HandlerThread mCameraThread;
private Handler mCameraHandler;
private boolean cameraOpened;
private boolean cameraOpened = true;
static ServiceConnection conn;
static PushScreenService pushScreenService;
private UVCCamera uvcCamera;

Loading…
Cancel
Save