@stream-io/video-react-native-sdk 0.7.8 → 0.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +9 -3
- package/android/src/main/java/com/streamvideo/reactnative/util/RingtoneUtil.java +121 -0
- package/dist/commonjs/utils/getAndroidDefaultRingtoneUrl.js +8 -3
- package/dist/commonjs/utils/getAndroidDefaultRingtoneUrl.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/module/utils/getAndroidDefaultRingtoneUrl.js +8 -3
- package/dist/module/utils/getAndroidDefaultRingtoneUrl.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/utils/getAndroidDefaultRingtoneUrl.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/utils/getAndroidDefaultRingtoneUrl.ts +9 -3
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
### [0.7.9](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-0.7.8...@stream-io/video-react-native-sdk-0.7.9) (2024-05-22)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* workaround for samsung device ringtone quirks ([#1362](https://github.com/GetStream/stream-video-js/issues/1362)) ([d15380a](https://github.com/GetStream/stream-video-js/commit/d15380a4aac2bd9b7b6dc6b9de337739710c97b8))
|
|
11
|
+
|
|
5
12
|
### [0.7.8](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-react-native-sdk-0.7.7...@stream-io/video-react-native-sdk-0.7.8) (2024-05-21)
|
|
6
13
|
|
|
7
14
|
### Dependency Updates
|
|
@@ -4,6 +4,7 @@ import android.app.AppOpsManager
|
|
|
4
4
|
import android.app.PictureInPictureParams
|
|
5
5
|
import android.content.Context
|
|
6
6
|
import android.content.pm.PackageManager
|
|
7
|
+
import android.net.Uri
|
|
7
8
|
import android.os.Build
|
|
8
9
|
import android.os.Process
|
|
9
10
|
import android.util.Rational
|
|
@@ -13,8 +14,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
|
13
14
|
import com.facebook.react.bridge.ReactMethod
|
|
14
15
|
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
|
|
15
16
|
import com.facebook.react.bridge.Promise;
|
|
16
|
-
import
|
|
17
|
-
|
|
17
|
+
import com.streamvideo.reactnative.util.RingtoneUtil
|
|
18
18
|
|
|
19
19
|
class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
20
20
|
|
|
@@ -36,7 +36,13 @@ class StreamVideoReactNativeModule(reactContext: ReactApplicationContext) : Reac
|
|
|
36
36
|
|
|
37
37
|
@ReactMethod
|
|
38
38
|
fun getDefaultRingtoneUrl(promise: Promise) {
|
|
39
|
-
|
|
39
|
+
val defaultRingtoneUri: Uri? =
|
|
40
|
+
RingtoneUtil.getActualDefaultRingtoneUri(reactApplicationContext);
|
|
41
|
+
if (defaultRingtoneUri != null) {
|
|
42
|
+
promise.resolve(defaultRingtoneUri.toString());
|
|
43
|
+
} else {
|
|
44
|
+
promise.reject(NAME, "Cannot get default ringtone in Android - check native logs for more info");
|
|
45
|
+
}
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
@ReactMethod
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
package com.streamvideo.reactnative.util;
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint;
|
|
4
|
+
import android.content.ContentResolver;
|
|
5
|
+
import android.content.Context;
|
|
6
|
+
import android.media.Ringtone;
|
|
7
|
+
import android.media.RingtoneManager;
|
|
8
|
+
import android.net.Uri;
|
|
9
|
+
import android.provider.Settings;
|
|
10
|
+
import android.util.Log;
|
|
11
|
+
|
|
12
|
+
import androidx.annotation.NonNull;
|
|
13
|
+
import androidx.annotation.Nullable;
|
|
14
|
+
|
|
15
|
+
import java.lang.reflect.InvocationTargetException;
|
|
16
|
+
import java.lang.reflect.Method;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Original source: https://github.com/signalapp/Signal-Android/blob/main/app/src/main/java/org/thoughtcrime/securesms/util/RingtoneUtil.java
|
|
20
|
+
* Some custom ROMs and some Samsung Android 11 devices have quirks around accessing the default ringtone. This attempts to deal
|
|
21
|
+
* with them with progressively worse approaches.
|
|
22
|
+
*/
|
|
23
|
+
public final class RingtoneUtil {
|
|
24
|
+
|
|
25
|
+
private static final String TAG = "RingtoneUtil";
|
|
26
|
+
|
|
27
|
+
private RingtoneUtil() {}
|
|
28
|
+
|
|
29
|
+
public static @Nullable Ringtone getRingtone(@NonNull Context context, @NonNull Uri uri) {
|
|
30
|
+
Ringtone tone;
|
|
31
|
+
try {
|
|
32
|
+
tone = RingtoneManager.getRingtone(context, uri);
|
|
33
|
+
} catch (SecurityException e) {
|
|
34
|
+
Log.w(TAG, "Unable to get default ringtone due to permission", e);
|
|
35
|
+
tone = RingtoneManager.getRingtone(context, RingtoneUtil.getActualDefaultRingtoneUri(context));
|
|
36
|
+
}
|
|
37
|
+
return tone;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public static @Nullable Uri getActualDefaultRingtoneUri(@NonNull Context context) {
|
|
41
|
+
Log.i(TAG, "Attempting to get default ringtone directly via normal way");
|
|
42
|
+
try {
|
|
43
|
+
return RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE);
|
|
44
|
+
} catch (SecurityException e) {
|
|
45
|
+
Log.w(TAG, "Failed to get ringtone with first fallback approach", e);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Log.i(TAG, "Attempting to get default ringtone directly via reflection");
|
|
49
|
+
String uriString = getStringForUser(context.getContentResolver(), getUserId(context));
|
|
50
|
+
Uri ringtoneUri = uriString != null ? Uri.parse(uriString) : null;
|
|
51
|
+
|
|
52
|
+
if (ringtoneUri != null && getUserIdFromAuthority(ringtoneUri.getAuthority(), getUserId(context)) == getUserId(context)) {
|
|
53
|
+
ringtoneUri = getUriWithoutUserId(ringtoneUri);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return ringtoneUri;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@SuppressWarnings("JavaReflectionMemberAccess")
|
|
60
|
+
@SuppressLint("DiscouragedPrivateApi")
|
|
61
|
+
private static @Nullable String getStringForUser(@NonNull ContentResolver resolver, int userHandle) {
|
|
62
|
+
try {
|
|
63
|
+
Method getStringForUser = Settings.System.class.getMethod("getStringForUser", ContentResolver.class, String.class, int.class);
|
|
64
|
+
return (String) getStringForUser.invoke(Settings.System.class, resolver, Settings.System.RINGTONE, userHandle);
|
|
65
|
+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
|
66
|
+
Log.w(TAG, "Unable to getStringForUser via reflection", e);
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@SuppressWarnings("JavaReflectionMemberAccess")
|
|
72
|
+
@SuppressLint("DiscouragedPrivateApi")
|
|
73
|
+
private static int getUserId(@NonNull Context context) {
|
|
74
|
+
try {
|
|
75
|
+
Object userId = Context.class.getMethod("getUserId").invoke(context);
|
|
76
|
+
if (userId instanceof Integer) {
|
|
77
|
+
return (Integer) userId;
|
|
78
|
+
} else {
|
|
79
|
+
Log.w(TAG, "getUserId did not return an integer");
|
|
80
|
+
}
|
|
81
|
+
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
|
82
|
+
Log.w(TAG, "Unable to getUserId via reflection", e);
|
|
83
|
+
}
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private static @Nullable Uri getUriWithoutUserId(@Nullable Uri uri) {
|
|
88
|
+
if (uri == null) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
Uri.Builder builder = uri.buildUpon();
|
|
92
|
+
builder.authority(getAuthorityWithoutUserId(uri.getAuthority()));
|
|
93
|
+
return builder.build();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private static @Nullable String getAuthorityWithoutUserId(@Nullable String auth) {
|
|
97
|
+
if (auth == null) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
int end = auth.lastIndexOf('@');
|
|
101
|
+
return auth.substring(end + 1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private static int getUserIdFromAuthority(@Nullable String authority, int defaultUserId) {
|
|
105
|
+
if (authority == null) {
|
|
106
|
+
return defaultUserId;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
int end = authority.lastIndexOf('@');
|
|
110
|
+
if (end == -1) {
|
|
111
|
+
return defaultUserId;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
String userIdString = authority.substring(0, end);
|
|
115
|
+
try {
|
|
116
|
+
return Integer.parseInt(userIdString);
|
|
117
|
+
} catch (NumberFormatException e) {
|
|
118
|
+
return defaultUserId;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -6,11 +6,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.getAndroidDefaultRingtoneUrl = getAndroidDefaultRingtoneUrl;
|
|
7
7
|
var _reactNative = require("react-native");
|
|
8
8
|
async function getAndroidDefaultRingtoneUrl() {
|
|
9
|
-
var _NativeModules$Stream;
|
|
10
9
|
if (_reactNative.Platform.OS !== 'android') {
|
|
11
10
|
return undefined;
|
|
12
11
|
}
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
try {
|
|
13
|
+
var _NativeModules$Stream;
|
|
14
|
+
const url = await ((_NativeModules$Stream = _reactNative.NativeModules.StreamVideoReactNative) === null || _NativeModules$Stream === void 0 ? void 0 : _NativeModules$Stream.getDefaultRingtoneUrl());
|
|
15
|
+
return url;
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.info(e);
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
15
20
|
}
|
|
16
21
|
//# sourceMappingURL=getAndroidDefaultRingtoneUrl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","getAndroidDefaultRingtoneUrl","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","getAndroidDefaultRingtoneUrl","Platform","OS","undefined","_NativeModules$Stream","url","NativeModules","StreamVideoReactNative","getDefaultRingtoneUrl","e","console","info"],"sourceRoot":"../../../src","sources":["utils/getAndroidDefaultRingtoneUrl.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEO,eAAeC,4BAA4BA,CAAA,EAEhD;EACA,IAAIC,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAAE;IAC7B,OAAOC,SAAS;EAClB;EACA,IAAI;IAAA,IAAAC,qBAAA;IACF,MAAMC,GAAG,GACP,QAAAD,qBAAA,GAAME,0BAAa,CAACC,sBAAsB,cAAAH,qBAAA,uBAApCA,qBAAA,CAAsCI,qBAAqB,CAAC,CAAC;IACrE,OAAOH,GAAG;EACZ,CAAC,CAAC,OAAOI,CAAC,EAAE;IACVC,OAAO,CAACC,IAAI,CAACF,CAAC,CAAC;EACjB;EAEA,OAAON,SAAS;AAClB"}
|
package/dist/commonjs/version.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
2
|
export async function getAndroidDefaultRingtoneUrl() {
|
|
3
|
-
var _NativeModules$Stream;
|
|
4
3
|
if (Platform.OS !== 'android') {
|
|
5
4
|
return undefined;
|
|
6
5
|
}
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
try {
|
|
7
|
+
var _NativeModules$Stream;
|
|
8
|
+
const url = await ((_NativeModules$Stream = NativeModules.StreamVideoReactNative) === null || _NativeModules$Stream === void 0 ? void 0 : _NativeModules$Stream.getDefaultRingtoneUrl());
|
|
9
|
+
return url;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
console.info(e);
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
9
14
|
}
|
|
10
15
|
//# sourceMappingURL=getAndroidDefaultRingtoneUrl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","Platform","getAndroidDefaultRingtoneUrl","
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","getAndroidDefaultRingtoneUrl","OS","undefined","_NativeModules$Stream","url","StreamVideoReactNative","getDefaultRingtoneUrl","e","console","info"],"sourceRoot":"../../../src","sources":["utils/getAndroidDefaultRingtoneUrl.ts"],"mappings":"AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,OAAO,eAAeC,4BAA4BA,CAAA,EAEhD;EACA,IAAID,QAAQ,CAACE,EAAE,KAAK,SAAS,EAAE;IAC7B,OAAOC,SAAS;EAClB;EACA,IAAI;IAAA,IAAAC,qBAAA;IACF,MAAMC,GAAG,GACP,QAAAD,qBAAA,GAAML,aAAa,CAACO,sBAAsB,cAAAF,qBAAA,uBAApCA,qBAAA,CAAsCG,qBAAqB,CAAC,CAAC;IACrE,OAAOF,GAAG;EACZ,CAAC,CAAC,OAAOG,CAAC,EAAE;IACVC,OAAO,CAACC,IAAI,CAACF,CAAC,CAAC;EACjB;EAEA,OAAOL,SAAS;AAClB"}
|
package/dist/module/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '0.7.
|
|
1
|
+
export const version = '0.7.9';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getAndroidDefaultRingtoneUrl.d.ts","sourceRoot":"","sources":["../../../src/utils/getAndroidDefaultRingtoneUrl.ts"],"names":[],"mappings":"AAEA,wBAAsB,4BAA4B,IAAI,OAAO,CAC3D,MAAM,GAAG,SAAS,CACnB,
|
|
1
|
+
{"version":3,"file":"getAndroidDefaultRingtoneUrl.d.ts","sourceRoot":"","sources":["../../../src/utils/getAndroidDefaultRingtoneUrl.ts"],"names":[],"mappings":"AAEA,wBAAsB,4BAA4B,IAAI,OAAO,CAC3D,MAAM,GAAG,SAAS,CACnB,CAaA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.7.
|
|
1
|
+
export declare const version = "0.7.9";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/package.json
CHANGED
|
@@ -6,7 +6,13 @@ export async function getAndroidDefaultRingtoneUrl(): Promise<
|
|
|
6
6
|
if (Platform.OS !== 'android') {
|
|
7
7
|
return undefined;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
try {
|
|
10
|
+
const url =
|
|
11
|
+
await NativeModules.StreamVideoReactNative?.getDefaultRingtoneUrl();
|
|
12
|
+
return url;
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.info(e);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return undefined;
|
|
12
18
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.7.
|
|
1
|
+
export const version = '0.7.9';
|