This commit is contained in:
2022-03-11 08:43:32 +08:00
commit 8f9ae202db
148 changed files with 23318 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
package com.yutou.doormanager
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.yutou.doormanager", appContext.packageName)
}
}

View File

@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yutou.doormanager">
<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.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Design.NoActionBar"
android:usesCleartextTraffic="true">
<meta-data
android:name="com.google.android.actions"
android:resource="@xml/provider_paths" />
<activity
android:name=".MainActivity"
android:exported="true"
android:screenOrientation="fullSensor">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SMSActivity">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SENDTO"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="sms"/>
<data android:scheme="smsto"/>
<data android:scheme="mms"/>
<data android:scheme="mmsto"/>
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<receiver
android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver
android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER"/>
<data android:mimeType="application/vnd.wap.mms-message"/>
</intent-filter>
</receiver>
<!-- Service that delivers messages from the phone "quick response" -->
<service
android:name=".SmsSendService"
android:exported="true"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
</manifest>

View File

@@ -0,0 +1,15 @@
package com.yutou.doormanager;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
public class HeadlessSmsSendService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@@ -0,0 +1,263 @@
package com.yutou.doormanager
import android.Manifest
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Rect
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.provider.Telephony
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.FileProvider
import com.yutou.doormanager.utils.*
import jp.co.cyberagent.android.gpuimage.GPUImageAddBlendFilter
import me.lake.librestreaming.core.listener.RESConnectionListener
import me.lake.librestreaming.filter.hardvideofilter.BaseHardVideoFilter
import me.lake.librestreaming.filter.hardvideofilter.HardVideoGroupFilter
import me.lake.librestreaming.ws.StreamAVOption
import me.lake.librestreaming.ws.StreamLiveCameraView
import me.lake.librestreaming.ws.filter.hardfilter.WatermarkFilter
import me.lake.librestreaming.ws.filter.hardfilter.extra.GPUImageCompatibleFilter
import org.json.JSONObject
import java.io.File
import java.util.*
class MainActivity : AppCompatActivity() {
private lateinit var button_up: Button
private lateinit var button_down: Button
private lateinit var button_screen: Button
private lateinit var button_open: Button
private lateinit var button_af: Button
private lateinit var mLiveCameraView: StreamLiveCameraView
private var zoom = 0.0f
private var isUpdate = true
public lateinit var myDataListener: MyDataListener
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.SEND_SMS
), 0
)
initView()
startRTMP()
myDataListener = MyDataListener()
DataUtils.addListener(myDataListener)
val intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
intent.putExtra(
Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
packageName
)
startActivity(intent)
val batteryLevelRcvr=SmsReceiver()
val batteryLevelFilter= IntentFilter(Intent.ACTION_BATTERY_CHANGED)
registerReceiver(batteryLevelRcvr, batteryLevelFilter)
Toast.makeText(this,"version = ${ packageManager.getPackageInfo(packageName, 0).versionName}",Toast.LENGTH_LONG).show()
}
private fun initView() {
button_up = findViewById(R.id.up)
button_down = findViewById(R.id.down)
button_screen = findViewById(R.id.screen)
button_open = findViewById(R.id.openPC)
button_af = findViewById(R.id.af)
button_up.setOnClickListener {
zoom += 0.1f
if (zoom > 1.0f) {
zoom = 1.0f
}
mLiveCameraView.setZoomByPercent(zoom)
uploadZoom(zoom)
}
button_down.setOnClickListener {
zoom -= 0.1f
if (zoom < 0f) {
zoom = 0.0f
}
mLiveCameraView.setZoomByPercent(zoom)
uploadZoom(zoom)
}
button_screen.setOnClickListener {
mLiveCameraView.takeScreenShot {
Utils.upload(it, this)
Handler(Looper.getMainLooper()).post {
Toast.makeText(this@MainActivity, "已拍照", Toast.LENGTH_LONG).show()
}
}
}
button_open.setOnClickListener {
val json = JSONObject()
json.put("type", "nas")
HttpUtils.post(
"http://192.168.31.88:8000/tools/openpc.do",
json,
null,
object : HttpListener {
override fun data(code: Int, data: String) {
Handler(Looper.getMainLooper()).post {
Toast.makeText(this@MainActivity, "开机成功:${data}", Toast.LENGTH_LONG)
.show()
}
}
})
}
button_af.setOnClickListener {
mLiveCameraView.setCreamAr()
}
}
private fun uploadZoom(zoom: Float) {
val json = JSONObject()
json.put("zoom", zoom)
HttpUtils.post("http://192.168.31.88:8000/door/zoom.do", json, null, object : HttpListener {
override fun data(code: Int, data: String) {
if (data == "1") {
Handler(Looper.getMainLooper()).post {
Toast.makeText(this@MainActivity, "设置成功:${zoom}", Toast.LENGTH_LONG).show()
}
}
}
})
}
lateinit var watermark: WatermarkFilter
private fun startRTMP() {
mLiveCameraView = findViewById(R.id.stream_previewView)
mLiveCameraView.setActivity(this)
val option = StreamAVOption().apply {
streamUrl = "rtmp://192.168.31.88/live"
}
mLiveCameraView.let {
it.init(this, option)
it.addStreamStateListener(object : RESConnectionListener {
override fun onOpenConnectionResult(result: Int) {
mLiveCameraView.setCreamAr()
}
override fun onWriteError(errno: Int) {
}
override fun onCloseConnectionResult(result: Int) {
}
})
val files: LinkedList<BaseHardVideoFilter> = LinkedList()
watermark =
WatermarkFilter(
WatermarkFilter.fromText(32f, Utils.getTime()),
Rect(50, 50, 800, 150)
)
// it.setMirror(true, true, true)
files.add(GPUImageCompatibleFilter(GPUImageAddBlendFilter()))
files.add(watermark)
it.setHardVideoFilter(HardVideoGroupFilter(files))
it.startStreaming(option.streamUrl)
Timer().schedule(object : TimerTask() {
override fun run() {
watermark.updateText(32f, Utils.getTime()+" 推流:${mLiveCameraView.avSpeed}")
if (!mLiveCameraView.isStreaming||mLiveCameraView.avSpeed==0) {
mLiveCameraView.stopStreaming()
mLiveCameraView.startStreaming("rtmp://192.168.31.88/live")
}
}
}, 0, 1000)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
}
override fun onDestroy() {
super.onDestroy()
mLiveCameraView.destroy()
DataUtils.removeListener(myDataListener)
}
inner class MyDataListener : DataListener {
override fun out(json: JSONObject) {
Handler(Looper.getMainLooper()).post {
zoom = json.getDouble("zoom").toFloat()
mLiveCameraView.setZoomByPercent(zoom)
if (json.getString("restart").equals("1")) {
val intent = packageManager.getLaunchIntentForPackage(packageName);
intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent)
android.os.Process.killProcess(android.os.Process.myPid());
}
if (!json.getString("audio").equals("null"))
AudioUtils().play(json.getString("audio"))
if (!json.isNull("update")) {
val versionName = packageManager.getPackageInfo(packageName, 0).versionName
if (json.getJSONObject("update").getString("versionName") != versionName) {
val url = json.getJSONObject("update").getString("url")
if (isUpdate) {
isUpdate = false
update(url, json.getJSONObject("update").getString("versionName"))
}
}
}
if(!json.isNull("af")){
mLiveCameraView.setCreamAr()
}
}
}
}
private fun update(url: String, version: String) {
val dialog = AlertDialog.Builder(this).apply {
val appVersionName = packageManager.getPackageInfo(packageName, 0).versionName
setTitle("检测到版本更新")
setMessage("当前版本号:${appVersionName}\n更新版本号:${version}\n是否更新?")
setPositiveButton("更新") { _, _ ->
HttpUtils.download(
url,
filesDir.absolutePath + File.separator + "download.apk",
object : HttpListener {
override fun data(code: Int, data: String) {
val intent = Intent(Intent.ACTION_VIEW)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
var apkUri = Uri.fromFile(File(data))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
apkUri = FileProvider.getUriForFile(
this@MainActivity, "$packageName.fileprovider",
File(data)
)
}
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
startActivity(intent)
}
});
}
setNegativeButton(
"取消"
) { p0, _ -> p0?.cancel() }
}
dialog.show()
}
}

