Compare commits
No commits in common. "o" and "master" have entirely different histories.
|
@ -30,13 +30,13 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'com.google.android.material:material:1.9.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
implementation 'androidx.preference:preference:1.2.0'
|
implementation 'androidx.preference:preference:1.2.1'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
|
|
||||||
implementation 'com.github.pedroSG94.rtmp-rtsp-stream-client-java:rtplibrary:2.2.6'
|
implementation 'com.github.pedroSG94.rtmp-rtsp-stream-client-java:rtplibrary:a813c206292cea0767d9cb091f14c87ca9afdc9e'
|
||||||
}
|
}
|
|
@ -27,10 +27,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<!--
|
|
||||||
android:launchMode="singleInstance"
|
|
||||||
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" >
|
|
||||||
-->
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
@ -49,4 +45,4 @@
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 31 KiB |
|
@ -18,7 +18,6 @@ import android.util.Log;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -63,30 +62,25 @@ public class MainActivity extends AppCompatActivity {
|
||||||
Log.d(TAG, "activity created");
|
Log.d(TAG, "activity created");
|
||||||
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
setContentView(R.layout.main_activity);
|
setContentView(R.layout.main_activity);
|
||||||
Map<String, String> permissionsToRequest = Collections.emptyMap();
|
Map<String, String> permissionsToRequest = new HashMap<>();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
permissionsToRequest = new HashMap<>(Map.of("android.permission.POST_NOTIFICATIONS",
|
permissionsToRequest.putAll(Map.of("android.permission.POST_NOTIFICATIONS",
|
||||||
getString(R.string.permission_denied_post_notifications)));
|
getString(R.string.permission_denied_post_notifications)));
|
||||||
if (checkSelfPermission("android.permission.POST_NOTIFICATIONS") != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
|
|
||||||
requestPermissions(new String[]{"android.permission.POST_NOTIFICATIONS"}, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
|
else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
|
||||||
permissionsToRequest = new HashMap<>(Map.of("android.permission.RECORD_AUDIO",
|
permissionsToRequest.putAll(Map.of("android.permission.RECORD_AUDIO",
|
||||||
getString(R.string.permission_denied_record_audio)));
|
getString(R.string.permission_denied_record_audio)));
|
||||||
}
|
}
|
||||||
permissionsToRequest.entrySet().removeIf(i -> checkSelfPermission(i.getKey()) == PackageManager.PERMISSION_GRANTED);
|
permissionsToRequest.entrySet().removeIf(i -> checkSelfPermission(i.getKey()) == PackageManager.PERMISSION_GRANTED);
|
||||||
if (!permissionsToRequest.isEmpty()) {
|
if (!permissionsToRequest.isEmpty()) {
|
||||||
Log.d(TAG, String.format("requesting permissions %s", String.join(" + ", permissionsToRequest.keySet().toArray(new String[0]))));
|
Log.d(TAG, String.format("requesting permissions %s", String.join(" + ", permissionsToRequest.keySet().toArray(new String[0]))));
|
||||||
Map<String, String> finalPermissionsToRequest = permissionsToRequest;
|
|
||||||
ActivityResultLauncher<String[]> permissionReq = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), (result) -> {
|
ActivityResultLauncher<String[]> permissionReq = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), (result) -> {
|
||||||
result.forEach((perm, granted) -> {
|
result.forEach((perm, granted) -> {
|
||||||
if (!granted) {
|
if (!granted) {
|
||||||
Log.d(TAG, String.format("permission denied: %s", perm));
|
Log.d(TAG, String.format("permission denied: %s", perm));
|
||||||
(new AlertDialog.Builder(this))
|
(new AlertDialog.Builder(this))
|
||||||
.setTitle(getText(R.string.error_title))
|
.setTitle(getText(R.string.error_title))
|
||||||
.setMessage(finalPermissionsToRequest.get(perm))
|
.setMessage(permissionsToRequest.get(perm))
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(getString(R.string.button_ok), (dialog, id) -> {})
|
.setPositiveButton(getString(R.string.button_ok), (dialog, id) -> {})
|
||||||
.create()
|
.create()
|
||||||
|
@ -125,7 +119,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.d(TAG, "button start");
|
Log.d(TAG, "button start");
|
||||||
MainActivity.this.screenCapService.createDisplay();
|
MainActivity.this.screenCapService.createDisplay(prefs.getString("server", "").toLowerCase().startsWith("rtsp"));
|
||||||
MainActivity.this.screenCapReq.launch(MainActivity.this.screenCapService.getScreenCapDisplay().sendIntent());
|
MainActivity.this.screenCapReq.launch(MainActivity.this.screenCapService.getScreenCapDisplay().sendIntent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,10 @@ import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.pedro.encoder.utils.CodecUtil;
|
import com.pedro.encoder.utils.CodecUtil;
|
||||||
import com.pedro.rtmp.utils.ConnectCheckerRtmp;
|
import com.pedro.rtmp.utils.ConnectCheckerRtmp;
|
||||||
|
import com.pedro.rtplibrary.base.DisplayBase;
|
||||||
import com.pedro.rtplibrary.rtmp.RtmpDisplay;
|
import com.pedro.rtplibrary.rtmp.RtmpDisplay;
|
||||||
|
import com.pedro.rtplibrary.rtsp.RtspDisplay;
|
||||||
|
import com.pedro.rtsp.utils.ConnectCheckerRtsp;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -49,9 +52,9 @@ public class ScreenCapService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IBinder mBinder = new MBinder();
|
private final IBinder mBinder = new MBinder();
|
||||||
private RtmpDisplay screenCapDisplay;
|
private DisplayBase screenCapDisplay;
|
||||||
|
|
||||||
public RtmpDisplay getScreenCapDisplay() {
|
public DisplayBase getScreenCapDisplay() {
|
||||||
return this.screenCapDisplay;
|
return this.screenCapDisplay;
|
||||||
}
|
}
|
||||||
private String infoDisplayText = "";
|
private String infoDisplayText = "";
|
||||||
|
@ -75,46 +78,94 @@ public class ScreenCapService extends Service {
|
||||||
Log.d(TAG, "service destroyed");
|
Log.d(TAG, "service destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createDisplay() {
|
protected void createDisplay(boolean rtsp) {
|
||||||
boolean use_gl = prefs.getBoolean("use_gl", true);
|
boolean use_gl = prefs.getBoolean("use_gl", true);
|
||||||
Log.d(TAG, String.format("creating display use_gl=%b", use_gl));
|
Log.d(TAG, String.format("creating display use_gl=%b", use_gl));
|
||||||
this.screenCapDisplay = new RtmpDisplay(this, use_gl, new ConnectCheckerRtmp() {
|
if (rtsp) {
|
||||||
public void onAuthErrorRtmp() {
|
this.screenCapDisplay = new RtspDisplay(this, use_gl, new ConnectCheckerRtsp() {
|
||||||
String text = getString(R.string.status_auth_error);
|
@Override
|
||||||
showToast(text);
|
public void onConnectionStartedRtsp(@NonNull String rtspUrl) {
|
||||||
setInfoDisplay(text);
|
setInfoDisplay(getString(R.string.status_connecting, rtspUrl));
|
||||||
ScreenCapService.this.stop();
|
ScreenCapService.this.connectionStateChange(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAuthSuccessRtmp() {
|
@Override
|
||||||
setInfoDisplay(getString(R.string.status_auth_success));
|
public void onConnectionSuccessRtsp() {
|
||||||
}
|
setInfoDisplay(getString(R.string.status_connected));
|
||||||
|
}
|
||||||
|
|
||||||
public void onConnectionFailedRtmp(@NonNull String reason) {
|
@Override
|
||||||
String text = getString(R.string.status_connection_failed_format, reason);
|
public void onConnectionFailedRtsp(@NonNull String reason) {
|
||||||
showToast(text);
|
String text = getString(R.string.status_connection_failed_format, reason);
|
||||||
setInfoDisplay(text);
|
showToast(text);
|
||||||
ScreenCapService.this.stop();
|
setInfoDisplay(text);
|
||||||
}
|
ScreenCapService.this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
public void onConnectionStartedRtmp(@NonNull String rtmpUrl) {
|
@Override
|
||||||
setInfoDisplay(getString(R.string.status_connecting, rtmpUrl));
|
public void onNewBitrateRtsp(long bitrate) {
|
||||||
ScreenCapService.this.connectionStateChange(true);
|
setInfoDisplay(getString(R.string.status_bitrate_format, bitrate));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onConnectionSuccessRtmp() {
|
@Override
|
||||||
setInfoDisplay(getString(R.string.status_connected));
|
public void onDisconnectRtsp() {
|
||||||
}
|
setInfoDisplay(getString(R.string.status_disconnected));
|
||||||
|
ScreenCapService.this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
public void onDisconnectRtmp() {
|
@Override
|
||||||
setInfoDisplay(getString(R.string.status_disconnected));
|
public void onAuthErrorRtsp() {
|
||||||
ScreenCapService.this.stop();
|
String text = getString(R.string.status_auth_error);
|
||||||
}
|
showToast(text);
|
||||||
|
setInfoDisplay(text);
|
||||||
|
ScreenCapService.this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
public void onNewBitrateRtmp(long bitrate) {
|
@Override
|
||||||
setInfoDisplay(getString(R.string.status_bitrate_format, bitrate));
|
public void onAuthSuccessRtsp() {
|
||||||
}
|
setInfoDisplay(getString(R.string.status_auth_success));
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.screenCapDisplay = new RtmpDisplay(this, use_gl, new ConnectCheckerRtmp() {
|
||||||
|
public void onAuthErrorRtmp() {
|
||||||
|
String text = getString(R.string.status_auth_error);
|
||||||
|
showToast(text);
|
||||||
|
setInfoDisplay(text);
|
||||||
|
ScreenCapService.this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAuthSuccessRtmp() {
|
||||||
|
setInfoDisplay(getString(R.string.status_auth_success));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onConnectionFailedRtmp(@NonNull String reason) {
|
||||||
|
String text = getString(R.string.status_connection_failed_format, reason);
|
||||||
|
showToast(text);
|
||||||
|
setInfoDisplay(text);
|
||||||
|
ScreenCapService.this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onConnectionStartedRtmp(@NonNull String rtmpUrl) {
|
||||||
|
setInfoDisplay(getString(R.string.status_connecting, rtmpUrl));
|
||||||
|
ScreenCapService.this.connectionStateChange(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onConnectionSuccessRtmp() {
|
||||||
|
setInfoDisplay(getString(R.string.status_connected));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDisconnectRtmp() {
|
||||||
|
setInfoDisplay(getString(R.string.status_disconnected));
|
||||||
|
ScreenCapService.this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onNewBitrateRtmp(long bitrate) {
|
||||||
|
setInfoDisplay(getString(R.string.status_bitrate_format, bitrate));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startCapture(String server) {
|
protected void startCapture(String server) {
|
||||||
|
@ -136,10 +187,17 @@ public class ScreenCapService extends Service {
|
||||||
|
|
||||||
screenCapDisplay.setForce(prefs.getBoolean("software_video_encoder", false) ? CodecUtil.Force.SOFTWARE : CodecUtil.Force.FIRST_COMPATIBLE_FOUND,
|
screenCapDisplay.setForce(prefs.getBoolean("software_video_encoder", false) ? CodecUtil.Force.SOFTWARE : CodecUtil.Force.FIRST_COMPATIBLE_FOUND,
|
||||||
prefs.getBoolean("software_audio_encoder", false) ? CodecUtil.Force.SOFTWARE : CodecUtil.Force.FIRST_COMPATIBLE_FOUND);
|
prefs.getBoolean("software_audio_encoder", false) ? CodecUtil.Force.SOFTWARE : CodecUtil.Force.FIRST_COMPATIBLE_FOUND);
|
||||||
screenCapDisplay.setWriteChunkSize(prefs.getInt("write_chunk_size_int", 1024));
|
if (screenCapDisplay instanceof RtmpDisplay d) {
|
||||||
|
d.setWriteChunkSize(prefs.getInt("write_chunk_size_int", 1024));
|
||||||
|
}
|
||||||
|
if (screenCapDisplay instanceof RtmpDisplay d) {
|
||||||
|
d.setVideoCodec(prefs.getBoolean("enable_h265", false) ? com.pedro.rtmp.rtmp.VideoCodec.H265 : com.pedro.rtmp.rtmp.VideoCodec.H264);
|
||||||
|
}
|
||||||
|
else if (screenCapDisplay instanceof RtspDisplay d) {
|
||||||
|
d.setVideoCodec(prefs.getBoolean("enable_h265", false) ? com.pedro.rtsp.rtsp.VideoCodec.H265 : com.pedro.rtsp.rtsp.VideoCodec.H264);
|
||||||
|
}
|
||||||
screenCapDisplay.setReTries(prefs.getInt("retries_int", 0));
|
screenCapDisplay.setReTries(prefs.getInt("retries_int", 0));
|
||||||
screenCapDisplay.resizeCache(prefs.getInt("cache_size_int", 120));
|
screenCapDisplay.setLogs(prefs.getBoolean("enable_lib_logs", true));
|
||||||
screenCapDisplay.setLogs(prefs.getBoolean("enable_droidcast_logs", false));
|
|
||||||
if (prefs.getBoolean("use_gl", true) && prefs.getBoolean("use_force_render", true)) {
|
if (prefs.getBoolean("use_gl", true) && prefs.getBoolean("use_force_render", true)) {
|
||||||
screenCapDisplay.getGlInterface().setForceRender(true);
|
screenCapDisplay.getGlInterface().setForceRender(true);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +220,7 @@ public class ScreenCapService extends Service {
|
||||||
}
|
}
|
||||||
Log.d(TAG, String.format("capture width %d height %d", video_width, video_height));
|
Log.d(TAG, String.format("capture width %d height %d", video_width, video_height));
|
||||||
if (this.screenCapDisplay.prepareInternalAudio(Integer.parseInt(prefs.getString("audio_bitrate", "131072")), 48000, prefs.getBoolean("stereo_audio", true), false, false) &&
|
if (this.screenCapDisplay.prepareInternalAudio(Integer.parseInt(prefs.getString("audio_bitrate", "131072")), 48000, prefs.getBoolean("stereo_audio", true), false, false) &&
|
||||||
this.screenCapDisplay.prepareVideo(video_width, video_height, Integer.parseInt(prefs.getString("fps", "30")), Integer.parseInt(prefs.getString("video_bitrate", "10485760")), 0, 320, -1, -1, 2)) {
|
this.screenCapDisplay.prepareVideo(video_width, video_height, Integer.parseInt(prefs.getString("fps", "30")), Integer.parseInt(prefs.getString("video_bitrate", "10485760")), 0, 320)) {
|
||||||
this.screenCapDisplay.startStream(server);
|
this.screenCapDisplay.startStream(server);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -24,6 +24,12 @@ public class SettingsActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSupportNavigateUp() {
|
||||||
|
onBackPressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static class SettingsFragment extends PreferenceFragmentCompat {
|
public static class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
|
|
@ -1,30 +1,14 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="108"
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
android:tint="#FFFFFF"
|
||||||
<aapt:attr name="android:fillColor">
|
android:autoMirrored="true">
|
||||||
<gradient
|
<group android:scaleX="1.9"
|
||||||
android:endX="85.84757"
|
android:scaleY="1.9"
|
||||||
android:endY="92.4963"
|
android:translateX="30.6"
|
||||||
android:startX="42.9492"
|
android:translateY="30.6">
|
||||||
android:startY="49.59793"
|
<path android:fillColor="@android:color/white" android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11z"/>
|
||||||
android:type="linear">
|
</group>
|
||||||
<item
|
</vector>
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
|
||||||
|
|
|
@ -1,170 +1,26 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="108">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#3DDC84"
|
android:pathData="M0,0h108v108h-108z">
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
<aapt:attr name="android:fillColor">
|
||||||
<path
|
<gradient
|
||||||
android:fillColor="#00000000"
|
android:endX="90.0"
|
||||||
android:pathData="M9,0L9,108"
|
android:endY="90.0"
|
||||||
android:strokeWidth="0.8"
|
android:startX="45.0"
|
||||||
android:strokeColor="#33FFFFFF" />
|
android:startY="45.0"
|
||||||
<path
|
android:type="linear">
|
||||||
android:fillColor="#00000000"
|
<item
|
||||||
android:pathData="M19,0L19,108"
|
android:color="@color/purple_700"
|
||||||
android:strokeWidth="0.8"
|
android:offset="0.0" />
|
||||||
android:strokeColor="#33FFFFFF" />
|
<item
|
||||||
<path
|
android:color="@color/purple_500"
|
||||||
android:fillColor="#00000000"
|
android:offset="1.0" />
|
||||||
android:pathData="M29,0L29,108"
|
</gradient>
|
||||||
android:strokeWidth="0.8"
|
</aapt:attr>
|
||||||
android:strokeColor="#33FFFFFF" />
|
</path>
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,0L39,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,0L49,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,0L59,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,0L69,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,0L79,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M89,0L89,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M99,0L99,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,9L108,9"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,19L108,19"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,29L108,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 10 KiB |
|
@ -16,7 +16,6 @@
|
||||||
<string name="network_header">网络设置</string>
|
<string name="network_header">网络设置</string>
|
||||||
<string name="video_bitrate_title">视频比特率</string>
|
<string name="video_bitrate_title">视频比特率</string>
|
||||||
<string name="audio_bitrate_title">音频比特率</string>
|
<string name="audio_bitrate_title">音频比特率</string>
|
||||||
<string name="hint_rtmp">rtmp://</string>
|
|
||||||
<string name="start_button">开始</string>
|
<string name="start_button">开始</string>
|
||||||
<string name="stop_button">停止</string>
|
<string name="stop_button">停止</string>
|
||||||
<string name="settings_button">设置</string>
|
<string name="settings_button">设置</string>
|
||||||
|
@ -35,4 +34,8 @@
|
||||||
<string name="permission_denied_post_notifications">通知权限被禁止</string>
|
<string name="permission_denied_post_notifications">通知权限被禁止</string>
|
||||||
<string name="permission_denied_record_audio">录音权限被禁止,在安卓12-上内录音频时这项权限是必需的</string>
|
<string name="permission_denied_record_audio">录音权限被禁止,在安卓12-上内录音频时这项权限是必需的</string>
|
||||||
<string name="button_ok">好</string>
|
<string name="button_ok">好</string>
|
||||||
|
<string name="misc_header">杂项</string>
|
||||||
|
<string name="enable_lib_logs_title">开启库日志</string>
|
||||||
|
<string name="enable_h265_title">开启 H.265</string>
|
||||||
|
<string name="h265_warning">并非所有服务器均支持 h265 推流</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<string name="video_bitrate_title">Video Bitrate (bps)</string>
|
<string name="video_bitrate_title">Video Bitrate (bps)</string>
|
||||||
<string name="audio_bitrate_title">Audio Bitrate</string>
|
<string name="audio_bitrate_title">Audio Bitrate</string>
|
||||||
|
|
||||||
<string name="hint_rtmp">rtmp://</string>
|
|
||||||
<string name="start_button">Start</string>
|
<string name="start_button">Start</string>
|
||||||
<string name="stop_button">Stop</string>
|
<string name="stop_button">Stop</string>
|
||||||
<string name="settings_button">Settings</string>
|
<string name="settings_button">Settings</string>
|
||||||
|
@ -39,4 +38,8 @@
|
||||||
<string name="permission_denied_record_audio">Audio recording permission denied, on Android 12- this is required for internal audio recording</string>
|
<string name="permission_denied_record_audio">Audio recording permission denied, on Android 12- this is required for internal audio recording</string>
|
||||||
|
|
||||||
<string name="button_ok">OK</string>
|
<string name="button_ok">OK</string>
|
||||||
|
<string name="misc_header">Misc</string>
|
||||||
|
<string name="enable_lib_logs_title">Enable library logs</string>
|
||||||
|
<string name="enable_h265_title">Enable H.265</string>
|
||||||
|
<string name="h265_warning">Only a few servers support h265 rtmp streaming</string>
|
||||||
</resources>
|
</resources>
|
|
@ -32,6 +32,12 @@
|
||||||
app:title="@string/fps_title"
|
app:title="@string/fps_title"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
app:key="enable_h265"
|
||||||
|
app:title="@string/enable_h265_title"
|
||||||
|
app:summaryOn="@string/h265_warning"
|
||||||
|
app:defaultValue="false" />
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:key="stereo_audio"
|
app:key="stereo_audio"
|
||||||
app:title="@string/stereo_audio_title"
|
app:title="@string/stereo_audio_title"
|
||||||
|
@ -79,4 +85,13 @@
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory app:title="@string/misc_header">
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
app:key="enable_lib_logs"
|
||||||
|
app:title="@string/enable_lib_logs_title"
|
||||||
|
app:defaultValue="true" />
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
|
@ -1,5 +1,5 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '8.0.2' apply false
|
id 'com.android.application' version '8.1.0' apply false
|
||||||
id 'com.android.library' version '8.0.2' apply false
|
id 'com.android.library' version '8.1.0' apply false
|
||||||
}
|
}
|