Skip to content

Commit 91b0298

Browse files
committed
Update
1 parent 4b440d0 commit 91b0298

File tree

8 files changed

+149
-66
lines changed

8 files changed

+149
-66
lines changed

packages/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ class SentryFlutterPlugin :
4343
private lateinit var context: Context
4444
private lateinit var sentryFlutter: SentryFlutter
4545

46-
private var activity: WeakReference<Activity>? = null
4746
private var pluginRegistrationTime: Long? = null
4847

4948
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
@@ -75,7 +74,6 @@ class SentryFlutterPlugin :
7574
"removeExtra" -> removeExtra(call.argument("key"), result)
7675
"setTag" -> setTag(call.argument("key"), call.argument("value"), result)
7776
"removeTag" -> removeTag(call.argument("key"), result)
78-
"displayRefreshRate" -> displayRefreshRate(result)
7977
"nativeCrash" -> crash()
8078
"setReplayConfig" -> setReplayConfig(call, result)
8179
"captureReplay" -> captureReplay(result)
@@ -217,29 +215,6 @@ class SentryFlutterPlugin :
217215
}
218216
}
219217

220-
private fun displayRefreshRate(result: Result) {
221-
var refreshRate: Int? = null
222-
223-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
224-
val display = activity?.get()?.display
225-
if (display != null) {
226-
refreshRate = display.refreshRate.toInt()
227-
}
228-
} else {
229-
val display =
230-
activity
231-
?.get()
232-
?.window
233-
?.windowManager
234-
?.defaultDisplay
235-
if (display != null) {
236-
refreshRate = display.refreshRate.toInt()
237-
}
238-
}
239-
240-
result.success(refreshRate)
241-
}
242-
243218
private fun TimeSpan.addToMap(map: MutableMap<String, Any?>) {
244219
if (startTimestamp == null) return
245220

@@ -381,12 +356,40 @@ class SentryFlutterPlugin :
381356
@SuppressLint("StaticFieldLeak")
382357
private var applicationContext: Context? = null
383358

359+
@SuppressLint("StaticFieldLeak")
360+
private var activity: WeakReference<Activity>? = null
361+
384362
private const val NATIVE_CRASH_WAIT_TIME = 500L
385363

386364
@Suppress("unused") // Used by native/jni bindings
387365
@JvmStatic
388366
fun privateSentryGetReplayIntegration(): ReplayIntegration? = replay
389367

368+
@Suppress("unused") // Used by native/jni bindings
369+
@JvmStatic
370+
fun getDisplayRefreshRate(): Int? {
371+
var refreshRate: Int? = null
372+
373+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
374+
val display = activity?.get()?.display
375+
if (display != null) {
376+
refreshRate = display.refreshRate.toInt()
377+
}
378+
} else {
379+
val display =
380+
activity
381+
?.get()
382+
?.window
383+
?.windowManager
384+
?.defaultDisplay
385+
if (display != null) {
386+
refreshRate = display.refreshRate.toInt()
387+
}
388+
}
389+
390+
return refreshRate
391+
}
392+
390393
@JvmStatic
391394
fun getApplicationContext(): Context? = applicationContext
392395

packages/flutter/ios/sentry_flutter/Sources/sentry_flutter/SentryFlutterPlugin.swift

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,6 @@ public class SentryFlutterPlugin: NSObject, FlutterPlugin {
133133
collectProfile(call, result)
134134
#endif
135135

136-
case "displayRefreshRate":
137-
displayRefreshRate(result)
138-
139136
case "pauseAppHangTracking":
140137
pauseAppHangTracking(result)
141138

@@ -514,42 +511,6 @@ public class SentryFlutterPlugin: NSObject, FlutterPlugin {
514511
result(nil)
515512
}
516513

517-
#if os(iOS)
518-
// Taken from the Flutter engine:
519-
// https://github.com/flutter/engine/blob/main/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm#L150
520-
private func displayRefreshRate(_ result: @escaping FlutterResult) {
521-
let displayLink = CADisplayLink(target: self, selector: #selector(onDisplayLink(_:)))
522-
displayLink.add(to: .main, forMode: .common)
523-
displayLink.isPaused = true
524-
525-
let preferredFPS = displayLink.preferredFramesPerSecond
526-
displayLink.invalidate()
527-
528-
if preferredFPS != 0 {
529-
result(preferredFPS)
530-
return
531-
}
532-
533-
if #available(iOS 13.0, *) {
534-
guard let windowScene = UIApplication.shared.windows.first?.windowScene else {
535-
result(nil)
536-
return
537-
}
538-
result(windowScene.screen.maximumFramesPerSecond)
539-
} else {
540-
result(UIScreen.main.maximumFramesPerSecond)
541-
}
542-
}
543-
544-
@objc private func onDisplayLink(_ displayLink: CADisplayLink) {
545-
// No-op
546-
}
547-
#elseif os(macOS)
548-
private func displayRefreshRate(_ result: @escaping FlutterResult) {
549-
result(nil)
550-
}
551-
#endif
552-
553514
private func pauseAppHangTracking(_ result: @escaping FlutterResult) {
554515
SentrySDK.pauseAppHangTracking()
555516
result("")
@@ -569,6 +530,41 @@ public class SentryFlutterPlugin: NSObject, FlutterPlugin {
569530
// Group of methods exposed to the Objective-C runtime via `@objc`.
570531
//
571532
// Purpose: Called from the Flutter plugin's native bridge (FFI) - bindings are created from SentryFlutterPlugin.h
533+
534+
#if os(iOS)
535+
// Taken from the Flutter engine:
536+
// https://github.com/flutter/engine/blob/main/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm#L150
537+
@objc public class func getDisplayRefreshRate() -> NSNumber? {
538+
let displayLink = CADisplayLink(target: self, selector: #selector(onDisplayLinkStatic(_:)))
539+
displayLink.add(to: .main, forMode: .common)
540+
displayLink.isPaused = true
541+
542+
let preferredFPS = displayLink.preferredFramesPerSecond
543+
displayLink.invalidate()
544+
545+
if preferredFPS != 0 {
546+
return NSNumber(value: preferredFPS)
547+
}
548+
549+
if #available(iOS 13.0, *) {
550+
guard let windowScene = UIApplication.shared.windows.first?.windowScene else {
551+
return nil
552+
}
553+
return NSNumber(value: windowScene.screen.maximumFramesPerSecond)
554+
} else {
555+
return NSNumber(value: UIScreen.main.maximumFramesPerSecond)
556+
}
557+
}
558+
559+
@objc private class func onDisplayLinkStatic(_ displayLink: CADisplayLink) {
560+
// No-op
561+
}
562+
#elseif os(macOS)
563+
@objc public class func getDisplayRefreshRate() -> NSNumber? {
564+
return nil
565+
}
566+
#endif
567+
572568
@objc(loadDebugImagesAsBytes:)
573569
public class func loadDebugImagesAsBytes(instructionAddresses: Set<String>) -> NSData? {
574570
var debugImages: [DebugMeta] = []

packages/flutter/ios/sentry_flutter/Sources/sentry_flutter_objc/SentryFlutterPlugin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#import <sentry_flutter/sentry_flutter-Swift.h>
55
#else
66
@interface SentryFlutterPlugin : NSObject
7+
+ (nullable NSNumber *)getDisplayRefreshRate;
78
+ (nullable NSData *)loadContextsAsBytes;
89
+ (nullable NSData *)loadDebugImagesAsBytes:(NSSet<NSString *> *)instructionAddresses;
910
@end

packages/flutter/lib/src/native/cocoa/binding.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,8 @@ class SentryId$1 extends objc.NSObject {
11211121
}
11221122

11231123
late final _class_SentryFlutterPlugin = objc.getClass("SentryFlutterPlugin");
1124+
late final _sel_getDisplayRefreshRate =
1125+
objc.registerName("getDisplayRefreshRate");
11241126
late final _sel_loadContextsAsBytes = objc.registerName("loadContextsAsBytes");
11251127
late final _sel_loadDebugImagesAsBytes_ =
11261128
objc.registerName("loadDebugImagesAsBytes:");
@@ -1146,6 +1148,15 @@ class SentryFlutterPlugin extends objc.NSObject {
11461148
obj.ref.pointer, _sel_isKindOfClass_, _class_SentryFlutterPlugin);
11471149
}
11481150

1151+
/// getDisplayRefreshRate
1152+
static objc.NSNumber? getDisplayRefreshRate() {
1153+
final _ret = _objc_msgSend_151sglz(
1154+
_class_SentryFlutterPlugin, _sel_getDisplayRefreshRate);
1155+
return _ret.address == 0
1156+
? null
1157+
: objc.NSNumber.castFromPointer(_ret, retain: true, release: true);
1158+
}
1159+
11491160
/// loadContextsAsBytes
11501161
static objc.NSData? loadContextsAsBytes() {
11511162
final _ret = _objc_msgSend_151sglz(

packages/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:async';
2+
import 'dart:ffi';
23
import 'dart:typed_data';
34
import 'package:meta/meta.dart';
45
import 'package:objective_c/objective_c.dart';
@@ -153,4 +154,15 @@ class SentryNativeCocoa extends SentryNativeChannel {
153154
return startTime;
154155
},
155156
);
157+
158+
@override
159+
int? displayRefreshRate() => tryCatchSync(
160+
'displayRefreshRate',
161+
() {
162+
final refreshRate = cocoa.SentryFlutterPlugin.getDisplayRefreshRate();
163+
if (refreshRate == null) return null;
164+
165+
return refreshRate.intValue;
166+
},
167+
);
156168
}

packages/flutter/lib/src/native/java/binding.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,31 @@ class SentryFlutterPlugin$Companion extends jni$_.JObject {
13051305
.object<ReplayIntegration?>(const $ReplayIntegration$NullableType());
13061306
}
13071307

1308+
static final _id_getDisplayRefreshRate = _class.instanceMethodId(
1309+
r'getDisplayRefreshRate',
1310+
r'()Ljava/lang/Integer;',
1311+
);
1312+
1313+
static final _getDisplayRefreshRate = jni$_.ProtectedJniExtensions.lookup<
1314+
jni$_.NativeFunction<
1315+
jni$_.JniResult Function(
1316+
jni$_.Pointer<jni$_.Void>,
1317+
jni$_.JMethodIDPtr,
1318+
)>>('globalEnv_CallObjectMethod')
1319+
.asFunction<
1320+
jni$_.JniResult Function(
1321+
jni$_.Pointer<jni$_.Void>,
1322+
jni$_.JMethodIDPtr,
1323+
)>();
1324+
1325+
/// from: `public final java.lang.Integer getDisplayRefreshRate()`
1326+
/// The returned object must be released after use, by calling the [release] method.
1327+
jni$_.JInteger? getDisplayRefreshRate() {
1328+
return _getDisplayRefreshRate(
1329+
reference.pointer, _id_getDisplayRefreshRate as jni$_.JMethodIDPtr)
1330+
.object<jni$_.JInteger?>(const jni$_.JIntegerNullableType());
1331+
}
1332+
13081333
static final _id_getApplicationContext = _class.instanceMethodId(
13091334
r'getApplicationContext',
13101335
r'()Landroid/content/Context;',
@@ -1765,6 +1790,31 @@ class SentryFlutterPlugin extends jni$_.JObject {
17651790
.object<ReplayIntegration?>(const $ReplayIntegration$NullableType());
17661791
}
17671792

1793+
static final _id_getDisplayRefreshRate = _class.staticMethodId(
1794+
r'getDisplayRefreshRate',
1795+
r'()Ljava/lang/Integer;',
1796+
);
1797+
1798+
static final _getDisplayRefreshRate = jni$_.ProtectedJniExtensions.lookup<
1799+
jni$_.NativeFunction<
1800+
jni$_.JniResult Function(
1801+
jni$_.Pointer<jni$_.Void>,
1802+
jni$_.JMethodIDPtr,
1803+
)>>('globalEnv_CallStaticObjectMethod')
1804+
.asFunction<
1805+
jni$_.JniResult Function(
1806+
jni$_.Pointer<jni$_.Void>,
1807+
jni$_.JMethodIDPtr,
1808+
)>();
1809+
1810+
/// from: `static public final java.lang.Integer getDisplayRefreshRate()`
1811+
/// The returned object must be released after use, by calling the [release] method.
1812+
static jni$_.JInteger? getDisplayRefreshRate() {
1813+
return _getDisplayRefreshRate(_class.reference.pointer,
1814+
_id_getDisplayRefreshRate as jni$_.JMethodIDPtr)
1815+
.object<jni$_.JInteger?>(const jni$_.JIntegerNullableType());
1816+
}
1817+
17681818
static final _id_getApplicationContext = _class.staticMethodId(
17691819
r'getApplicationContext',
17701820
r'()Landroid/content/Context;',

packages/flutter/lib/src/native/java/sentry_native_java.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ class SentryNativeJava extends SentryNativeChannel {
171171
return null;
172172
}
173173

174+
@override
175+
int? displayRefreshRate() {
176+
return native.SentryFlutterPlugin.Companion
177+
.getDisplayRefreshRate()
178+
?.intValue();
179+
}
180+
174181
@override
175182
Future<void> close() async {
176183
await _replayRecorder?.stop();

packages/flutter/lib/src/native/sentry_native_channel.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,11 @@ class SentryNativeChannel
223223
}
224224

225225
@override
226-
Future<int?> displayRefreshRate() =>
227-
channel.invokeMethod('displayRefreshRate');
226+
FutureOr<int?> displayRefreshRate() {
227+
assert(false,
228+
'displayRefreshRate should not be used through method channels.');
229+
return null;
230+
}
228231

229232
@override
230233
Future<void> pauseAppHangTracking() =>

0 commit comments

Comments
 (0)