View File

@@ -0,0 +1,12 @@
package com.yutou.doormanager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
}
}

View File

@@ -0,0 +1,46 @@
package com.yutou.doormanager
import android.app.Activity
import android.app.Application
import android.os.Bundle
import com.yutou.doormanager.utils.DataUtils
import java.lang.ref.WeakReference
class MyApplication: Application() {
companion object{
lateinit var activitys:WeakReference<Activity>
}
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityCreated(p0: Activity, p1: Bundle?) {
activitys=WeakReference(p0)
}
override fun onActivityStarted(p0: Activity) {
TODO("Not yet implemented")
}
override fun onActivityResumed(p0: Activity) {
TODO("Not yet implemented")
}
override fun onActivityPaused(p0: Activity) {
TODO("Not yet implemented")
}
override fun onActivityStopped(p0: Activity) {
TODO("Not yet implemented")
}
override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {
TODO("Not yet implemented")
}
override fun onActivityDestroyed(p0: Activity) {
TODO("Not yet implemented")
}
})
}
}

View File

@@ -0,0 +1,12 @@
package com.yutou.doormanager
import androidx.lifecycle.ViewModel
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class MyViewModel:ViewModel() {
var index:Int = 0
val data:String by lazy {
"data = "+index
}
}

View File

@@ -0,0 +1,14 @@
package com.yutou.doormanager;
import android.app.Activity;
import android.os.Bundle;
import android.telephony.SmsManager;
import androidx.annotation.Nullable;
public class SMSActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}

View File

@@ -0,0 +1,44 @@
package com.yutou.doormanager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import com.yutou.doormanager.utils.SmsUtils;
public class SmsReceiver extends BroadcastReceiver {
private static boolean isLowPower = true;
private static boolean isPower = true;
public static int powerData=0;
private static int power=100;
@Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra("status", -1);
int rawlevel = intent.getIntExtra("level", -1);
int scale = intent.getIntExtra("scale", -1);
int level = -1;
if(rawlevel >= 0 && scale > 0){
level = (rawlevel*100)/scale;
}
powerData=status;
if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
isPower = true;
if (isLowPower) {
SmsUtils.Companion.sendSms("监控电源已断开", context);
isLowPower = false;
}
if(level!=power&&level%10==0){
SmsUtils.Companion.sendSms("监控剩余电量:"+level,context);
power=level;
}
} else {
isLowPower = true;
if (isPower) {
SmsUtils.Companion.sendSms("监控电源已连接", context);
isPower = false;
}
}
}
}

View File

@@ -0,0 +1,22 @@
package com.yutou.doormanager;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import androidx.annotation.Nullable;
public class SmsSendService extends Service {
class MyBinder extends Binder {
public SmsSendService getService(){
return SmsSendService.this;
}
}
private MyBinder binder=new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}

View File

@@ -0,0 +1,8 @@
package com.yutou.doormanager
class TestData {
val str by lazy {
println("Init lazy")
"Hello World"
}
}

View File

@@ -0,0 +1,21 @@
package com.yutou.doormanager.utils
import android.media.MediaPlayer
class AudioUtils() {
fun play(url: String) {
println("url = ${url}")
val player = MediaPlayer()
player.isLooping = false
player.setOnCompletionListener {
println(" --> play over")
it.release()
}
//setAudioStreamType(AudioManager.STREAM_MUSIC)
player.setDataSource(url)
player.prepare() // might take long! (for buffering, etc)
player.start()
}
}

View File

@@ -0,0 +1,7 @@
package com.yutou.doormanager.utils
import org.json.JSONObject
interface DataListener {
fun out(json:JSONObject)
}

View File

@@ -0,0 +1,50 @@
package com.yutou.doormanager.utils
import org.json.JSONObject
import java.util.*
import kotlin.collections.ArrayList
class DataUtils {
var listener= ArrayList<DataListener>()
companion object{
private var instance:DataUtils?=null
get() {
if(field==null){
field= DataUtils()
}
return field
}
@Synchronized
fun get():DataUtils{
return instance!!
}
fun addListener(_listener: DataListener){
instance!!.listener.add(_listener)
}
fun removeListener(_listener: DataListener){
instance!!.listener.remove(_listener)
}
}
init {
run()
}
private fun run(){
Timer().schedule(object : TimerTask() {
override fun run() {
val json=JSONObject()
json.put("def","")
HttpUtils.post("http://192.168.31.88:8000/door/data.do",json,null,object :HttpListener{
override fun data(code: Int, data: String) {
if(code==200){
listener.forEach { it.out(JSONObject(data)) }
}
}
})
}
},0,1000)
}
}

View File

@@ -0,0 +1,5 @@
package com.yutou.doormanager.utils
interface HttpListener{
fun data(code:Int,data:String)
}

View File

@@ -0,0 +1,88 @@
package com.yutou.doormanager.utils
import okhttp3.*
import okhttp3.RequestBody.Companion.asRequestBody
import org.json.JSONObject
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
class HttpUtils {
companion object {
fun uploadImage(body: JSONObject) {
post(
"http://192.168.31.88:802/qq/file.do",
body,
File(body.getString("filePath")),
object : HttpListener {
override fun data(code: Int, data: String) {
}
})
}
fun post(url: String, json: JSONObject, file: File?, listener: HttpListener) {
val client = OkHttpClient()
val builder = Request.Builder()
builder.url(url)
.post(
MultipartBody.Builder().run {
if (file != null) {
addFormDataPart(
"image",
json.getString("fileName"),
file.asRequestBody()
)
}
json.keys().forEach {
addFormDataPart(it, json.getString(it))
}
build()
}
)
client.newCall(builder.build()).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
print("failure = ")
println(e)
}
override fun onResponse(call: Call, response: Response) {
listener.data(response.code, response.body!!.string())
}
})
}
fun download(url: String, filePath: String, listener: HttpListener) {
val client = OkHttpClient()
val builder = Request.Builder().url(url).build()
client.newCall(builder).enqueue(object :Callback{
override fun onFailure(call: Call, e: IOException) {
println(e)
}
override fun onResponse(call: Call, response: Response) {
if(response.isSuccessful){
if(File(filePath).exists()){
File(filePath).delete()
}
println("文件大小:"+response.body?.contentLength())
val inputStream=response.body?.byteStream()
val outputStream=FileOutputStream(filePath)
val bytes= ByteArray(1024)
var len=0
while ((inputStream?.read(bytes)).also { len=it!! }!=-1){
outputStream.write(bytes,0,len)
outputStream.flush()
}
outputStream.close()
inputStream?.close()
println("实际文件大小:"+File(filePath).length())
listener.data(0,filePath)
}
}
})
}
}
}

View File

@@ -0,0 +1,29 @@
package com.yutou.doormanager.utils
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.telephony.SmsManager
class SmsUtils {
companion object{
fun sendSms(message:String, context:Context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
var smsManager= context.getSystemService(SmsManager::class.java)
val sentIntent = Intent("SENT_SMS_ACTION")
val sentPI = PendingIntent.getBroadcast(context, 0, sentIntent, 0)
val deliverIntent = Intent("DELIVERED_SMS_ACTION")
val deliverPI = PendingIntent.getBroadcast(context, 0, deliverIntent, 0)
if(smsManager==null)
smsManager=SmsManager.getDefault()
println("smsManager = ${smsManager}")
smsManager.sendTextMessage("+8613687358829", null, message, sentPI, deliverPI)
} else {
return
}
}
}
}

View File

@@ -0,0 +1,32 @@
package com.yutou.doormanager.utils
import android.content.Context
import android.graphics.Bitmap
import org.json.JSONObject
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.*
class Utils {
companion object {
fun upload(bitmap: Bitmap, context: Context) {
val file = File(context.cacheDir.absolutePath + File.separator + "tmp.png")
val out = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
out.apply {
flush()
close()
}
val json=JSONObject()
json.put("fileName",file.name)
json.put("filePath",file.absolutePath)
HttpUtils.uploadImage(json)
// file.deleteOnExit()
}
fun getTime():String{
return SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss", Locale.CHINA).format(Date())
}
}
}

View File

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,60 @@
<?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=".MainActivity">
<!-- <androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />-->
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="wrap_content"
android:gravity="center"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/stream_previewView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="@+id/up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="@string/button_up" />
<Button
android:id="@+id/down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_down" />
<Button
android:id="@+id/screen"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_screen" />
<Button
android:id="@+id/af"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_af" />
</LinearLayout>
<me.lake.librestreaming.ws.StreamLiveCameraView
android:id="@+id/stream_previewView"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/linearLayout"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,64 @@
<?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=".MainActivity">
<!-- <androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />-->
<me.lake.librestreaming.ws.StreamLiveCameraView
android:id="@+id/stream_previewView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="64dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_up"/>
<Button
android:id="@+id/down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_down" />
<Button
android:id="@+id/screen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_screen" />
<Button
android:id="@+id/openPC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_open" />
<Button
android:id="@+id/af"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_af" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.DoorManager" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@@ -0,0 +1,8 @@
<resources>
<string name="app_name">DoorManager</string>
<string name="button_up">+</string>
<string name="button_down">-</string>
<string name="button_screen">拍照</string>
<string name="button_open">开机</string>
<string name="button_af">对焦</string>
</resources>

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.DoorManager" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version ="1.0" encoding ="utf-8"?><!-- Learn More about how to use App Actions: https://developer.android.com/guide/actions/index.html -->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path=""/>
<files-path
name="files"
path="." />
</paths>

View File

@@ -0,0 +1,17 @@
package com.yutou.doormanager
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}