├── app ├── .gitignore ├── app-release.apk ├── src │ └── main │ │ ├── logo-web.png │ │ ├── assets │ │ ├── www │ │ │ ├── images │ │ │ │ ├── b.gif │ │ │ │ ├── l.gif │ │ │ │ ├── r.gif │ │ │ │ ├── t.gif │ │ │ │ ├── bl.gif │ │ │ │ ├── br.gif │ │ │ │ ├── tl.gif │ │ │ │ ├── tr.gif │ │ │ │ ├── vlc.png │ │ │ │ ├── error.png │ │ │ │ ├── focus.png │ │ │ │ ├── info.png │ │ │ │ ├── logo.gif │ │ │ │ ├── menu.gif │ │ │ │ ├── torch.png │ │ │ │ ├── angelcam.png │ │ │ │ ├── favicon.png │ │ │ │ ├── mangocam.png │ │ │ │ ├── pattern.jpg │ │ │ │ ├── success.png │ │ │ │ ├── tinycam.png │ │ │ │ ├── torch_on.png │ │ │ │ ├── videolan.png │ │ │ │ ├── warning.png │ │ │ │ ├── zoom_in.png │ │ │ │ ├── zoom_out.png │ │ │ │ ├── GooglePlus.png │ │ │ │ ├── blue_corner.gif │ │ │ │ ├── cont_back.gif │ │ │ │ ├── fullscreen.png │ │ │ │ ├── menu_item.gif │ │ │ │ ├── torch_none.png │ │ │ │ ├── torch_off.png │ │ │ │ ├── wifi_h264.png │ │ │ │ ├── wifi_mjpeg.png │ │ │ │ ├── wifi_none.png │ │ │ │ ├── battery_none.png │ │ │ │ ├── active_menu_item.gif │ │ │ │ ├── battery_charging_000.png │ │ │ │ ├── battery_charging_020.png │ │ │ │ ├── battery_charging_040.png │ │ │ │ ├── battery_charging_060.png │ │ │ │ ├── battery_charging_080.png │ │ │ │ ├── battery_charging_100.png │ │ │ │ ├── battery_discharging_000.png │ │ │ │ ├── battery_discharging_020.png │ │ │ │ ├── battery_discharging_040.png │ │ │ │ ├── battery_discharging_060.png │ │ │ │ ├── battery_discharging_080.png │ │ │ │ └── battery_discharging_100.png │ │ │ └── api │ │ │ │ └── styles.css │ │ └── Angelcam │ │ │ └── ca.pem │ │ ├── res │ │ ├── raw │ │ │ ├── notification1.mp3 │ │ │ └── notification2.mp3 │ │ ├── drawable-hdpi │ │ │ ├── ic_dns.png │ │ │ ├── ic_mic.png │ │ │ ├── logo.png │ │ │ ├── ic_cloud.png │ │ │ ├── ic_error.png │ │ │ ├── ic_info.png │ │ │ ├── ic_star.png │ │ │ ├── ic_stop.png │ │ │ ├── ic_account.png │ │ │ ├── ic_mic_off.png │ │ │ ├── ic_network.png │ │ │ ├── ic_people.png │ │ │ ├── ic_settings.png │ │ │ ├── ic_stream.png │ │ │ ├── ic_videocam.png │ │ │ ├── ic_warning.png │ │ │ ├── ic_app_settings.png │ │ │ ├── ic_cloud_upload.png │ │ │ ├── ic_adapter_angelcam.png │ │ │ └── ic_adapter_mangocam.png │ │ ├── drawable-mdpi │ │ │ ├── ic_dns.png │ │ │ ├── ic_mic.png │ │ │ ├── logo.png │ │ │ ├── ic_cloud.png │ │ │ ├── ic_error.png │ │ │ ├── ic_info.png │ │ │ ├── ic_star.png │ │ │ ├── ic_stop.png │ │ │ ├── ic_account.png │ │ │ ├── ic_mic_off.png │ │ │ ├── ic_network.png │ │ │ ├── ic_people.png │ │ │ ├── ic_settings.png │ │ │ ├── ic_stream.png │ │ │ ├── ic_videocam.png │ │ │ ├── ic_warning.png │ │ │ ├── ic_app_settings.png │ │ │ ├── ic_cloud_upload.png │ │ │ ├── ic_adapter_angelcam.png │ │ │ └── ic_adapter_mangocam.png │ │ ├── drawable-xhdpi │ │ │ ├── logo.png │ │ │ ├── ic_dns.png │ │ │ ├── ic_info.png │ │ │ ├── ic_mic.png │ │ │ ├── ic_star.png │ │ │ ├── ic_stop.png │ │ │ ├── ic_account.png │ │ │ ├── ic_cloud.png │ │ │ ├── ic_error.png │ │ │ ├── ic_mic_off.png │ │ │ ├── ic_network.png │ │ │ ├── ic_people.png │ │ │ ├── ic_stream.png │ │ │ ├── ic_warning.png │ │ │ ├── ic_settings.png │ │ │ ├── ic_videocam.png │ │ │ ├── ic_app_settings.png │ │ │ ├── ic_cloud_upload.png │ │ │ ├── ic_adapter_angelcam.png │ │ │ └── ic_adapter_mangocam.png │ │ ├── drawable │ │ │ ├── screen_cast.png │ │ │ └── circle_shape.xml │ │ ├── drawable-xxhdpi │ │ │ ├── ic_dns.png │ │ │ ├── ic_mic.png │ │ │ ├── ic_cloud.png │ │ │ ├── ic_error.png │ │ │ ├── ic_info.png │ │ │ ├── ic_people.png │ │ │ ├── ic_star.png │ │ │ ├── ic_stop.png │ │ │ ├── ic_stream.png │ │ │ ├── ic_account.png │ │ │ ├── ic_mic_off.png │ │ │ ├── ic_network.png │ │ │ ├── ic_settings.png │ │ │ ├── ic_videocam.png │ │ │ ├── ic_warning.png │ │ │ ├── ic_app_settings.png │ │ │ ├── ic_cloud_upload.png │ │ │ ├── ic_adapter_angelcam.png │ │ │ └── ic_adapter_mangocam.png │ │ ├── drawable-xxxhdpi │ │ │ ├── ic_cloud.png │ │ │ ├── ic_dns.png │ │ │ ├── ic_error.png │ │ │ ├── ic_info.png │ │ │ ├── ic_mic.png │ │ │ ├── ic_star.png │ │ │ ├── ic_stop.png │ │ │ ├── ic_account.png │ │ │ ├── ic_mic_off.png │ │ │ ├── ic_network.png │ │ │ ├── ic_people.png │ │ │ ├── ic_stream.png │ │ │ ├── ic_warning.png │ │ │ ├── ic_settings.png │ │ │ ├── ic_videocam.png │ │ │ ├── ic_app_settings.png │ │ │ ├── ic_cloud_upload.png │ │ │ ├── ic_adapter_angelcam.png │ │ │ └── ic_adapter_mangocam.png │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ ├── xml │ │ │ └── backup_rules.xml │ │ ├── values-small │ │ │ └── dimens.xml │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── colors.xml │ │ │ ├── styles.xml │ │ │ └── array.xml │ │ ├── values-it │ │ │ └── array.xml │ │ ├── menu │ │ │ └── menu_main.xml │ │ ├── anim │ │ │ ├── in_left.xml │ │ │ ├── in_right.xml │ │ │ ├── out_left.xml │ │ │ └── out_right.xml │ │ └── layout │ │ │ ├── fragment_logo.xml │ │ │ ├── fragment_slideshow.xml │ │ │ ├── fragment_status.xml │ │ │ └── activity_settings.xml │ │ ├── aidl │ │ └── com │ │ │ └── spynet │ │ │ └── camera │ │ │ ├── media │ │ │ └── CameraInfo.aidl │ │ │ └── services │ │ │ ├── IStreamServiceCallBack.aidl │ │ │ └── IStreamService.aidl │ │ ├── java │ │ └── com │ │ │ └── spynet │ │ │ └── camera │ │ │ ├── network │ │ │ ├── Angelcam │ │ │ │ └── API │ │ │ │ │ ├── AngelcamAPI.java │ │ │ │ │ ├── PingMessage.java │ │ │ │ │ ├── StatusMessage.java │ │ │ │ │ ├── RedirectMessage.java │ │ │ │ │ ├── HungUpMessage.java │ │ │ │ │ └── AckMessage.java │ │ │ ├── DDNS │ │ │ │ ├── DynuClient.java │ │ │ │ ├── NoIpClient.java │ │ │ │ ├── DNSdynamicClient.java │ │ │ │ ├── FreeDNSDClient.java │ │ │ │ └── DuckDNSClient.java │ │ │ ├── Mangocam │ │ │ │ └── API │ │ │ │ │ ├── MangocamCommand.java │ │ │ │ │ ├── NoopCommand.java │ │ │ │ │ ├── MangocamAPI.java │ │ │ │ │ ├── StatsCommand.java │ │ │ │ │ ├── ReconnectCommand.java │ │ │ │ │ ├── InfoCommand.java │ │ │ │ │ ├── StopMJPEGCommand.java │ │ │ │ │ ├── DisconnectCommand.java │ │ │ │ │ └── ResetCommand.java │ │ │ ├── TCPAudioPacketizer.java │ │ │ ├── TCPVideoPacketizer.java │ │ │ ├── UDPAudioPacketizer.java │ │ │ ├── UDPVideoPacketizer.java │ │ │ └── TCPListener.java │ │ │ ├── ui │ │ │ ├── EditTextLockedPreference.java │ │ │ ├── EditTextPreference.java │ │ │ ├── ServiceFragment.java │ │ │ └── ScreenCaptureRequestActivity.java │ │ │ ├── SpyNetApplication.java │ │ │ ├── media │ │ │ ├── ByteArrayInputBitStream.java │ │ │ ├── DummySurfaceHolder.java │ │ │ ├── CameraInfo.java │ │ │ └── AudioData.java │ │ │ ├── common │ │ │ ├── TimeStamp.java │ │ │ └── Image.java │ │ │ └── gl │ │ │ └── Shader.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .idea ├── copyright │ ├── profiles_settings.xml │ └── spyNet_Camera_GPL.xml ├── markdown-navigator │ └── profiles_settings.xml ├── encodings.xml ├── vcs.xml ├── inspectionProfiles │ ├── profiles_settings.xml │ └── Project_Default.xml ├── modules.xml ├── runConfigurations.xml ├── gradle.xml ├── compiler.xml ├── misc.xml └── markdown-navigator.xml ├── settings.gradle ├── spyNet Camera.iml ├── gradle.properties ├── README.md └── gradlew.bat /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/app-release.apk -------------------------------------------------------------------------------- /app/src/main/logo-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/logo-web.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/assets/www/images/b.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/b.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/l.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/l.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/r.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/r.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/t.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/t.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /app/src/main/assets/www/images/bl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/bl.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/br.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/br.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/tl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/tl.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/tr.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/tr.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/vlc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/vlc.png -------------------------------------------------------------------------------- /app/src/main/res/raw/notification1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/raw/notification1.mp3 -------------------------------------------------------------------------------- /app/src/main/res/raw/notification2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/raw/notification2.mp3 -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/assets/www/images/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/error.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/focus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/focus.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/info.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/logo.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/menu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/menu.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/torch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/torch.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_dns.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_mic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_dns.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_mic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/screen_cast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable/screen_cast.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/angelcam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/angelcam.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/favicon.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/mangocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/mangocam.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/pattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/pattern.jpg -------------------------------------------------------------------------------- /app/src/main/assets/www/images/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/success.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/tinycam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/tinycam.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/torch_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/torch_on.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/videolan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/videolan.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/warning.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/zoom_in.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/zoom_out.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_cloud.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_info.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_star.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_cloud.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_info.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_star.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_dns.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_info.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_mic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_star.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_dns.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_mic.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/GooglePlus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/GooglePlus.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/blue_corner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/blue_corner.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/cont_back.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/cont_back.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/fullscreen.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/menu_item.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/menu_item.gif -------------------------------------------------------------------------------- /app/src/main/assets/www/images/torch_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/torch_none.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/torch_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/torch_off.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/wifi_h264.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/wifi_h264.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/wifi_mjpeg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/wifi_mjpeg.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/wifi_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/wifi_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_account.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_mic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_mic_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_network.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_stream.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_videocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_videocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_warning.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_account.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_mic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_mic_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_network.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_stream.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_videocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_videocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_warning.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_account.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_cloud.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_mic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_mic_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_network.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_stream.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_warning.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_cloud.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_info.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_star.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_stream.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_cloud.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_dns.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_info.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_mic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_star.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_stop.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_videocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_videocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_account.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_mic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_mic_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_network.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_videocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_videocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_warning.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_account.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_mic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_mic_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_network.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_stream.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_warning.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/assets/www/images/active_menu_item.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/active_menu_item.gif -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_app_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_app_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_cloud_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_cloud_upload.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_app_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_app_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_cloud_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_cloud_upload.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_app_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_app_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_cloud_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_cloud_upload.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_videocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_videocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_app_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_app_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_cloud_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_cloud_upload.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_app_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_app_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_cloud_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_cloud_upload.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_charging_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_charging_000.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_charging_020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_charging_020.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_charging_040.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_charging_040.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_charging_060.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_charging_060.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_charging_080.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_charging_080.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_charging_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_charging_100.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_adapter_angelcam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_adapter_angelcam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_adapter_mangocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-hdpi/ic_adapter_mangocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_adapter_angelcam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_adapter_angelcam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_adapter_mangocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-mdpi/ic_adapter_mangocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_adapter_angelcam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_adapter_angelcam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_adapter_mangocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xhdpi/ic_adapter_mangocam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_adapter_angelcam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_adapter_angelcam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_adapter_mangocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxhdpi/ic_adapter_mangocam.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_discharging_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_discharging_000.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_discharging_020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_discharging_020.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_discharging_040.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_discharging_040.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_discharging_060.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_discharging_060.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_discharging_080.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_discharging_080.png -------------------------------------------------------------------------------- /app/src/main/assets/www/images/battery_discharging_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/assets/www/images/battery_discharging_100.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_adapter_angelcam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_adapter_angelcam.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_adapter_mangocam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ziacto/spynet-camera/HEAD/app/src/main/res/drawable-xxxhdpi/ic_adapter_mangocam.png -------------------------------------------------------------------------------- /app/src/main/aidl/com/spynet/camera/media/CameraInfo.aidl: -------------------------------------------------------------------------------- 1 | package com.spynet.camera.media; 2 | 3 | /** 4 | * AIDL definition for the CameraInfo class. 5 | */ 6 | parcelable CameraInfo; 7 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 06 22:21:50 CET 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | include ':app' 23 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | -------------------------------------------------------------------------------- /spyNet Camera.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/copyright/spyNet_Camera_GPL.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/assets/www/api/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | padding: 0px; 4 | background-color: #E2EEFE; 5 | } 6 | h1 { 7 | font-size: 22px; 8 | font-family: "Trebuchet MS", Verdana; 9 | text-transform: uppercase; 10 | font-weight: normal; 11 | color: #1D4D81; 12 | } 13 | h2 { 14 | font-size: 20px; 15 | font-family: "Trebuchet MS", Verdana; 16 | font-weight: normal; 17 | color: #1D4D81; 18 | } 19 | h3 { 20 | font-size: 18px; 21 | font-family: "Trebuchet MS", Verdana; 22 | font-weight: normal; 23 | color: #1D4D81; 24 | } 25 | p { 26 | text-align: left; 27 | font-size: 14px; 28 | font-family: "Trebuchet MS", Verdana; 29 | margin: 4px; 30 | } 31 | .center { 32 | margin: auto; 33 | width: 75%; 34 | padding: 10px; 35 | } 36 | .api_entry { 37 | line-height: 1.4; 38 | width: auto; 39 | background-color: #fff; 40 | padding: 8px 12px; 41 | border-left: 4px solid #4CAF50; 42 | word-wrap: break-word; 43 | -webkit-box-shadow: 2px 2px 2px #ACA5A5; 44 | box-shadow: 2px 2px 2px #ACA5A5; 45 | } 46 | code { 47 | background-color: #5E4B4B; 48 | color: #F7EFEF; 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-small/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 12sp 25 | 6dp 26 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | 14sp 26 | 8dp 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/values-it/array.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | "Solo WiFi" 26 | "Solo rete mobile" 27 | "Sia WiFi che rete mobile" 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 25 | 26 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 25 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | #546E7A 25 | #CC263238 26 | #CDDC39 27 | #66000000 28 | #f0f0f0 29 | #202020 30 | -------------------------------------------------------------------------------- /app/src/main/res/anim/in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 26 | 30 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/anim/in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 26 | 30 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/anim/out_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 26 | 30 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/anim/out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 26 | 30 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Angelcam/API/AngelcamAPI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Angelcam.API; 23 | 24 | /** 25 | * Defines some Angelcam Ready constants. 26 | */ 27 | public final class AngelcamAPI { 28 | 29 | /** 30 | * Hidden constructor, the class cannot be instantiated. 31 | */ 32 | private AngelcamAPI() { 33 | } 34 | 35 | // Client protocol version 36 | public static final int VERSION = 0; 37 | 38 | // Connection timeout in seconds 39 | public static final int CONNECT_TIMEOUT = 10; 40 | 41 | // Default keepalive interval in seconds 42 | public static final int KEEPALIVE_INTERVAL = 60; 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_logo.xml: -------------------------------------------------------------------------------- 1 | 21 | 22 | 27 | 28 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/ui/EditTextLockedPreference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.ui; 23 | 24 | import android.content.Context; 25 | import android.util.AttributeSet; 26 | 27 | /** 28 | * Extends {@link EditTextPreference} to lock the initial value. 29 | */ 30 | public class EditTextLockedPreference extends EditTextPreference { 31 | 32 | public EditTextLockedPreference(Context context) { 33 | super(context); 34 | } 35 | 36 | public EditTextLockedPreference(Context context, AttributeSet attrs) { 37 | super(context, attrs); 38 | } 39 | 40 | public EditTextLockedPreference(Context context, AttributeSet attrs, int defStyleAttr) { 41 | super(context, attrs, defStyleAttr); 42 | } 43 | 44 | @Override 45 | protected void onClick() { 46 | callChangeListener(getText()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/DDNS/DynuClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.DDNS; 23 | 24 | import android.content.Context; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | /** 29 | * Implements the Dynu client (https://www.dynu.com). 30 | */ 31 | public class DynuClient extends DDNSClient { 32 | /** 33 | * Creates a new DynuClient object. 34 | * 35 | * @param context the context where the NoIpClient is used 36 | * @param hostname the public hostname handled by the DDNS service 37 | * @param username the DDNS service username 38 | * @param password the DDNS service password 39 | */ 40 | public DynuClient(@NotNull Context context, String hostname, String username, String password) { 41 | super(context, hostname, username, password); 42 | mURL = "https://api.dynu.com/nic/update"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/MangocamCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import org.json.JSONException; 25 | 26 | import java.io.IOException; 27 | 28 | /** 29 | * Defines the interface implemented by the Mangocam Connect protocol commands. 30 | */ 31 | public interface MangocamCommand { 32 | /** 33 | * Formats the command / reply string to send to the server. 34 | * 35 | * @return the string representing the command / reply 36 | * @throws JSONException on JSON error 37 | */ 38 | String get() throws JSONException; 39 | 40 | /** 41 | * Parses the command /reply received from the server. 42 | * 43 | * @param command the string representing the command / reply 44 | * @throws IOException on JSON error 45 | */ 46 | void parse(String command) throws IOException; 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/DDNS/NoIpClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.DDNS; 23 | 24 | import android.content.Context; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | /** 29 | * Implements the NoIp client (https://my.noip.com). 30 | */ 31 | public class NoIpClient extends DDNSClient { 32 | /** 33 | * Creates a new NoIpClient object. 34 | * 35 | * @param context the context where the NoIpClient is used 36 | * @param hostname the public hostname handled by the DDNS service 37 | * @param username the DDNS service username 38 | * @param password the DDNS service password 39 | */ 40 | public NoIpClient(@NotNull Context context, String hostname, String username, String password) { 41 | super(context, hostname, username, password); 42 | mURL = "https://dynupdate.no-ip.com/nic/update"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of spyNet Camera, the Android IP camera 3 | # 4 | # Copyright (C) 2016-2017 Paolo Dematteis 5 | # 6 | # spyNet Camera is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # spyNet Camera is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | # 19 | # Paolo Dematteis - spynet314@gmail.com 20 | # 21 | 22 | # Project-wide Gradle settings. 23 | 24 | # IDE (e.g. Android Studio) users: 25 | # Gradle settings configured through the IDE *will override* 26 | # any settings specified in this file. 27 | 28 | # For more details on how to configure your build environment visit 29 | # http://www.gradle.org/docs/current/userguide/build_environment.html 30 | 31 | # Specifies the JVM arguments used for the daemon process. 32 | # The setting is particularly useful for tweaking memory settings. 33 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 34 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 35 | 36 | # When configured, Gradle will run in incubating parallel mode. 37 | # This option should only be used with decoupled projects. More details, visit 38 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 39 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/DDNS/DNSdynamicClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.DDNS; 23 | 24 | import android.content.Context; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | /** 29 | * Implements the DNSdynamic client (http://www.dnsdynamic.org). 30 | */ 31 | public class DNSdynamicClient extends DDNSClient { 32 | /** 33 | * Creates a new DNSdynamicClient object. 34 | * 35 | * @param context the context where the NoIpClient is used 36 | * @param hostname the public hostname handled by the DDNS service 37 | * @param username the DDNS service username 38 | * @param password the DDNS service password 39 | */ 40 | public DNSdynamicClient(@NotNull Context context, String hostname, String username, String password) { 41 | super(context, hostname, username, password); 42 | mURL = "https://www.dnsdynamic.org/api"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/DDNS/FreeDNSDClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.DDNS; 23 | 24 | import android.content.Context; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | /** 29 | * Implements the Free DNS client (http://freedns.afraid.org/dynamic). 30 | */ 31 | public class FreeDNSDClient extends DDNSClient { 32 | /** 33 | * Creates a new DNSdynamicClient object. 34 | * 35 | * @param context the context where the NoIpClient is used 36 | * @param hostname the public hostname handled by the DDNS service 37 | * @param username the DDNS service username 38 | * @param password the DDNS service password 39 | */ 40 | public FreeDNSDClient(@NotNull Context context, String hostname, String username, String password) { 41 | super(context, hostname, username, password); 42 | mURL = "https://sync.afraid.org/nic/update"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/SpyNetApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera; 23 | 24 | import android.app.Application; 25 | 26 | import com.github.stkent.amplify.feedback.DefaultEmailFeedbackCollector; 27 | import com.github.stkent.amplify.feedback.GooglePlayStoreFeedbackCollector; 28 | import com.github.stkent.amplify.tracking.Amplify; 29 | 30 | /** 31 | * The spyNet Camera application. 32 | */ 33 | public class SpyNetApplication extends Application { 34 | 35 | @Override 36 | public void onCreate() { 37 | super.onCreate(); 38 | 39 | // Initialize the Amplify library 40 | Amplify.initSharedInstance(this) 41 | //.setAlwaysShow(BuildConfig.DEBUG) 42 | .setPositiveFeedbackCollectors(new GooglePlayStoreFeedbackCollector()) 43 | .setCriticalFeedbackCollectors(new DefaultEmailFeedbackCollector(getString(R.string.app_support_email))) 44 | .applyAllDefaultRules(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | apply plugin: 'com.android.application' 23 | 24 | android { 25 | compileSdkVersion 25 26 | buildToolsVersion '25.0.2' 27 | defaultConfig { 28 | applicationId "com.spynet.camtest" 29 | minSdkVersion 17 30 | targetSdkVersion 23 31 | versionCode 37 32 | versionName '2.4.6' 33 | } 34 | buildTypes { 35 | release { 36 | minifyEnabled false 37 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 38 | } 39 | } 40 | productFlavors { 41 | } 42 | } 43 | 44 | dependencies { 45 | compile fileTree(include: ['*.jar'], dir: 'libs') 46 | compile 'com.android.support:appcompat-v7:25.2.0' 47 | compile 'com.android.support:support-v4:25.2.0' 48 | compile 'org.jetbrains:annotations:13.0' 49 | compile 'com.takisoft.fix:preference-v7:25.2.0.0' 50 | compile 'com.github.stkent:amplify:2.0.0' 51 | compile 'org.bitlet:weupnp:0.1.4' 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/NoopCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import android.content.Context; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | import org.json.JSONException; 28 | 29 | import java.io.IOException; 30 | 31 | /** 32 | * Defines the Mangocam API NOOP command.
33 | *
34 | * Command example:
35 | *
36 | * NOOP [] 37 | */ 38 | public class NoopCommand implements MangocamCommand { 39 | 40 | private final Context mContext; 41 | 42 | /** 43 | * Creates a new NoopCommand object. 44 | * 45 | * @param context the context where the object is used 46 | */ 47 | public NoopCommand(@NotNull Context context) { 48 | mContext = context; 49 | } 50 | 51 | 52 | @Override 53 | public String get() throws JSONException { 54 | return "OK {\"cmd\":\"NOOP\"}\r\n"; 55 | } 56 | 57 | @Override 58 | public void parse(String command) throws IOException { 59 | // Nothing to do 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/assets/Angelcam/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFFDCCAvwCCQD+OG2n4YvuhzANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJD 3 | WjETMBEGA1UECAwKU29tZS1TdGF0ZTEPMA0GA1UEBwwGUHJhZ3VlMRcwFQYDVQQK 4 | DA5hbmdlbGNhbSwgaW5jLjAeFw0xNTAzMDUxMDIxMTBaFw0yNTAzMDIxMDIxMTBa 5 | MEwxCzAJBgNVBAYTAkNaMRMwEQYDVQQIDApTb21lLVN0YXRlMQ8wDQYDVQQHDAZQ 6 | cmFndWUxFzAVBgNVBAoMDmFuZ2VsY2FtLCBpbmMuMIICIjANBgkqhkiG9w0BAQEF 7 | AAOCAg8AMIICCgKCAgEA7nhHZxTAevpmPMVJYtmtec+mjLom4IoXgLnNj2vX59th 8 | RBPUEHBTMEozU4A3u0lZXp5nGLi/S4yVQ+I2JXCLPivh76sqUaW3aaDBVoN9B0G6 9 | lZWCCR3T9bVZSimnFn/ybnqCqpCCFK3uE5a0hBSbqwm+s0XekRkfoapOoxpwcKAZ 10 | yN8dVOXX4gcr7ZJOMJwMDBjCooUBG43zVCwGPMcbDg6tWSLTVY0cPUmlffDG+OvL 11 | GXdwsI1wT0JsHEYe3XCxl/mn8FxFInL24aiHA/XsKOuAj6P9b9Iz6kcaJYPBc0xy 12 | ecsGwFO3Cv+KbdyIFsnw+xm3J7IBHlOTeJnv6rdD3R9MOZy8bFZcFDY13B4Ikzf9 13 | 7odcWVMnM5w4uWexkOPbjfMqOqhfmFHNvL4iuoc6kYbWjNOcqj4e0O0SmQcX0oDM 14 | dZkhOAD087lNif+TNHI33KA0eCUPO65rknWiI0jT+DNuHYbKcdrIdIs+ndnPA9KB 15 | U3FIa2COwmh1Zhy/gduluthf5t8ndja6jvOEeP4HujSQumt6iCmQsKZ16ftX5nob 16 | bbHEY7BKEtMbBASTJnZ3rvBzqOmuyg+T1x2tRmTVFkyvdyaGaV++DbkHvGszw0rG 17 | BhAR0M3/HI0Ew+yg4SROGtKihQ3DXwXndADkyPespJkaMmcUERukt2KuJXRpDCkC 18 | AwEAATANBgkqhkiG9w0BAQUFAAOCAgEACupy0wOMJT2vzQgh30Cd36sH25PimImX 19 | V54nU2HbVXSXQ4w88cKkS88NeDuqvcf+n1uKxC2fnUMor0JAy0irXyddUT5SZkn3 20 | mTheasPzDG96SRVx25yIqmzHlfrDE0prangh3oBD3vrPyIWPAIVWVaZ56b3p8MTY 21 | ZdcRVQkp1fVyfLU89EBpVAQDV5roic4UD1IBHjvYRpycL31oi8FXeCTMgwhPE3GA 22 | M/EPD3NBX5wDtFWkJKrhbU+IFeDYldKzeBd1TrbfmifkoFkddSOxf89EQpnfPgxs 23 | 9XRuwZiPLuakuGvnw7FZYyzv5FoettDePuxlNsKuThe/eYTo+dL+1+OvpFm4epeI 24 | 7HPazSmSaLDYqnOakiSRyUVQEC7cSODBuwVG9hb/5NCwO1bsp/sAe2TZechV2E1p 25 | v+2XAPCWLtsNFK48OEvQ7sP/7YyOUuHP0hEgbWAe5R795MT5b1GJCikN/JNe8omk 26 | 3evPhqJg3p3439Lnr6Fcfgbj2ZSSasWcxd3XleZGweoUB6VNFBbjSjf5W573C3/o 27 | SH19jbTHRM+Q9ELqjvR/JNJp3BYUr8g+6HZoKKjSvRye2orvlyH0rg0Q0puXdrv1 28 | keEsNQUlw5QbZhNEWn7PHiRNcQkwXbRCJD8NvBKL5tdQ0fOWTk5RBnYlAbMDUd4l 29 | u8c1VUFo3So= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spyNet Cloud IP Camera 2 | 3 | ### Allows to use your mobile device as an IP camera than can stream to the cloud 4 | 5 | With *spyNet Camera* it is possible to use an Android device as a wireless IP camera. 6 | This way, it is possible to renew old smartphones and tablets, realizing your own video surveillance system easily, even on the WEB. 7 | The integrated cloud support allows to access the ***angelcam*** and ***Mangocam*** services quickly, 8 | with no need to configure the router. 9 | It works with the WiFi or by using the mobile data connectivity. 10 | 11 | ### Main features: 12 | 13 | * H264 and MJPEG video formats 14 | * AAC audio formats 15 | * HTTP, RTSP, RTSP over TCP and RTSP over HTTP protocols 16 | * UPnP support 17 | * integrated support for the ***angelcam*** and ***Mangocam*** cloud services 18 | * compatibility with standard VCR and online services 19 | * streaming available even with the screen off and the device sleeping 20 | * background streaming when the app is closed 21 | * discreet monotoring by simulating a digital photo-frame, while streaming the front camera 22 | * integrated server to allow accessibility on the local network 23 | * can stream any available camera 24 | * *Screen Capture* (aka screencast) to stream the screen content 25 | * selectable video resolution and quality 26 | * selectable audio quality and gain 27 | * interactive zoom and focus control 28 | * JSON API 29 | * no ads, no restrictions, absolutely for free 30 | 31 | ### Get involved 32 | 33 | You are encouraged to verify the code, to propose changes or bug fixes 34 | and to translate the messages in your own language. 35 | 36 | ### Disclaimer 37 | 38 | According to the GPL license, you are the welcome in browsing, downloading and editing the spyNet Camera source code, maybe to create your own version. 39 | Anyway, the only official version will be the one that can be downloaded from the Google Play Store. 40 | The author is not responsible of any other version other than the official one. 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/MangocamAPI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | /** 25 | * Defines some Mangocam Connect constants. 26 | */ 27 | public final class MangocamAPI { 28 | 29 | /** 30 | * Hidden constructor, the class cannot be instantiated. 31 | */ 32 | private MangocamAPI() { 33 | } 34 | 35 | // Client protocol version 36 | public static final double VERSION = 1.0; 37 | 38 | // Base URL to access API 39 | public static final String BASE_URL = "/api/v2/upload/"; 40 | 41 | // Connection timeout in seconds 42 | public static final int CONNECT_TIMEOUT = 10; 43 | 44 | // Default keepalive interval in seconds 45 | public static final int KEEPALIVE_INTERVAL = 30; 46 | 47 | // Maximum allowed bandwidth in kbps 48 | public static final int MAX_BANDWIDTH = 1000; 49 | 50 | // Maximum allowed MJPEG fps 51 | public static final int MJPEG_MAX_FPS = 5; 52 | 53 | // Default delay, in seconds, after which to stop sending and start again autonomously 54 | public static final int MJPEG_SPLIT_SECS = 5; 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/ui/EditTextPreference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.ui; 23 | 24 | import android.content.Context; 25 | import android.util.AttributeSet; 26 | 27 | /** 28 | * Extends {@link com.takisoft.fix.support.v7.preference.EditTextPreference} to automatically 29 | * update the summary. 30 | */ 31 | public class EditTextPreference extends com.takisoft.fix.support.v7.preference.EditTextPreference { 32 | 33 | private CharSequence mSummary; 34 | 35 | public EditTextPreference(Context context) { 36 | super(context); 37 | mSummary = super.getSummary(); 38 | } 39 | 40 | public EditTextPreference(Context context, AttributeSet attrs) { 41 | super(context, attrs); 42 | mSummary = super.getSummary(); 43 | } 44 | 45 | public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) { 46 | super(context, attrs, defStyleAttr); 47 | mSummary = super.getSummary(); 48 | } 49 | 50 | @Override 51 | public void setText(String text) { 52 | super.setText(text); 53 | if (mSummary != null) 54 | setSummary(String.format(mSummary.toString(), text == null ? "" : text)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Angelcam/API/PingMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Angelcam.API; 23 | 24 | import java.io.InvalidObjectException; 25 | 26 | /** 27 | * Defines the Arrow protocol PING message.
28 | * Ping request used for connection health checks.
29 | * It is periodically sent by both server and client.
30 | * The message contains no data. 31 | */ 32 | public class PingMessage extends ControlMessage { 33 | 34 | /** 35 | * Creates a new PingMessage object. 36 | * 37 | * @param messageID message ID, used for request/response pairing 38 | */ 39 | public PingMessage(int messageID, int errorCode) { 40 | super(messageID, TYPE_PING); 41 | } 42 | 43 | /** 44 | * Wraps a PingMessage object around a ControlMessage object. 45 | * 46 | * @param message the original ControlMessage object 47 | * @throws InvalidObjectException if the {@code message} doesn't match 48 | */ 49 | public PingMessage(ControlMessage message) throws InvalidObjectException { 50 | super(message.mMessageID, message.mType); 51 | if (mType != TYPE_PING) 52 | throw new InvalidObjectException("The message is not a PING message"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_slideshow.xml: -------------------------------------------------------------------------------- 1 | 21 | 22 | 27 | 28 | 32 | 33 | 39 | 40 | 41 | 42 | 46 | 47 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/StatsCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import android.content.Context; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | import org.json.JSONException; 28 | import org.json.JSONObject; 29 | 30 | import java.io.IOException; 31 | 32 | /** 33 | * Defines the Mangocam API STATS command.
34 | *
35 | * Command example:
36 | *
37 | * STATS [] 38 | */ 39 | public class StatsCommand implements MangocamCommand { 40 | 41 | private final Context mContext; 42 | private final long mUptime; 43 | private final boolean mUploading; 44 | 45 | /** 46 | * Creates a new InfoCommand object. 47 | * 48 | * @param context the context where the object is used 49 | * @param uptime how long the client is on in seconds 50 | * @param uploading whether the client is uploading images to the server 51 | */ 52 | public StatsCommand(@NotNull Context context, long uptime, boolean uploading) { 53 | mContext = context; 54 | mUptime = uptime; 55 | mUploading = uploading; 56 | } 57 | 58 | @Override 59 | public String get() throws JSONException { 60 | JSONObject jObject = new JSONObject(); 61 | jObject.put("cmd", "STATS"); 62 | jObject.put("uptime", mUptime); 63 | jObject.put("uploading", mUploading ? 1 : 0); 64 | return "OK " + jObject.toString() + "\r\n"; 65 | } 66 | 67 | @Override 68 | public void parse(String command) throws IOException { 69 | // Nothing to do 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | 33 | 34 | 41 | 42 | 45 | 46 | 54 | 55 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 26 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Angelcam/API/StatusMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Angelcam.API; 23 | 24 | import java.io.ByteArrayOutputStream; 25 | import java.io.IOException; 26 | 27 | /** 28 | * Defines the Arrow protocol STATUS message.
29 | * Response for the GET_STATUS request. It is sent by client. 30 | */ 31 | public class StatusMessage extends ControlMessage { 32 | 33 | private final int mFlags; // Client status flags 34 | private final int mActiveSessions; // Active sessions 35 | 36 | /** 37 | * Creates a new StatusMessage object. 38 | * 39 | * @param messageID message ID, used for request/response pairing 40 | * @param flags client status flags 41 | * @param sessions number of active sessions 42 | */ 43 | public StatusMessage(int messageID, int flags, int sessions) { 44 | super(messageID, TYPE_STATUS); 45 | mFlags = flags; 46 | mActiveSessions = sessions; 47 | } 48 | 49 | @Override 50 | public byte[] toByteArray() throws IOException { 51 | 52 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 53 | 54 | // request_id - unsigned integer 55 | buffer.write(mMessageID >> 8); 56 | buffer.write(mMessageID); 57 | // status_flags 58 | buffer.write(mFlags >> 24); 59 | buffer.write(mFlags >> 16); 60 | buffer.write(mFlags >> 8); 61 | buffer.write(mFlags); 62 | // active_sessions - unsigned integer 63 | buffer.write(mActiveSessions >> 24); 64 | buffer.write(mActiveSessions >> 16); 65 | buffer.write(mActiveSessions >> 8); 66 | buffer.write(mActiveSessions); 67 | 68 | mData = buffer.toByteArray(); 69 | return super.toByteArray(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/media/ByteArrayInputBitStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.media; 23 | 24 | import java.io.ByteArrayInputStream; 25 | 26 | /** 27 | * A specialized {@link ByteArrayInputStream} for reading the contents of a byte array 28 | * as a bitstream. 29 | */ 30 | public class ByteArrayInputBitStream extends ByteArrayInputStream { 31 | 32 | private int mAvail = 0; // Number of available bits in mData 33 | private int mData; // Next bits to consume (from a previous call) 34 | 35 | /** 36 | * Constructs a new ByteArrayInputBitStream on the byte array buf. 37 | * 38 | * @param buf the byte array to stream over. 39 | */ 40 | public ByteArrayInputBitStream(byte[] buf) { 41 | super(buf); 42 | } 43 | 44 | /** 45 | * Reads some bits from the stream, starting from the MSB. 46 | * 47 | * @param bits number of bits to get, in the range 1-32 48 | * @return the bits read or -1 if the end of this stream has been reached. 49 | */ 50 | public synchronized int read(int bits) { 51 | 52 | long res = 0; 53 | int left = bits; 54 | int pos = 32; 55 | 56 | if (bits < 1 || bits > 32) 57 | throw new IllegalArgumentException("bits not in range 1 to 32"); 58 | 59 | while (true) { 60 | if (mAvail > 0) { 61 | pos -= mAvail; 62 | res |= (mData << pos) & 0xFFFFFFFFL; 63 | if (left > mAvail) { 64 | left -= mAvail; 65 | } else { 66 | mAvail -= left; 67 | return (int) (res >> (32 - bits)); 68 | } 69 | } 70 | if ((mData = read()) == -1) 71 | return -1; 72 | mAvail = 8; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/ReconnectCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import android.content.Context; 25 | import android.util.JsonReader; 26 | 27 | import org.jetbrains.annotations.NotNull; 28 | import org.json.JSONException; 29 | 30 | import java.io.IOException; 31 | import java.io.StringReader; 32 | 33 | /** 34 | * Defines the Mangocam API RECONNECT command.
35 | * Forces connection to a new host. 36 | */ 37 | public class ReconnectCommand implements MangocamCommand { 38 | 39 | private final Context mContext; 40 | private String mHost = null; 41 | 42 | /** 43 | * Creates a new ReconnectCommand object. 44 | * 45 | * @param context the context where the object is used 46 | */ 47 | public ReconnectCommand(@NotNull Context context) { 48 | mContext = context; 49 | } 50 | 51 | @Override 52 | public String get() throws JSONException { 53 | return "OK {\"cmd\":\"RECONNECT\"}\r\n"; 54 | } 55 | 56 | @Override 57 | public void parse(String command) throws IOException { 58 | if (!command.startsWith("RECONNECT ")) 59 | throw new IllegalArgumentException("wrong command"); 60 | command = command.substring(10); 61 | JsonReader jr = new JsonReader(new StringReader(command)); 62 | jr.beginObject(); 63 | while (jr.hasNext()) { 64 | switch (jr.nextName()) { 65 | case "host": 66 | mHost = jr.nextString(); 67 | break; 68 | default: 69 | jr.skipValue(); 70 | } 71 | } 72 | jr.endObject(); 73 | } 74 | 75 | /** 76 | * @return the host to send MJPEG to 77 | */ 78 | public String getHost() { 79 | return mHost; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/media/DummySurfaceHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.media; 23 | 24 | import android.graphics.Canvas; 25 | import android.graphics.Rect; 26 | import android.view.Surface; 27 | import android.view.SurfaceHolder; 28 | 29 | /** 30 | * Implements a dummy SurfaceHolder that holds an already exiting Surface. 31 | */ 32 | public class DummySurfaceHolder implements SurfaceHolder { 33 | 34 | private final Surface mSurface; 35 | 36 | /** 37 | * Creates a new DummySurfaceHolder object. 38 | * 39 | * @param surface the Surface to hold 40 | */ 41 | public DummySurfaceHolder(Surface surface) { 42 | mSurface = surface; 43 | } 44 | 45 | @Override 46 | public void addCallback(Callback callback) { 47 | } 48 | 49 | @Override 50 | public void removeCallback(Callback callback) { 51 | } 52 | 53 | @Override 54 | public boolean isCreating() { 55 | return false; 56 | } 57 | 58 | @Override 59 | public void setType(int type) { 60 | } 61 | 62 | @Override 63 | public void setFixedSize(int width, int height) { 64 | } 65 | 66 | @Override 67 | public void setSizeFromLayout() { 68 | } 69 | 70 | @Override 71 | public void setFormat(int format) { 72 | } 73 | 74 | @Override 75 | public void setKeepScreenOn(boolean screenOn) { 76 | } 77 | 78 | @Override 79 | public Canvas lockCanvas() { 80 | return null; 81 | } 82 | 83 | @Override 84 | public Canvas lockCanvas(Rect dirty) { 85 | return null; 86 | } 87 | 88 | @Override 89 | public void unlockCanvasAndPost(Canvas canvas) { 90 | } 91 | 92 | @Override 93 | public Rect getSurfaceFrame() { 94 | return null; 95 | } 96 | 97 | @Override 98 | public Surface getSurface() { 99 | return mSurface; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/common/TimeStamp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.common; 23 | 24 | /** 25 | * A collection of functions to handle the timestamp. 26 | */ 27 | public final class TimeStamp { 28 | 29 | // Number of milliseconds between Jan 1, 1900 and Jan 1, 1970 (70 years plus 17 leap days) 30 | private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L * 1000L; 31 | 32 | /** 33 | * Hidden constructor, the class cannot be instantiated. 34 | */ 35 | private TimeStamp() { 36 | } 37 | 38 | /** 39 | * Returns the current high-resolution timestamp, in microseconds.
40 | * This method can only be used to measure elapsed time and is not related to any other notion 41 | * of system or wall-clock time. The value returned represents microseconds since some fixed but 42 | * arbitrary origin time (perhaps in the future, so values may be negative). 43 | * The same origin is used by all invocations of this method. 44 | * 45 | * @return the current timestamp in microseconds 46 | */ 47 | public static long getTimeStamp() { 48 | return System.nanoTime() / 1000L; 49 | } 50 | 51 | /** 52 | * Returns the current timestamp in NTP format (RFC-1305).
53 | * NTP timestamps are represented as a 64-bit unsigned fixed-point number, in seconds relative to 54 | * 0h on 1 January 1900. The integer part is in the first 32 bits and the fraction part in the 55 | * last 32 bits. In the fraction part, the non-significant low-order bits should be set to 0. 56 | * 57 | * @return the current NTP timestamp 58 | */ 59 | public static long getNTPTimeStamp() { 60 | long timeMillis = System.currentTimeMillis() + OFFSET_1900_TO_1970; 61 | long timeSeconds = timeMillis / 1000L; 62 | long timeFraction = timeMillis - timeSeconds * 1000L; 63 | return (timeSeconds << 32) | (((timeFraction << 32) / 1000L) & 0xFFFFFFFFL); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/aidl/com/spynet/camera/services/IStreamServiceCallBack.aidl: -------------------------------------------------------------------------------- 1 | package com.spynet.camera.services; 2 | 3 | /** 4 | * Interface defining the methods that the StreamService uses to communicate with the client. 5 | */ 6 | interface IStreamServiceCallBack { 7 | /** 8 | * Notifies that the streaming has started. 9 | */ 10 | oneway void onStreamingStarted(); 11 | 12 | /** 13 | * Notifies that the streaming has stopped. 14 | */ 15 | oneway void onStreamingStopped(); 16 | 17 | /** 18 | * Notifies that the audio streaming has started. 19 | */ 20 | oneway void onAudioStarted(); 21 | 22 | /** 23 | * Notifies that the audio streaming has stopped. 24 | */ 25 | oneway void onAudioStopped(); 26 | 27 | /** 28 | * Notifies that an adapter has connected to its server. 29 | * 30 | * @param adapter the adapter name 31 | */ 32 | oneway void onAdapterConnected(in String adapter); 33 | 34 | /** 35 | * Notifies that an adapter has disconnected from the server. 36 | * 37 | * @param adapter the adapter name 38 | */ 39 | oneway void onAdapterDisconnected(in String adapter); 40 | 41 | /** 42 | * Notifies that an action has been requested by a client. 43 | * 44 | * @param code the log code 45 | * @param message the log message 46 | */ 47 | oneway void onLog(int code, in String message); 48 | 49 | /** 50 | * Notifies that the frame size changed. 51 | * 52 | * @param size the frame size in pixels 53 | */ 54 | oneway void onFrameSizeChanged(in Point size); 55 | 56 | /** 57 | * Notifies that the bitrate changed. 58 | * 59 | * @param video the video bitrate 60 | * @param audio the audio bitrate 61 | */ 62 | oneway void onBitrateChanged(int video, int audio); 63 | 64 | /** 65 | * Notifies that a new zoom has been set. 66 | * 67 | * @param zoom the new zoom factor 68 | */ 69 | oneway void onZoom(float zoom); 70 | 71 | /** 72 | * Called when the torch state changes. 73 | * 74 | * @param state {@code true} if the torch is on, {@code false} if it is off 75 | */ 76 | oneway void onTorch(boolean state); 77 | 78 | /** 79 | * Notifies that a new mute state has been set. 80 | * 81 | * @param mute the new mute state 82 | */ 83 | oneway void onMute(boolean mute); 84 | 85 | /** 86 | * Notifies that a new frame rate value is available. 87 | * 88 | * @param fps the new frame rate value 89 | */ 90 | oneway void onFrameRate(float fps); 91 | 92 | /** 93 | * Called when the screen capture has been denied or authorized by the user. 94 | * 95 | * @param authorized whether the screen capture has been authorized by the user 96 | */ 97 | oneway void onScreenCapture(boolean authorized); 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/InfoCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import android.content.Context; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | import org.json.JSONException; 28 | import org.json.JSONObject; 29 | 30 | import java.io.IOException; 31 | import java.util.Calendar; 32 | import java.util.TimeZone; 33 | 34 | /** 35 | * Defines the Mangocam API INFO command.
36 | *
37 | * Command example:
38 | *
39 | * INFO [] 40 | */ 41 | public class InfoCommand implements MangocamCommand { 42 | 43 | private final Context mContext; 44 | private final int mImageWidth, mImageHeight; 45 | 46 | /** 47 | * Creates a new InfoCommand object. 48 | * 49 | * @param context the context where the object is used 50 | * @param width image width 51 | * @param height image height 52 | */ 53 | public InfoCommand(@NotNull Context context, int width, int height) { 54 | mContext = context; 55 | mImageWidth = width; 56 | mImageHeight = height; 57 | } 58 | 59 | @Override 60 | public String get() throws JSONException { 61 | JSONObject jObject = new JSONObject(); 62 | jObject.put("cmd", "INFO"); 63 | jObject.put("vendor", "spyNet"); 64 | jObject.put("s_ver", com.spynet.camera.BuildConfig.VERSION_NAME); 65 | jObject.put("os_name", "Android"); 66 | jObject.put("os_ver", android.os.Build.VERSION.RELEASE); 67 | Calendar cal = Calendar.getInstance(); 68 | TimeZone tz = cal.getTimeZone(); 69 | jObject.put("tz", tz.getID()); 70 | jObject.put("max_res_x", mImageWidth); 71 | jObject.put("max_res_y", mImageHeight); 72 | jObject.put("aspect", Math.floor((double) mImageWidth / (double) mImageHeight * 100.0) / 100.0); 73 | return "OK " + jObject.toString() + "\r\n"; 74 | } 75 | 76 | @Override 77 | public void parse(String command) throws IOException { 78 | // Nothing to do 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Angelcam/API/RedirectMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Angelcam.API; 23 | 24 | import java.io.InvalidObjectException; 25 | 26 | /** 27 | * Defines the Arrow protocol REDIRECT message.
28 | * The message can be sent by server to redirect a client to another server. No ACK is expected, the 29 | * server closes connection immediately after sending the redirect command. Message data consist 30 | * of a "host:port" NULL terminated string. 31 | */ 32 | public class RedirectMessage extends ControlMessage { 33 | 34 | private final String mHost; // Host 35 | private final int mPort; // Port 36 | 37 | /** 38 | * Wraps a RedirectMessage object around a ControlMessage object. 39 | * 40 | * @param message the original ControlMessage object 41 | * @throws InvalidObjectException if the {@code message} doesn't match 42 | */ 43 | public RedirectMessage(ControlMessage message) throws InvalidObjectException { 44 | super(message.mMessageID, message.mType); 45 | if (mType != TYPE_REDIRECT) 46 | throw new InvalidObjectException("the message is not a REDIRECT message"); 47 | if (message.mData == null) 48 | throw new InvalidObjectException("the message has no data"); 49 | if (message.mData.length < 2 || message.mData[message.mData.length - 1] != 0) 50 | throw new InvalidObjectException("the message contains invalid data"); 51 | String host = new String(message.mData, 0, message.mData.length - 1); 52 | String[] c = host.split(":"); 53 | if (c.length != 2) 54 | throw new InvalidObjectException("the message contains invalid data"); 55 | mHost = c[0]; 56 | mPort = Integer.parseInt(c[1]); 57 | } 58 | 59 | /** 60 | * @return the host name 61 | */ 62 | public String getHost() { 63 | return mHost; 64 | } 65 | 66 | /** 67 | * @return the port number 68 | */ 69 | public int getPort() { 70 | return mPort; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/ui/ServiceFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.ui; 23 | 24 | import android.content.Context; 25 | import android.support.v4.app.Fragment; 26 | import android.content.ServiceConnection; 27 | import android.os.Bundle; 28 | 29 | import com.spynet.camera.services.IStreamService; 30 | 31 | /** 32 | * Defines a retained Fragment where to store {@link com.spynet.camera.services.StreamService} 33 | * references, to keep them persistent between Activity recreation. 34 | */ 35 | public class ServiceFragment extends Fragment { 36 | 37 | private Context mContext; 38 | private ServiceConnection mConnection; 39 | private IStreamService mService; 40 | 41 | @Override 42 | public void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | setRetainInstance(true); 45 | } 46 | 47 | @Override 48 | public void onAttach(Context context) { 49 | super.onAttach(context); 50 | mContext = context; 51 | } 52 | 53 | @Override 54 | public void onDetach() { 55 | super.onDetach(); 56 | mContext = null; 57 | } 58 | 59 | /** 60 | * @return the {@link Context} the fragment is attached to 61 | */ 62 | public Context getContext() { 63 | return mContext; 64 | } 65 | 66 | /** 67 | * Stores a {@link ServiceConnection} reference. 68 | */ 69 | public void setServiceConnection(ServiceConnection connection) { 70 | mConnection = connection; 71 | } 72 | 73 | /** 74 | * @return the {@link ServiceConnection} previously stored by setServiceConnection() 75 | */ 76 | public ServiceConnection getServiceConnection() { 77 | return mConnection; 78 | } 79 | 80 | /** 81 | * Stores a {@link IStreamService} reference. 82 | */ 83 | public void setStreamService(IStreamService service) { 84 | mService = service; 85 | } 86 | 87 | /** 88 | * @return the {@link IStreamService} previously stored by setStreamService() 89 | */ 90 | public IStreamService getStreamService() { 91 | return mService; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_status.xml: -------------------------------------------------------------------------------- 1 | 21 | 22 | 29 | 30 | 39 | 40 | 49 | 50 | 59 | 60 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 29 | 30 | 49 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/ui/ScreenCaptureRequestActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.ui; 23 | 24 | import android.content.Context; 25 | import android.content.Intent; 26 | import android.media.projection.MediaProjectionManager; 27 | import android.support.v7.app.AppCompatActivity; 28 | import android.os.Bundle; 29 | import android.util.Log; 30 | 31 | import com.spynet.camera.media.Recorder; 32 | 33 | import org.jetbrains.annotations.NotNull; 34 | 35 | /** 36 | * An {@link android.app.Activity} that will fire the screen capture request 37 | * to the user. 38 | */ 39 | public class ScreenCaptureRequestActivity extends AppCompatActivity { 40 | 41 | private static final int SCREEN_CAPTURE_REQUEST_ID = 2536; 42 | 43 | private final String TAG = getClass().getSimpleName(); 44 | 45 | /** 46 | * Factory method that makes an explicit intent used to start the 47 | * ScreenCaptureRequestActivity. 48 | * 49 | * @param context the context in which the Activity will execute 50 | * @return the created Intent 51 | */ 52 | @NotNull 53 | public static Intent MakeIntent(Context context) { 54 | return new Intent(context, ScreenCaptureRequestActivity.class); 55 | } 56 | 57 | @Override 58 | protected void onCreate(Bundle savedInstanceState) { 59 | super.onCreate(savedInstanceState); 60 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { 61 | MediaProjectionManager manager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE); 62 | startActivityForResult(manager.createScreenCaptureIntent(), SCREEN_CAPTURE_REQUEST_ID); 63 | } else { 64 | Log.w(TAG, "Media projection requires API " + android.os.Build.VERSION_CODES.LOLLIPOP); 65 | finish(); 66 | } 67 | } 68 | 69 | @Override 70 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 71 | if (requestCode == SCREEN_CAPTURE_REQUEST_ID) { 72 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { 73 | Intent intent = new Intent(Recorder.ACTION_START_SCREEN_CAPTURE); 74 | intent.putExtra(Recorder.EXTRA_MEDIA_PROJECTION_RESULT, resultCode); 75 | intent.putExtra(Recorder.EXTRA_MEDIA_PROJECTION_INTENT, data); 76 | sendBroadcast(intent); 77 | } 78 | finish(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 47 | 48 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 69 | 70 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/StopMJPEGCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import android.content.Context; 25 | import android.util.JsonReader; 26 | 27 | import org.jetbrains.annotations.NotNull; 28 | import org.json.JSONException; 29 | 30 | import java.io.IOException; 31 | import java.io.StringReader; 32 | 33 | /** 34 | * Defines the Mangocam API STOP_MJPEG command.
35 | *
36 | * Command example:
37 | *
38 | * STOP_MJPEG {"host":"www107.mangocam.com","task":"201007331","node":"107"} 39 | */ 40 | public class StopMJPEGCommand implements MangocamCommand { 41 | 42 | private final Context mContext; 43 | private String mHost; 44 | private int mNode; 45 | private int mTask; 46 | 47 | /** 48 | * Creates a new StatsCommand object. 49 | * 50 | * @param context the context where the object is used 51 | */ 52 | public StopMJPEGCommand(@NotNull Context context) { 53 | mContext = context; 54 | } 55 | 56 | @Override 57 | public String get() throws JSONException { 58 | return "OK {\"cmd\":\"STOP_MJPEG\"}\r\n"; 59 | } 60 | 61 | @Override 62 | public void parse(String command) throws IOException { 63 | if (!command.startsWith("STOP_MJPEG ")) 64 | throw new IllegalArgumentException("wrong command"); 65 | command = command.substring(11); 66 | JsonReader jr = new JsonReader(new StringReader(command)); 67 | jr.beginObject(); 68 | while (jr.hasNext()) { 69 | switch (jr.nextName()) { 70 | case "host": 71 | mHost = jr.nextString(); 72 | break; 73 | case "node": 74 | mNode = jr.nextInt(); 75 | break; 76 | case "task": 77 | mTask = jr.nextInt(); 78 | break; 79 | default: 80 | jr.skipValue(); 81 | } 82 | } 83 | jr.endObject(); 84 | } 85 | 86 | /** 87 | * @return the host to send MJPEG to 88 | */ 89 | public String getHost() { 90 | return mHost; 91 | } 92 | 93 | /** 94 | * @return the node 95 | */ 96 | public int getNode() { 97 | return mNode; 98 | } 99 | 100 | /** 101 | * @return the task ID, used by the upload server, the client will just relay 102 | */ 103 | public int getTask() { 104 | return mTask; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/gl/Shader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.gl; 23 | 24 | import android.opengl.GLES20; 25 | 26 | /** 27 | * Allows to create an OpenGL program by compiling and linking a given vertex shader 28 | * and a fragment shader. 29 | */ 30 | public class Shader { 31 | 32 | /** 33 | * The program object. 34 | */ 35 | public final int program; 36 | 37 | /** 38 | * Creates a new Shader object. 39 | * 40 | * @param vertexShaderSource the vertex shader source code 41 | * @param fragmentShaderSource the fragment shader source code 42 | */ 43 | public Shader(String vertexShaderSource, String fragmentShaderSource) { 44 | 45 | int[] result = new int[1]; 46 | String infoLog; 47 | 48 | // Build and compile vertex shader 49 | int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); 50 | GLES20.glShaderSource(vertexShader, vertexShaderSource); 51 | GLES20.glCompileShader(vertexShader); 52 | GLES20.glGetShaderiv(vertexShader, GLES20.GL_COMPILE_STATUS, result, 0); 53 | if (result[0] == 0) { 54 | infoLog = GLES20.glGetShaderInfoLog(vertexShader); 55 | throw new RuntimeException(infoLog); 56 | } 57 | 58 | // Build and compile fragment shader 59 | int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); 60 | GLES20.glShaderSource(fragmentShader, fragmentShaderSource); 61 | GLES20.glCompileShader(fragmentShader); 62 | GLES20.glGetShaderiv(fragmentShader, GLES20.GL_COMPILE_STATUS, result, 0); 63 | if (result[0] == 0) { 64 | infoLog = GLES20.glGetShaderInfoLog(fragmentShader); 65 | throw new RuntimeException(infoLog); 66 | } 67 | 68 | // Link shaders 69 | program = GLES20.glCreateProgram(); 70 | GLES20.glAttachShader(program, vertexShader); 71 | GLES20.glAttachShader(program, fragmentShader); 72 | GLES20.glLinkProgram(program); 73 | GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, result, 0); 74 | if (result[0] == 0) { 75 | infoLog = GLES20.glGetProgramInfoLog(vertexShader); 76 | throw new RuntimeException(infoLog); 77 | } 78 | 79 | // Delete the shaders as they're linked into our program now and no longer necessary 80 | GLES20.glDeleteShader(vertexShader); 81 | GLES20.glDeleteShader(fragmentShader); 82 | } 83 | 84 | /** 85 | * Use the program by calling {@code glUseProgram(program)}. 86 | */ 87 | public void use() { 88 | GLES20.glUseProgram(program); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/media/CameraInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.media; 23 | 24 | import android.graphics.Point; 25 | import android.os.Parcel; 26 | import android.os.Parcelable; 27 | 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | 31 | /** 32 | * Defines a {@link Parcelable} camera information container. 33 | */ 34 | public class CameraInfo implements Parcelable { 35 | 36 | private final String mDescription; 37 | private final int mCameraId; 38 | private final List mSupportedPreviewSizes; 39 | 40 | /** 41 | * Creates a new CameraInfo object from Parcel. 42 | * 43 | * @param in the input Parcel 44 | */ 45 | protected CameraInfo(Parcel in) { 46 | mDescription = in.readString(); 47 | mCameraId = in.readInt(); 48 | mSupportedPreviewSizes = new ArrayList<>(); 49 | in.readTypedList(mSupportedPreviewSizes, Point.CREATOR); 50 | } 51 | 52 | /** 53 | * Creates a new CameraInfo object. 54 | * 55 | * @param description the camera description 56 | * @param cameraId the camera id 57 | * @param sizes the preview resolutions supported by the camera. 58 | */ 59 | public CameraInfo(String description, int cameraId, List sizes) { 60 | mDescription = description; 61 | mCameraId = cameraId; 62 | mSupportedPreviewSizes = sizes != null ? new ArrayList<>(sizes) : null; 63 | } 64 | 65 | /** 66 | * @return the camera description 67 | */ 68 | public String getDescription() { 69 | return mDescription; 70 | } 71 | 72 | /** 73 | * @return the camera ID 74 | */ 75 | public int getCameraId() { 76 | return mCameraId; 77 | } 78 | 79 | /** 80 | * @return the list of supported preview sizes 81 | */ 82 | public List getSupportedPreviewSizes() { 83 | return mSupportedPreviewSizes; 84 | } 85 | 86 | public static final Creator CREATOR = new Creator() { 87 | @Override 88 | public CameraInfo createFromParcel(Parcel in) { 89 | return new CameraInfo(in); 90 | } 91 | 92 | @Override 93 | public CameraInfo[] newArray(int size) { 94 | return new CameraInfo[size]; 95 | } 96 | }; 97 | 98 | @Override 99 | public int describeContents() { 100 | return 0; 101 | } 102 | 103 | @Override 104 | public void writeToParcel(Parcel dest, int flags) { 105 | dest.writeString(mDescription); 106 | dest.writeInt(mCameraId); 107 | dest.writeTypedList(mSupportedPreviewSizes); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/TCPAudioPacketizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network; 23 | 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | import java.io.IOException; 27 | 28 | /** 29 | * Defines the RTP packetizer to stream AAC audio over a TCP channel.
30 | * It implements RTP/RTCP over RTSP as defined in RFC 2326, session 10.12.
31 | * Stream data such as RTP packets is encapsulated by an ASCII dollar 32 | * sign (24 hexadecimal), followed by a one-byte channel identifier, 33 | * followed by the length of the encapsulated binary data as a binary, 34 | * two-byte integer in network byte order. The stream data follows 35 | * immediately afterwards, without a CRLF, but including the upper-layer 36 | * protocol headers. Each $ block contains exactly one upper-layer 37 | * protocol data unit, e.g., one RTP packet. 38 | */ 39 | public class TCPAudioPacketizer extends RTPAudioPacketizer { 40 | 41 | private static final int RTP_PACKET_SIZE = 2000; 42 | 43 | private final byte[] mPacket; // The RTP packet 44 | private final int mRTPChannel; // The channel to use to send RTP packets 45 | private final int mRTCPChannel; // The channel to use to send RTCP packets 46 | 47 | /** 48 | * Creates a new TCPAudioPacketizer object. 49 | * 50 | * @param connection the StreamConnection that owns the packetizer 51 | * @param rtpChannel the channel used to send RTP packets 52 | * @param rtcpChannel the channel used to send RTCP packets 53 | * @param clock the clock rate in Hz 54 | * @param seq the sequence number of the first packet 55 | */ 56 | public TCPAudioPacketizer(@NotNull StreamConnection connection, 57 | int rtpChannel, int rtcpChannel, 58 | int clock, int seq) { 59 | super(connection, clock, RTP_PACKET_SIZE, seq); 60 | mPacket = new byte[4 + RTP_PACKET_SIZE]; 61 | mRTPChannel = rtpChannel; 62 | mRTCPChannel = rtcpChannel; 63 | mPacket[0] = '$'; 64 | } 65 | 66 | @Override 67 | protected void rtpSend(byte[] data, int length) throws IOException { 68 | mPacket[1] = (byte) mRTPChannel; 69 | mPacket[2] = (byte) (length >> 8); 70 | mPacket[3] = (byte) length; 71 | System.arraycopy(data, 0, mPacket, 4, length); 72 | mConnection.write(mPacket, 0, 4 + length); 73 | } 74 | 75 | @Override 76 | protected void rtcpSend(byte[] data, int length) throws IOException { 77 | mPacket[1] = (byte) (mRTCPChannel); 78 | mPacket[2] = (byte) (length >> 8); 79 | mPacket[3] = (byte) length; 80 | System.arraycopy(data, 0, mPacket, 4, length); 81 | mConnection.write(mPacket, 0, 4 + length); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/TCPVideoPacketizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network; 23 | 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | import java.io.IOException; 27 | 28 | /** 29 | * Defines the RTP packetizer to stream AVC video slices over a TCP channel.
30 | * It implements RTP/RTCP over RTSP as defined in RFC 2326, session 10.12.
31 | * Stream data such as RTP packets is encapsulated by an ASCII dollar 32 | * sign (24 hexadecimal), followed by a one-byte channel identifier, 33 | * followed by the length of the encapsulated binary data as a binary, 34 | * two-byte integer in network byte order. The stream data follows 35 | * immediately afterwards, without a CRLF, but including the upper-layer 36 | * protocol headers. Each $ block contains exactly one upper-layer 37 | * protocol data unit, e.g., one RTP packet. 38 | */ 39 | public class TCPVideoPacketizer extends RTPVideoPacketizer { 40 | 41 | private static final int RTP_PACKET_SIZE = 65000; 42 | 43 | private final byte[] mPacket; // The RTP packet 44 | private final int mRTPChannel; // The channel to use to send RTP packets 45 | private final int mRTCPChannel; // The channel to use to send RTCP packets 46 | 47 | /** 48 | * Creates a new TCPVideoPacketizer object. 49 | * 50 | * @param connection the StreamConnection that owns the packetizer 51 | * @param rtpChannel the channel used to send RTP packets 52 | * @param rtcpChannel the channel used to send RTCP packets 53 | * @param clock the clock rate in Hz 54 | * @param seq the sequence number of the first packet 55 | */ 56 | public TCPVideoPacketizer(@NotNull StreamConnection connection, 57 | int rtpChannel, int rtcpChannel, 58 | int clock, int seq) { 59 | super(connection, clock, RTP_PACKET_SIZE, seq); 60 | mPacket = new byte[4 + RTP_PACKET_SIZE]; 61 | mRTPChannel = rtpChannel; 62 | mRTCPChannel = rtcpChannel; 63 | mPacket[0] = '$'; 64 | } 65 | 66 | @Override 67 | protected void rtpSend(byte[] data, int length) throws IOException { 68 | mPacket[1] = (byte) mRTPChannel; 69 | mPacket[2] = (byte) (length >> 8); 70 | mPacket[3] = (byte) length; 71 | System.arraycopy(data, 0, mPacket, 4, length); 72 | mConnection.write(mPacket, 0, 4 + length); 73 | } 74 | 75 | @Override 76 | protected void rtcpSend(byte[] data, int length) throws IOException { 77 | mPacket[1] = (byte) (mRTCPChannel); 78 | mPacket[2] = (byte) (length >> 8); 79 | mPacket[3] = (byte) length; 80 | System.arraycopy(data, 0, mPacket, 4, length); 81 | mConnection.write(mPacket, 0, 4 + length); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/DisconnectCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import android.content.Context; 25 | import android.util.JsonReader; 26 | 27 | import org.jetbrains.annotations.NotNull; 28 | import org.json.JSONException; 29 | 30 | import java.io.IOException; 31 | import java.io.StringReader; 32 | import java.util.Random; 33 | 34 | /** 35 | * Defines the Mangocam API DISCONNECT command.
36 | */ 37 | public class DisconnectCommand implements MangocamCommand { 38 | 39 | private final Context mContext; 40 | private int mWaitSec = 0, mWaitSecMin = 0, mWaitSecMax = 0; 41 | private String mWaitReason = ""; 42 | 43 | /** 44 | * Creates a new DisconnectCommand object. 45 | * 46 | * @param context the context where the object is used 47 | */ 48 | public DisconnectCommand(@NotNull Context context) { 49 | mContext = context; 50 | } 51 | 52 | @Override 53 | public String get() throws JSONException { 54 | return "OK {\"cmd\":\"DISCONNECT\"}\r\n"; 55 | } 56 | 57 | @Override 58 | public void parse(String command) throws IOException { 59 | if (!command.startsWith("DISCONNECT ")) 60 | throw new IllegalArgumentException("wrong command"); 61 | command = command.substring(11); 62 | JsonReader jr = new JsonReader(new StringReader(command)); 63 | jr.beginObject(); 64 | while (jr.hasNext()) { 65 | switch (jr.nextName()) { 66 | case "wait_time_secs": 67 | mWaitSec = jr.nextInt(); 68 | break; 69 | case "wait_time_secs_min": 70 | mWaitSecMin = jr.nextInt(); 71 | break; 72 | case "wait_time_secs_max": 73 | mWaitSecMax = jr.nextInt(); 74 | break; 75 | case "wait_reason": 76 | mWaitReason = jr.nextString(); 77 | break; 78 | default: 79 | jr.skipValue(); 80 | } 81 | } 82 | jr.endObject(); 83 | } 84 | 85 | /** 86 | * @return the requested wait delay in seconds before to reconnect 87 | */ 88 | public int getWaitDelay() { 89 | if (mWaitSecMax > mWaitSecMin) { 90 | Random random = new Random(System.currentTimeMillis()); 91 | return mWaitSecMin + random.nextInt(mWaitSecMax - mWaitSecMin); 92 | } else { 93 | return mWaitSec; 94 | } 95 | } 96 | 97 | /** 98 | * @return the reason to wait before to reconnect 99 | */ 100 | public String getWaitReason() { 101 | return mWaitReason; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/DDNS/DuckDNSClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.DDNS; 23 | 24 | import android.content.Context; 25 | import android.util.Log; 26 | 27 | import com.spynet.camera.ui.SettingsActivity; 28 | 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | import java.io.BufferedReader; 32 | import java.io.FileNotFoundException; 33 | import java.io.InputStream; 34 | import java.io.InputStreamReader; 35 | import java.net.HttpURLConnection; 36 | import java.net.URL; 37 | import java.text.DateFormat; 38 | import java.util.Date; 39 | 40 | /** 41 | * Implements the Duck DNS client (https://www.duckdns.org). 42 | */ 43 | public class DuckDNSClient extends DDNSClient { 44 | 45 | protected String mToken; // The account token (aka password) 46 | 47 | /** 48 | * Creates a new DuckDNSClient object. 49 | * 50 | * @param context the context where the NoIpClient is used 51 | * @param hostname the public hostname handled by the DDNS service 52 | * @param username the DDNS service username 53 | * @param password the DDNS service password 54 | */ 55 | public DuckDNSClient(@NotNull Context context, String hostname, String username, String password) { 56 | super(context, hostname, username, password); 57 | mToken = password; 58 | mURL = "https://www.duckdns.org/update"; 59 | } 60 | 61 | @Override 62 | protected String updateDDNS() { 63 | HttpURLConnection connection = null; 64 | try { 65 | URL url = new URL(mURL + "?" + "domains=" + mHostname + "&token=" + mToken + "&verbose=true"); 66 | connection = (HttpURLConnection) url.openConnection(); 67 | connection.addRequestProperty("User-Agent", mUserAgent); 68 | connection.setConnectTimeout(TIMEOUT); 69 | connection.setReadTimeout(TIMEOUT); 70 | InputStream in; 71 | try { 72 | in = connection.getInputStream(); 73 | } catch (FileNotFoundException e) { 74 | in = connection.getErrorStream(); 75 | } 76 | BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); 77 | String result = "", data; 78 | while ((data = reader.readLine()) != null) result += data + " "; 79 | Log.v(TAG, "DDNS update result: " + result); 80 | return result; 81 | } catch (Exception e) { 82 | Log.e(TAG, "DDNS update request failed", e); 83 | return null; 84 | } finally { 85 | if (connection != null) 86 | connection.disconnect(); 87 | } 88 | } 89 | 90 | @Override 91 | protected void parseResult(String result) { 92 | String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date()); 93 | SettingsActivity.setServerDDNSLastUpdate(mContext, currentDateTimeString + " - " + result); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Angelcam/API/HungUpMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Angelcam.API; 23 | 24 | import java.io.ByteArrayOutputStream; 25 | import java.io.IOException; 26 | import java.io.InvalidObjectException; 27 | 28 | /** 29 | * Defines the Arrow protocol HUP message.
30 | * Hangup notification. It might be sent by both client and server to notify the other side of the 31 | * communication that a session with a given ID has been terminated. 32 | */ 33 | public class HungUpMessage extends ControlMessage { 34 | 35 | private final int mSessionID; // Session ID identifying a connection to a local service 36 | private final int mErrorCode; // Error code 37 | 38 | /** 39 | * Creates a new HungUpMessage object. 40 | * 41 | * @param messageID message ID, used for request/response pairing 42 | * @param sessionID ID of the session that has been terminated 43 | * @param errorCode error code 44 | */ 45 | public HungUpMessage(int messageID, int sessionID, int errorCode) { 46 | super(messageID, TYPE_HUP); 47 | mSessionID = sessionID; 48 | mErrorCode = errorCode; 49 | } 50 | 51 | /** 52 | * Wraps an HungUpMessage object around a ControlMessage object. 53 | * 54 | * @param message the original ControlMessage object 55 | * @throws InvalidObjectException if the {@code message} doesn't match 56 | */ 57 | public HungUpMessage(ControlMessage message) throws InvalidObjectException { 58 | super(message.mMessageID, message.mType); 59 | if (mType != TYPE_HUP) 60 | throw new InvalidObjectException("the message is not an HUP message"); 61 | if (message.mData == null) 62 | throw new InvalidObjectException("the message has no data"); 63 | if (message.mData.length != 8) 64 | throw new InvalidObjectException("the message contains invalid data"); 65 | mSessionID = ((message.mData[1] & 0xff) << 16) | 66 | ((message.mData[2] & 0xff) << 8) | (message.mData[3] & 0xff); 67 | mErrorCode = ((message.mData[4] & 0xff) << 24) | ((message.mData[5] & 0xff) << 16) | 68 | ((message.mData[6] & 0xff) << 8) | (message.mData[7] & 0xff); 69 | } 70 | 71 | @Override 72 | public byte[] toByteArray() throws IOException { 73 | 74 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 75 | 76 | // error_code - 32bit unsigned integer 77 | buffer.write(mErrorCode >> 24); 78 | buffer.write(mErrorCode >> 16); 79 | buffer.write(mErrorCode >> 8); 80 | buffer.write(mErrorCode); 81 | 82 | mData = buffer.toByteArray(); 83 | return super.toByteArray(); 84 | } 85 | 86 | @Override 87 | public int getSessionID() { 88 | return mSessionID; 89 | } 90 | 91 | /** 92 | * @return the error code 93 | */ 94 | public int getErrorCode() { 95 | return mErrorCode; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/aidl/com/spynet/camera/services/IStreamService.aidl: -------------------------------------------------------------------------------- 1 | package com.spynet.camera.services; 2 | 3 | import com.spynet.camera.media.CameraInfo; 4 | import com.spynet.camera.services.IStreamServiceCallBack; 5 | 6 | /** 7 | * Interface defining the methods to communicate with the StreamService. 8 | */ 9 | interface IStreamService { 10 | /** 11 | * Registers the callback used by the StreamService to communicate with the client. 12 | */ 13 | oneway void registerCallBack(in IStreamServiceCallBack cb); 14 | 15 | /** 16 | * Restarts a service functionality. 17 | * 18 | * @param what what to restart 19 | */ 20 | void restart(in String what); 21 | 22 | /** 23 | * @return the number of available cameras 24 | */ 25 | int getNumberOfCameras(); 26 | 27 | /** 28 | * Returns the information of one camera. 29 | * 30 | * @param index the index of the information to be returned, 31 | * from 0 to {@code getNumberOfCameras()} - 1 32 | * @return the information of the camera referred by {@code cameraId} 33 | */ 34 | CameraInfo getCameraInfo(int index); 35 | 36 | /** 37 | * Sets the surface where to stream the video. 38 | * 39 | * @param surface the surface where to stream the video, null to render offscreen 40 | */ 41 | void setSurface(in Surface surface); 42 | 43 | /** 44 | * @return whether the screen capture camera is used 45 | */ 46 | boolean isScreenCaptureCamera(); 47 | 48 | /** 49 | * @return whether a front camera is used 50 | */ 51 | boolean isFrontCamera(); 52 | 53 | /** 54 | * @return the frame size in pixels 55 | */ 56 | Point getFrameSize(); 57 | 58 | /** 59 | * @return the average frame rate in frames per second 60 | */ 61 | float getAverageFrameRate(); 62 | 63 | /** 64 | * Sets the camera zoom. 65 | * 66 | * @param zoom the zoom factor 67 | */ 68 | void setZoom(float zoom); 69 | 70 | /** 71 | * @return the camera zoom 72 | */ 73 | float getZoom(); 74 | 75 | /** 76 | * Starts camera auto-focus. 77 | * 78 | * @param x the horizontal coordinate of the focus area, in the range -1000 to 1000. 79 | * @param y the vertical coordinate of the focus area, in the range -1000 to 1000. 80 | */ 81 | void autoFocus(int x, int y); 82 | 83 | /** 84 | * @return the video bitrate in bps 85 | */ 86 | int getVideoBitrate(); 87 | 88 | /** 89 | * @return the audio bitrate in bps 90 | */ 91 | int getAudioBitrate(); 92 | 93 | /** 94 | * @return the number of active streams 95 | */ 96 | int getNumberOfStreams(); 97 | 98 | /** 99 | * @return the number of active audio streams 100 | */ 101 | int getNumberOfAudioStreams(); 102 | 103 | /** 104 | * Sets the audio gain. 105 | * 106 | * @param audio gain in dB 107 | */ 108 | void setGain(double gain); 109 | 110 | /** 111 | * Sets the audio mute state. 112 | * 113 | * @param muet the mute state 114 | */ 115 | void setMute(boolean mute); 116 | 117 | /** 118 | * @return the audio mute state 119 | */ 120 | boolean getMute(); 121 | 122 | /** 123 | * @return whether the H264 stream is available 124 | */ 125 | boolean isH264Available(); 126 | 127 | /** 128 | * @return whether the MJPEG stream is available 129 | */ 130 | boolean isMJPEGAvailable(); 131 | 132 | /** 133 | * @return whether the screen capture is available 134 | */ 135 | boolean isScreenCaptureAvailable(); 136 | 137 | /** 138 | * @return whether the MangocamAdapter is connected 139 | */ 140 | boolean isMangocamConnected(); 141 | 142 | /** 143 | * @return whether the AngelcamAdapter is connected 144 | */ 145 | boolean isAngelcamConnected(); 146 | } 147 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/media/AudioData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.media; 23 | 24 | import android.media.AudioFormat; 25 | 26 | /** 27 | * Defines a buffer containing audio data. 28 | */ 29 | public class AudioData { 30 | 31 | private static final int FORMAT_COMPRESSED = -1; 32 | private static final int TYPE_UNCOMPRESSED_AUDIO = 1; 33 | private static final int TYPE_COMPRESSED_AUDIO = 2; 34 | private static final int TYPE_AUDIO_CONFIG = 3; 35 | 36 | private final byte[] data; // The audio data 37 | private final int format; // The data format 38 | private final int type; // The data type 39 | private final long timestamp; // The timestamp 40 | 41 | /** 42 | * Creates a new AudioData object that contains uncompressed audio. 43 | * 44 | * @param data the raw data 45 | * @param format the data format ({@link AudioFormat}) 46 | * @param timestamp the timestamp 47 | */ 48 | public AudioData(byte[] data, int format, long timestamp) { 49 | this.data = (data != null ? data.clone() : null); 50 | this.format = format; 51 | this.timestamp = timestamp; 52 | this.type = TYPE_UNCOMPRESSED_AUDIO; 53 | } 54 | 55 | /** 56 | * Creates a new AudioData object that contains compressed audio. 57 | * 58 | * @param data the raw data 59 | * @param timestamp the timestamp 60 | */ 61 | public AudioData(byte[] data, long timestamp) { 62 | this.data = (data != null ? data.clone() : null); 63 | this.format = FORMAT_COMPRESSED; 64 | this.timestamp = timestamp; 65 | this.type = TYPE_COMPRESSED_AUDIO; 66 | } 67 | 68 | /** 69 | * Creates a new AudioData object that contains audio configuration information. 70 | * 71 | * @param data the raw data 72 | */ 73 | public AudioData(byte[] data) { 74 | this.data = (data != null ? data.clone() : null); 75 | this.format = FORMAT_COMPRESSED; 76 | this.timestamp = 0; 77 | this.type = TYPE_AUDIO_CONFIG; 78 | } 79 | 80 | /** 81 | * @return the raw data 82 | */ 83 | public byte[] getData() { 84 | return data; 85 | } 86 | 87 | /** 88 | * @return the data format ({@link AudioFormat}) 89 | */ 90 | public int getFormat() { 91 | return format; 92 | } 93 | 94 | /** 95 | * @return the timestamp 96 | */ 97 | public long getTimestamp() { 98 | return timestamp; 99 | } 100 | 101 | /** 102 | * @return {@code true} if the data represents compressed audio, 103 | * {@code false} otherwise 104 | */ 105 | public boolean isCompressed() { 106 | return format == FORMAT_COMPRESSED; 107 | } 108 | 109 | /** 110 | * @return {@code true} if the data contains audio configuration information, 111 | * {@code false} otherwise 112 | */ 113 | public boolean isConfig() { 114 | return type == TYPE_AUDIO_CONFIG; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 33 | 34 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/UDPAudioPacketizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network; 23 | 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | import java.io.IOException; 27 | import java.net.DatagramPacket; 28 | import java.net.DatagramSocket; 29 | import java.net.InetAddress; 30 | import java.net.SocketException; 31 | 32 | /** 33 | * Defines the RTP packetizer to stream AAC audio using the UDP protocol. 34 | */ 35 | public class UDPAudioPacketizer extends RTPAudioPacketizer { 36 | 37 | protected static final int RTP_PACKET_SIZE = 1400; 38 | 39 | private final DatagramSocket mRTPSocket; // The socket to send RTP packets to 40 | private final DatagramSocket mRTCPSocket; // The socket to send RTCP packets to 41 | private final DatagramPacket mPacket; // The UDP packet to send 42 | private final int mRTPPort; // The client port used by the RTP protocol 43 | private final int mRTCPPort; // The client port used by the RTCP protocol 44 | 45 | /** 46 | * Creates a new UDPAudioPacketizer object. 47 | * 48 | * @param connection the StreamConnection that owns the packetizer 49 | * @param host the host to send packets to 50 | * @param rtpPort the UDP port to send RTP packets to 51 | * @param rtcpPort the UDP port to send RTCP packets to 52 | * @param clock the clock rate in Hz 53 | * @param seq the sequence number of the first packet 54 | */ 55 | public UDPAudioPacketizer(@NotNull StreamConnection connection, 56 | InetAddress host, int rtpPort, int rtcpPort, 57 | int clock, int seq) 58 | throws SocketException { 59 | super(connection, clock, RTP_PACKET_SIZE, seq); 60 | mRTPSocket = new DatagramSocket(); 61 | mRTCPSocket = new DatagramSocket(mRTPSocket.getLocalPort() + 1); 62 | mPacket = new DatagramPacket(new byte[RTP_PACKET_SIZE], RTP_PACKET_SIZE); 63 | mPacket.setAddress(host); 64 | mRTPPort = rtpPort; 65 | mRTCPPort = rtcpPort; 66 | } 67 | 68 | @Override 69 | protected void rtpSend(byte[] data, int length) throws IOException { 70 | mPacket.setData(data, 0, length); 71 | mPacket.setPort(mRTPPort); 72 | mRTPSocket.send(mPacket); 73 | } 74 | 75 | @Override 76 | protected void rtcpSend(byte[] data, int length) throws IOException { 77 | mPacket.setData(data, 0, length); 78 | mPacket.setPort(mRTCPPort); 79 | mRTCPSocket.send(mPacket); 80 | } 81 | 82 | @Override 83 | public void close() { 84 | super.close(); 85 | mRTPSocket.close(); 86 | mRTCPSocket.close(); 87 | } 88 | 89 | /** 90 | * @return the local port used by the RTP protocol 91 | */ 92 | public int getRTPLocalPort() { 93 | return mRTPSocket.getLocalPort(); 94 | } 95 | 96 | /** 97 | * @return the local port used by the RTCP protocol 98 | */ 99 | public int getRTCPLocalPort() { 100 | return mRTCPSocket.getLocalPort(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/UDPVideoPacketizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network; 23 | 24 | import org.jetbrains.annotations.NotNull; 25 | 26 | import java.io.IOException; 27 | import java.net.DatagramPacket; 28 | import java.net.DatagramSocket; 29 | import java.net.InetAddress; 30 | import java.net.SocketException; 31 | 32 | /** 33 | * Defines the RTP packetizer to stream AVC video slices using the UDP protocol. 34 | */ 35 | public class UDPVideoPacketizer extends RTPVideoPacketizer { 36 | 37 | protected static final int RTP_PACKET_SIZE = 1400; 38 | 39 | private final DatagramSocket mRTPSocket; // The socket to send RTP packets to 40 | private final DatagramSocket mRTCPSocket; // The socket to send RTCP packets to 41 | private final DatagramPacket mPacket; // The UDP packet to send 42 | private final int mRTPPort; // The client port used by the RTP protocol 43 | private final int mRTCPPort; // The client port used by the RTCP protocol 44 | 45 | /** 46 | * Creates a new UDPVideoPacketizer object. 47 | * 48 | * @param connection the StreamConnection that owns the packetizer 49 | * @param host the host to send packets to 50 | * @param rtpPort the UDP port to send RTP packets to 51 | * @param rtcpPort the UDP port to send RTCP packets to 52 | * @param clock the clock rate in Hz 53 | * @param seq the sequence number of the first packet 54 | */ 55 | public UDPVideoPacketizer(@NotNull StreamConnection connection, 56 | InetAddress host, int rtpPort, int rtcpPort, 57 | int clock, int seq) 58 | throws SocketException { 59 | super(connection, clock, RTP_PACKET_SIZE, seq); 60 | mRTPSocket = new DatagramSocket(); 61 | mRTCPSocket = new DatagramSocket(mRTPSocket.getLocalPort() + 1); 62 | mPacket = new DatagramPacket(new byte[RTP_PACKET_SIZE], RTP_PACKET_SIZE); 63 | mPacket.setAddress(host); 64 | mRTPPort = rtpPort; 65 | mRTCPPort = rtcpPort; 66 | } 67 | 68 | @Override 69 | protected void rtpSend(byte[] data, int length) throws IOException { 70 | mPacket.setData(data, 0, length); 71 | mPacket.setPort(mRTPPort); 72 | mRTPSocket.send(mPacket); 73 | } 74 | 75 | @Override 76 | protected void rtcpSend(byte[] data, int length) throws IOException { 77 | mPacket.setData(data, 0, length); 78 | mPacket.setPort(mRTCPPort); 79 | mRTCPSocket.send(mPacket); 80 | } 81 | 82 | @Override 83 | public void close() { 84 | super.close(); 85 | mRTPSocket.close(); 86 | mRTCPSocket.close(); 87 | } 88 | 89 | /** 90 | * @return the local port used by the RTP protocol 91 | */ 92 | public int getRTPLocalPort() { 93 | return mRTPSocket.getLocalPort(); 94 | } 95 | 96 | /** 97 | * @return the local port used by the RTCP protocol 98 | */ 99 | public int getRTCPLocalPort() { 100 | return mRTCPSocket.getLocalPort(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/common/Image.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.common; 23 | 24 | import android.graphics.Rect; 25 | import android.graphics.YuvImage; 26 | 27 | import java.io.OutputStream; 28 | 29 | /** 30 | * Common utilities to handle images. 31 | */ 32 | public final class Image { 33 | 34 | /** 35 | * Hidden constructor, the class cannot be instantiated. 36 | */ 37 | private Image() { 38 | } 39 | 40 | /** 41 | * Converts a NV12 image to a YUV420SemiPlanar image.
42 | * We assume that there's no padding (stride = {@code width}) and that the {@code data} 43 | * buffer contains exactly one image, i.e. its size equals {@code width * height * 3 / 2}. 44 | * 45 | * @param data the image data 46 | * @param width the image width 47 | * @param height the image height 48 | */ 49 | public static void convertNV12ToYUV420SemiPlanar(byte[] data, int width, int height) { 50 | for (int i = width * height; i < data.length; ) { 51 | byte tmp = data[i]; 52 | data[i] = data[++i]; 53 | data[i++] = tmp; 54 | } 55 | } 56 | 57 | /** 58 | * Converts a NV12 image to a YUV420Planar image.
59 | * We assume that there's no padding (stride = {@code width}) and that the {@code data} 60 | * buffer contains exactly one image, i.e. its size equals {@code width * height * 3 / 2}. 61 | * 62 | * @param data the image data 63 | * @param width the image width 64 | * @param height the image height 65 | */ 66 | public static void convertNV12ToYUV420Planar(byte[] data, int width, int height) { 67 | 68 | final int c_stride = width / 2; 69 | final int c_size = c_stride * height / 2; 70 | final int cr_offset = width * height; 71 | 72 | byte[] tmp = new byte[c_size * 2]; 73 | for (int src = cr_offset, cr_dst = 0, cb_dst = c_size; src < data.length; src++) { 74 | if (src % 2 == 0) { 75 | tmp[cb_dst++] = data[src]; 76 | } else { 77 | tmp[cr_dst++] = data[src]; 78 | } 79 | } 80 | System.arraycopy(tmp, 0, data, cr_offset, c_size * 2); 81 | } 82 | 83 | /** 84 | * Compress an YUV image to a JPEG image. 85 | * Only ImageFormat.NV21 and ImageFormat.YUY2 are supported for now. 86 | * 87 | * @param data the YUV data 88 | * @param width the width of the image 89 | * @param height the height of the image 90 | * @param format the YUV data format as defined in ImageFormat 91 | * @param quality hint to the compressor, 0-100. 92 | * 0 meaning compress for small size, 100 meaning compress for max quality. 93 | * @param out OutputStream to write the compressed data. 94 | */ 95 | public static void compressToJpeg(byte[] data, int width, int height, int format, 96 | int quality, OutputStream out) { 97 | YuvImage img = new YuvImage(data, format, width, height, null); 98 | img.compressToJpeg(new Rect(0, 0, width - 1, height - 1), quality, out); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Angelcam/API/AckMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Angelcam.API; 23 | 24 | import java.io.ByteArrayOutputStream; 25 | import java.io.IOException; 26 | import java.io.InvalidObjectException; 27 | 28 | /** 29 | * Defines the Arrow protocol ACK message.
30 | * The message is a response to another Control Protocol message.
31 | * It might be sent by both client and server.
32 | * The message consists of 32bit unsigned integer used as an error code. 33 | */ 34 | public class AckMessage extends ControlMessage { 35 | 36 | // OK 37 | public final static int ERROR_NO_ERROR = 0x00000000; 38 | // Unsupported version of the Arrow protocol 39 | public final static int ERROR_UNSUPPORTED_PROTOCOL_VERSION = 0x00000001; 40 | // Access denied (client is not registered) 41 | public final static int ERROR_UNAUTHORIZED = 0x00000002; 42 | // Cannot connect to a given service 43 | public final static int ERROR_CONNECTION_ERROR = 0x00000003; 44 | // unsupported method 45 | public final static int ERROR_UNSUPPORTED_METHOD = 0x00000004; 46 | // internal server error 47 | public final static int ERROR_INTERNAL_SERVER_ERROR = 0xffffffff; 48 | 49 | private final int mErrorCode; // Error code 50 | 51 | /** 52 | * Creates a new AckMessage object. 53 | * 54 | * @param messageID message ID, used for request/response pairing 55 | * @param errorCode error code 56 | */ 57 | public AckMessage(int messageID, int errorCode) { 58 | super(messageID, TYPE_ACK); 59 | mErrorCode = errorCode; 60 | } 61 | 62 | /** 63 | * Wraps an AckMessage object around a ControlMessage object. 64 | * 65 | * @param message the original ControlMessage object 66 | * @throws InvalidObjectException if the {@code message} doesn't match 67 | */ 68 | public AckMessage(ControlMessage message) throws InvalidObjectException { 69 | super(message.mMessageID, message.mType); 70 | if (mType != TYPE_ACK) 71 | throw new InvalidObjectException("the message is not an ACK message"); 72 | if (message.mData == null) 73 | throw new InvalidObjectException("the message has no data"); 74 | if (message.mData.length != 4) 75 | throw new InvalidObjectException("the message contains invalid data"); 76 | mErrorCode = ((message.mData[0] & 0xff) << 24) | ((message.mData[1] & 0xff) << 16) | 77 | ((message.mData[2] & 0xff) << 8) | (message.mData[3] & 0xff); 78 | } 79 | 80 | @Override 81 | public byte[] toByteArray() throws IOException { 82 | 83 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 84 | 85 | // error_code - 32bit unsigned integer 86 | buffer.write(mErrorCode >> 24); 87 | buffer.write(mErrorCode >> 16); 88 | buffer.write(mErrorCode >> 8); 89 | buffer.write(mErrorCode); 90 | 91 | mData = buffer.toByteArray(); 92 | return super.toByteArray(); 93 | } 94 | 95 | /** 96 | * @return the error code 97 | */ 98 | public int getErrorCode() { 99 | return mErrorCode; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/Mangocam/API/ResetCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network.Mangocam.API; 23 | 24 | import android.content.Context; 25 | import android.util.JsonReader; 26 | 27 | import org.jetbrains.annotations.NotNull; 28 | import org.json.JSONException; 29 | 30 | import java.io.IOException; 31 | import java.io.StringReader; 32 | 33 | /** 34 | * Defines the Mangocam API RESET command. 35 | */ 36 | public class ResetCommand implements MangocamCommand { 37 | 38 | private final Context mContext; 39 | private String mErrorMessage = ""; 40 | private int mErrorCode = 0; 41 | 42 | /** 43 | * Creates a new ResetCommand object. 44 | * 45 | * @param context the context where the object is used 46 | */ 47 | public ResetCommand(@NotNull Context context) { 48 | mContext = context; 49 | } 50 | 51 | @Override 52 | public String get() throws JSONException { 53 | return "RESET\r\n"; 54 | } 55 | 56 | @Override 57 | public void parse(String command) throws IOException, IllegalStateException { 58 | if (command.startsWith("OK ")) { 59 | String json = command.substring(3); 60 | JsonReader jr = new JsonReader(new StringReader(json)); 61 | jr.beginObject(); 62 | while (jr.hasNext()) { 63 | switch (jr.nextName()) { 64 | case "cmd": 65 | String cmd = jr.nextString(); 66 | if (!cmd.equals("RESET")) 67 | throw new IllegalStateException("wrong cmd field"); 68 | break; 69 | default: 70 | jr.skipValue(); 71 | } 72 | } 73 | jr.endObject(); 74 | } else if (command.startsWith("ERR ")) { 75 | String json = command.substring(4); 76 | JsonReader jr = new JsonReader(new StringReader(json)); 77 | jr.beginObject(); 78 | while (jr.hasNext()) { 79 | switch (jr.nextName()) { 80 | case "cmd": 81 | String cmd = jr.nextString(); 82 | if (!cmd.equals("RESET")) 83 | throw new IllegalStateException("wrong cmd field"); 84 | break; 85 | case "message": 86 | mErrorMessage = jr.nextString(); 87 | break; 88 | case "code": 89 | mErrorCode = jr.nextInt(); 90 | break; 91 | default: 92 | jr.skipValue(); 93 | } 94 | } 95 | jr.endObject(); 96 | } else { 97 | throw new IllegalStateException("wrong response"); 98 | } 99 | } 100 | 101 | /** 102 | * @return the error message from the negative response 103 | */ 104 | public String getErrorMessge() { 105 | return mErrorMessage; 106 | } 107 | 108 | /** 109 | * @return the error code from the negative response 110 | */ 111 | public int getErrorCode() { 112 | return mErrorCode; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/res/values/array.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | "64" 26 | "128" 27 | "256" 28 | "384" 29 | "512" 30 | "768" 31 | "1024" 32 | "1536" 33 | "2048" 34 | "3072" 35 | "4096" 36 | "6144" 37 | "8192" 38 | 39 | 40 | "10" 41 | "15" 42 | "20" 43 | "25" 44 | "30" 45 | 46 | 47 | "1" 48 | "2" 49 | "5" 50 | "10" 51 | 52 | 53 | "32" 54 | "64" 55 | "128" 56 | "256" 57 | 58 | 59 | "-6" 60 | "0" 61 | "6" 62 | "12" 63 | "18" 64 | "24" 65 | 66 | 67 | "-6" 68 | "0" 69 | "+6" 70 | "+12" 71 | "+18" 72 | "+24" 73 | 74 | 75 | "25" 76 | "50" 77 | "75" 78 | "100" 79 | 80 | 81 | "1" 82 | "2" 83 | "5" 84 | "10" 85 | "15" 86 | "20" 87 | "25" 88 | "30" 89 | 90 | 91 | "No-IP (www.noip.com)" 92 | "Dynu (www.dynu.com)" 93 | "DNSdynamic (www.dnsdynamic.org)" 94 | "FreeDNS (freedns.afraid.org)" 95 | "Duck DNS (www.duckdns.org/)" 96 | 97 | 98 | "noip" 99 | "dynu" 100 | "dnsdynamic" 101 | "freedns" 102 | "duckdns" 103 | 104 | 105 | "WiFi only" 106 | "Mobile only" 107 | "WiFi and mobile" 108 | 109 | 110 | "wifi" 111 | "mobile" 112 | "all" 113 | 114 | -------------------------------------------------------------------------------- /app/src/main/java/com/spynet/camera/network/TCPListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of spyNet Camera, the Android IP camera 3 | * 4 | * Copyright (C) 2016-2017 Paolo Dematteis 5 | * 6 | * spyNet Camera is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * spyNet Camera is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | * 19 | * Paolo Dematteis - spynet314@gmail.com 20 | */ 21 | 22 | package com.spynet.camera.network; 23 | 24 | import android.util.Log; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | import java.io.Closeable; 29 | import java.io.IOException; 30 | import java.net.ServerSocket; 31 | import java.net.Socket; 32 | import java.net.SocketException; 33 | 34 | /** 35 | * Defines a generic TCP listener that runs in its own thread. 36 | */ 37 | public class TCPListener implements Closeable { 38 | 39 | protected final String TAG = getClass().getSimpleName(); 40 | 41 | private final ServerSocket mSocket; // The listening socket 42 | private final ListenerCallback mCallback; // The callback to notify the client 43 | private final Thread mThread; // The listening thread 44 | 45 | /** 46 | * Defines the interface that the client has to implement to receive notifications 47 | * about incoming connections. 48 | */ 49 | public interface ListenerCallback { 50 | /** 51 | * Notifies a new incoming connection. 52 | * 53 | * @param listener the TCPListener that accepted the connection 54 | * @param socket the socket to handle the connection 55 | * @throws IOException if an error occurs while handling the new connection 56 | */ 57 | void onNewConnection(TCPListener listener, Socket socket) throws IOException; 58 | } 59 | 60 | /** 61 | * Creates a new TCPListener object. 62 | * 63 | * @param port the server port 64 | * @param callback the callback implemented by the client 65 | * @throws IOException if an error occurs while creating the socket 66 | */ 67 | public TCPListener(int port, @NotNull ListenerCallback callback) throws IOException { 68 | mSocket = new ServerSocket(port); 69 | mCallback = callback; 70 | mThread = new Thread(new Runnable() { 71 | @Override 72 | public void run() { 73 | listen(); 74 | } 75 | }); 76 | mThread.start(); 77 | } 78 | 79 | /** 80 | * Closes the listener. 81 | */ 82 | @Override 83 | public void close() { 84 | try { 85 | mThread.interrupt(); 86 | mSocket.close(); 87 | } catch (Exception e) { 88 | Log.e(TAG, "unexpected exception while closing the socket", e); 89 | } 90 | } 91 | 92 | /** 93 | * Listen for incoming connections and notify the client. 94 | */ 95 | private void listen() { 96 | Log.d(TAG, "listener started"); 97 | try { 98 | while (true) { 99 | try { 100 | Log.v(TAG, "listening for a new connection"); 101 | Socket socket = mSocket.accept(); 102 | Log.v(TAG, "new connection from " + socket.toString()); 103 | mCallback.onNewConnection(this, socket); 104 | } catch (SocketException e) { 105 | Log.v(TAG, "socket closed"); 106 | break; 107 | } catch (Exception e) { 108 | Log.e(TAG, "unexpected exception while listening, continue", e); 109 | } 110 | } 111 | } finally { 112 | close(); 113 | Log.d(TAG, "listener stopped"); 114 | } 115 | } 116 | } 117 | --------------------------------------------------------------------------------