desc:摄像头视频预览
							parent
							
								
									65cc6c2d5f
								
							
						
					
					
						commit
						e0feb94d2a
					
				
											
												Binary file not shown.
											
										
									
								| @ -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) { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue