├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── encodings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── rvirin │ │ └── onvif │ │ └── demo │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── rvirin │ │ │ └── onvif │ │ │ └── demo │ │ │ ├── MainActivity.kt │ │ │ └── StreamActivity.kt │ └── res │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxxhdpi │ │ └── ic_launcher.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_main_alt.xml │ │ ├── activity_stream.xml │ │ └── activity_stream_old.xml │ │ ├── menu │ │ └── stream.xml │ │ ├── values-v26 │ │ └── styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── rvirin │ └── onvif │ └── demo │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle ├── bintray-android-v1.gradle ├── bintray-java-v1.gradle ├── install-v1.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── ic_launcher.zip ├── ic_launcher └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ └── drawable-xxxhdpi │ └── ic_launcher.png ├── images └── demo.png ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── net │ │ └── dhleong │ │ └── vlcvideoview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── net │ │ │ └── dhleong │ │ │ └── vlcvideoview │ │ │ ├── VlcOptions.java │ │ │ └── VlcVideoView.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── net │ └── dhleong │ └── vlcvideoview │ └── ExampleUnitTest.java ├── libvlc ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── org │ │ └── videolan │ │ └── libvlc │ │ ├── AWindow.java │ │ ├── Dialog.java │ │ ├── IVLCVout.java │ │ ├── LibVLC.java │ │ ├── Media.java │ │ ├── MediaDiscoverer.java │ │ ├── MediaList.java │ │ ├── MediaPlayer.java │ │ ├── VLCEvent.java │ │ ├── VLCObject.java │ │ ├── media │ │ ├── MediaPlayer.java │ │ └── VideoView.java │ │ └── util │ │ ├── AndroidUtil.java │ │ ├── Dumper.java │ │ ├── Extensions.java │ │ ├── HWDecoderUtil.java │ │ ├── MediaBrowser.java │ │ └── VLCUtil.java │ ├── jniLibs │ ├── arm64-v8a │ │ ├── libanw.21.so │ │ ├── libjniloader.so │ │ └── libvlcjni.so │ ├── armeabi-v7a │ │ ├── libanw.10.so │ │ ├── libanw.13.so │ │ ├── libanw.14.so │ │ ├── libanw.18.so │ │ ├── libanw.21.so │ │ ├── libiomx.10.so │ │ ├── libiomx.13.so │ │ ├── libiomx.14.so │ │ ├── libjniloader.so │ │ └── libvlcjni.so │ ├── x86 │ │ ├── libanw.10.so │ │ ├── libanw.13.so │ │ ├── libanw.14.so │ │ ├── libanw.18.so │ │ ├── libanw.21.so │ │ ├── libiomx.10.so │ │ ├── libiomx.13.so │ │ ├── libiomx.14.so │ │ ├── libjniloader.so │ │ └── libvlcjni.so │ └── x86_64 │ │ ├── libanw.21.so │ │ ├── libjniloader.so │ │ └── libvlcjni.so │ └── res │ └── values │ └── strings.xml ├── onvifcamera ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── rvirin │ │ └── onvif │ │ └── onvifcamera │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── rvirin │ │ │ └── onvif │ │ │ └── onvifcamera │ │ │ ├── OnvifDevice.kt │ │ │ ├── OnvifDeviceInformation.kt │ │ │ ├── OnvifDigestInformation.kt │ │ │ ├── OnvifMediaProfiles.kt │ │ │ ├── OnvifMediaStreamURI.kt │ │ │ ├── OnvifServices.kt │ │ │ └── OnvifXMLBuilder.kt │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── rvirin │ └── onvif │ └── onvifcamera │ └── ExampleUnitTest.java ├── pedrovlc ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── pedro │ │ └── vlc │ │ ├── Constants.java │ │ ├── VlcListener.java │ │ ├── VlcOptions.java │ │ └── VlcVideoLibrary.java │ └── res │ └── values │ └── strings.xml ├── settings.gradle └── test /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # IntelliJ 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/dictionaries 41 | .idea/libraries 42 | 43 | # Keystore files 44 | *.jks 45 | 46 | # External native build folder generated in Android Studio 2.2 and later 47 | .externalNativeBuild 48 | 49 | # Google Services (e.g. APIs or Firebase) 50 | google-services.json 51 | 52 | # Freeline 53 | freeline.py 54 | freeline/ 55 | freeline_project_description.json 56 | 57 | # fastlane 58 | fastlane/report.xml 59 | fastlane/Preview.html 60 | fastlane/screenshots 61 | fastlane/test_output 62 | fastlane/readme.md 63 | 64 | .DS_Store 65 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yashrs/ONVIF-Camera/fd28cea8abc6061275943035c77bed550e6c81e8/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rémy Virin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ONVIF-Camera 2 | An Android app for viewing ONVIF camera's. Users can take screenshot of video while they are watching and also can view the camera in background by using Picture in Picture in Android 3 | 4 | This app was selected in Top 10 and an award of $800 was given to this application [Link to blog](https://www.onvif.org/blog/2018/07/onvif-challenge-announces-top-10/) 5 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion 27 9 | defaultConfig { 10 | applicationId 'com.rvirin.onvif.demo' 11 | minSdkVersion 23 12 | targetSdkVersion 27 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | allprojects { 26 | repositories { 27 | maven { url 'https://jitpack.io' } 28 | } 29 | } 30 | 31 | dependencies { 32 | implementation fileTree(include: ['*.jar'], dir: 'libs') 33 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 34 | implementation 'com.android.support:appcompat-v7:27.1.1' 35 | implementation 'com.android.support.constraint:constraint-layout:1.1.0' 36 | testImplementation 'junit:junit:4.12' 37 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 38 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 39 | 40 | implementation project(':libvlc') 41 | implementation project(':pedrovlc') 42 | implementation project(':onvifcamera') 43 | //implementation project(':library') 44 | implementation 'com.android.support:design:27.1.1' 45 | } 46 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/rvirin/onvif/demo/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.rvirin.onvif.demo 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.onvif.onvifcamera_android", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/rvirin/onvif/demo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.rvirin.onvif.demo 2 | 3 | import android.Manifest 4 | import android.content.Intent 5 | import android.content.pm.PackageManager 6 | import android.support.v7.app.AppCompatActivity 7 | import android.os.Bundle 8 | import android.support.v4.app.ActivityCompat 9 | import android.support.v4.content.ContextCompat 10 | import android.util.Log 11 | import android.view.View 12 | import android.widget.CheckBox 13 | import android.widget.EditText 14 | import android.widget.TextView 15 | import android.widget.Toast 16 | import com.rvirin.onvif.R 17 | import com.rvirin.onvif.onvifcamera.* 18 | 19 | import com.rvirin.onvif.onvifcamera.OnvifRequest.Type.GetStreamURI 20 | import com.rvirin.onvif.onvifcamera.OnvifRequest.Type.GetProfiles 21 | import com.rvirin.onvif.onvifcamera.OnvifRequest.Type.GetDeviceInformation 22 | import com.rvirin.onvif.onvifcamera.OnvifRequest.Type.GetServices 23 | import android.R.id.edit 24 | import android.content.Context 25 | import android.content.SharedPreferences 26 | 27 | 28 | const val RTSP_URL = "com.rvirin.onvif.onvifcamera.demo.RTSP_URL" 29 | 30 | /** 31 | * Main activity of this demo project. It allows the user to type his camera IP address, 32 | * login and password. 33 | */ 34 | class MainActivity : AppCompatActivity(), OnvifListener { 35 | 36 | private var toast: Toast? = null 37 | 38 | override fun onCreate(savedInstanceState: Bundle?) { 39 | super.onCreate(savedInstanceState) 40 | setContentView(R.layout.activity_main) 41 | setupPermissions() 42 | loadFromSharedPrefs() 43 | } 44 | fun loadFromSharedPrefs() 45 | { 46 | val sp :SharedPreferences = getSharedPreferences("general", Context.MODE_PRIVATE) 47 | val ip: String = sp.getString("ip", "") 48 | val username: String = sp.getString("username", "") 49 | val password: String = sp.getString("password", "") 50 | 51 | (findViewById(R.id.ipAddress)).setText(ip) 52 | (findViewById(R.id.login)).setText(username) 53 | (findViewById(R.id.password)).setText(password) 54 | 55 | } 56 | fun saveToSharedPrefs() 57 | { 58 | val sp :SharedPreferences = getSharedPreferences("general", Context.MODE_PRIVATE) 59 | 60 | val editor :SharedPreferences.Editor = sp.edit() 61 | 62 | val ipAddress = (findViewById(R.id.ipAddress)).text.toString() 63 | val login = (findViewById(R.id.login)).text.toString() 64 | val password = (findViewById(R.id.password)).text.toString() 65 | 66 | editor.putString("ip", ipAddress) 67 | editor.putString("username", login) 68 | editor.putString("password", password) 69 | 70 | editor.commit() 71 | 72 | } 73 | override fun requestPerformed(response: OnvifResponse) 74 | { 75 | 76 | Log.d("INFO", response.parsingUIMessage) 77 | 78 | toast?.cancel() 79 | 80 | if (!response.success) { 81 | Log.e("ERROR", "request failed: ${response.request.type} \n Response: ${response.error}") 82 | toast = Toast.makeText(this, "⛔️ Request failed: ${response.request.type}", Toast.LENGTH_SHORT) 83 | toast?.show() 84 | } 85 | // if GetServices have been completed, we request the device information 86 | else if (response.request.type == GetServices) { 87 | currentDevice.getDeviceInformation() 88 | } 89 | // if GetDeviceInformation have been completed, we request the profiles 90 | else if (response.request.type == GetDeviceInformation) 91 | { 92 | 93 | val textView = findViewById(R.id.explanationTextView) 94 | textView.text = response.parsingUIMessage 95 | toast = Toast.makeText(this, "Device information retrieved 👍", Toast.LENGTH_SHORT) 96 | toast?.show() 97 | 98 | val c : CheckBox = findViewById(R.id.remember_details) 99 | if(c.isChecked()) 100 | { 101 | saveToSharedPrefs() 102 | Toast.makeText(this, "Saved Information for next time!", Toast.LENGTH_SHORT).show() 103 | 104 | } 105 | currentDevice.getProfiles() 106 | 107 | } 108 | // if GetProfiles have been completed, we request the Stream URI 109 | else if (response.request.type == GetProfiles) { 110 | val profilesCount = currentDevice.mediaProfiles.count() 111 | toast = Toast.makeText(this, "$profilesCount profiles retrieved 😎", Toast.LENGTH_SHORT) 112 | toast?.show() 113 | 114 | currentDevice.getStreamURI() 115 | 116 | } 117 | // if GetStreamURI have been completed, we're ready to play the video 118 | else if (response.request.type == GetStreamURI) { 119 | 120 | val button = findViewById(R.id.button) 121 | button.text = getString(R.string.Play) 122 | 123 | toast = Toast.makeText(this, "Stream URI retrieved,\nready for the movie 🍿", Toast.LENGTH_SHORT) 124 | toast?.show() 125 | } 126 | } 127 | 128 | fun buttonClicked(view: View) 129 | { 130 | 131 | // If we were able to retrieve information from the camera, and if we have a rtsp uri, 132 | // We open StreamActivity and pass the rtsp URI 133 | if (currentDevice.isConnected) { 134 | currentDevice.rtspURI?.let { uri -> 135 | val intent = Intent(this, StreamActivity::class.java).apply { 136 | putExtra(RTSP_URL, uri) 137 | } 138 | startActivity(intent) 139 | } ?: run { 140 | Toast.makeText(this, "RTSP URI haven't been retrieved", Toast.LENGTH_SHORT).show() 141 | } 142 | } else { 143 | 144 | // get the information type by the user to create the Onvif device 145 | val ipAddress = (findViewById(R.id.ipAddress)).text.toString() 146 | val login = (findViewById(R.id.login)).text.toString() 147 | val password = (findViewById(R.id.password)).text.toString() 148 | 149 | if (ipAddress.isNotEmpty() && 150 | login.isNotEmpty() && 151 | password.isNotEmpty()) 152 | { 153 | 154 | // Create ONVIF device with user inputs and retrieve camera informations 155 | currentDevice = OnvifDevice(ipAddress, login, password) 156 | currentDevice.listener = this 157 | currentDevice.getServices() 158 | 159 | } else { 160 | toast?.cancel() 161 | toast = Toast.makeText(this, 162 | "Please enter an IP Address, Login and Password", 163 | Toast.LENGTH_SHORT) 164 | toast?.show() 165 | } 166 | } 167 | } 168 | 169 | private val TAG_P = "Permissions" 170 | private val WRITE_REQUEST_CODE = 101 171 | 172 | private fun setupPermissions() { 173 | val permission = ContextCompat.checkSelfPermission(this, 174 | Manifest.permission.WRITE_EXTERNAL_STORAGE) 175 | 176 | if (permission != PackageManager.PERMISSION_GRANTED) { 177 | Log.i(TAG_P, "Permission to Write External Storage not granted") 178 | makeRequest() 179 | } 180 | } 181 | private fun makeRequest() { 182 | ActivityCompat.requestPermissions(this, 183 | arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE), 184 | WRITE_REQUEST_CODE) 185 | } 186 | 187 | override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { 188 | when(requestCode) 189 | { 190 | WRITE_REQUEST_CODE-> 191 | { 192 | if(grantResults.isEmpty() || grantResults[0]!=PackageManager.PERMISSION_GRANTED) 193 | { 194 | Log.i(TAG_P, "Permission denied by user") 195 | Toast.makeText(applicationContext, "The Write Permission is required in order to record videos. Please grant it.", Toast.LENGTH_LONG).show() 196 | makeRequest() 197 | } 198 | else 199 | { 200 | Log.i(TAG_P, "Permission granted by user") 201 | } 202 | } 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /app/src/main/java/com/rvirin/onvif/demo/StreamActivity.kt: -------------------------------------------------------------------------------- 1 | package com.rvirin.onvif.demo 2 | 3 | import android.app.PictureInPictureParams 4 | import android.content.res.Configuration 5 | import android.graphics.Bitmap 6 | import android.graphics.BitmapFactory 7 | import android.media.MediaRecorder 8 | import android.os.Build 9 | import android.support.v7.app.AppCompatActivity 10 | import android.os.Bundle 11 | import android.os.Environment 12 | import android.widget.Button 13 | import android.widget.Toast 14 | import com.pedro.vlc.VlcListener 15 | import com.pedro.vlc.VlcVideoLibrary 16 | import com.rvirin.onvif.R 17 | import kotlinx.android.synthetic.main.activity_stream.* 18 | import com.rvirin.onvif.R.id.textureView 19 | import android.provider.MediaStore.Images.Media.getBitmap 20 | import android.util.Log 21 | import android.util.Rational 22 | import android.view.* 23 | import java.io.File 24 | import java.io.FileOutputStream 25 | import java.io.IOException 26 | import java.text.SimpleDateFormat 27 | import java.util.* 28 | 29 | 30 | /** 31 | * This activity helps us to show the live stream of an ONVIF camera thanks to VLC library. 32 | */ 33 | class StreamActivity : AppCompatActivity(), VlcListener, View.OnClickListener { 34 | 35 | 36 | private var vlcVideoLibrary: VlcVideoLibrary? = null 37 | public var textureView: TextureView? = null 38 | 39 | override fun onCreate(savedInstanceState: Bundle?) { 40 | super.onCreate(savedInstanceState) 41 | setContentView(R.layout.activity_stream) 42 | 43 | textureView = findViewById(R.id.textureView) 44 | 45 | val bStartStop = findViewById