Skip to content

Commit a971590

Browse files
committed
decoupled the event logic from component logic.
Events when a screen is connected/disconnected will be received even if the external view component is not rendered
1 parent 6e8198f commit a971590

File tree

5 files changed

+475
-433
lines changed

5 files changed

+475
-433
lines changed

packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java

Lines changed: 99 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -17,100 +17,127 @@
1717

1818
import java.util.Map;
1919
import java.util.HashMap;
20+
2021
import android.util.Log;
2122

2223
import com.facebook.react.bridge.LifecycleEventListener;
2324
import com.facebook.react.bridge.ReactApplicationContext;
2425

2526
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
2627
class ExternalDisplayScreen extends Presentation {
27-
ExternalDisplayScreen(Context ctx, Display display) {
28-
super(ctx, display);
29-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen init");
28+
ExternalDisplayScreen(Context ctx, Display display) {
29+
super(ctx, display);
30+
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen init");
3031

31-
}
32+
}
3233

33-
@Override
34-
protected void onCreate(Bundle savedInstanceState) {
35-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onCreate");
34+
@Override
35+
protected void onCreate(Bundle savedInstanceState) {
36+
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onCreate");
3637

37-
super.onCreate(savedInstanceState);
38-
}
38+
super.onCreate(savedInstanceState);
39+
}
3940
}
4041

4142
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
4243
class ExternalDisplayHelper implements DisplayManager.DisplayListener {
43-
44-
public static Map<String, Object> getScreenInfo(Display[] displays) {
45-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getScreenInfo");
46-
47-
HashMap<String, Object> info = new HashMap<String, Object>();
48-
for (Display display : displays) {
49-
int displayId = display.getDisplayId();
50-
if (
51-
display.getDisplayId() == Display.DEFAULT_DISPLAY ||
52-
(display.getFlags() & Display.FLAG_PRESENTATION) == 0
53-
) {
54-
continue;
55-
}
56-
HashMap<String, Object> data = new HashMap<String, Object>();
57-
DisplayMetrics displayMetrics = new DisplayMetrics();
58-
display.getMetrics(displayMetrics);
59-
data.put("id", displayId);
60-
data.put("width", displayMetrics.widthPixels);
61-
data.put("height", displayMetrics.heightPixels);
62-
info.put(String.valueOf(display.getDisplayId()), data);
44+
private static final String TAG = "RNExternalDisplayEvent";
45+
private static ExternalDisplayHelper instance = null;
46+
private DisplayManager dm = null;
47+
private Listener listener = null;
48+
private Display displays = null;
49+
50+
// Private constructor to prevent direct instantiation
51+
private ExternalDisplayHelper(Context context, Listener listener) {
52+
this.listener = listener;
53+
dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
54+
if (dm != null) {
55+
dm.registerDisplayListener(this, null);
56+
} else {
57+
}
6358
}
64-
return info;
65-
}
66-
67-
public interface Listener {
68-
void onDisplayAdded(Display[] displays, int displayId);
69-
void onDisplayChanged(Display[] displays, int displayId);
70-
void onDisplayRemoved(Display[] displays, int displayId);
71-
}
72-
73-
private Listener listener = null;
74-
private DisplayManager dm = null;
75-
private Display displays = null;
7659

77-
public ExternalDisplayHelper(Context context, Listener listener) {
78-
this.listener = listener;
79-
80-
dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
81-
dm.registerDisplayListener(this, null);
82-
}
83-
84-
public Display getDisplay(int displayId) {
85-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getDisplay");
86-
87-
return dm.getDisplay(displayId);
88-
}
60+
// Method to initialize the singleton instance
61+
public static synchronized void initialize(Context context, Listener listener) {
62+
if (instance == null) {
63+
instance = new ExternalDisplayHelper(context.getApplicationContext(), listener);
64+
}
65+
}
8966

90-
public Display[] getDisplays() {
91-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getDisplays");
67+
// Method to get the singleton instance
68+
public static synchronized ExternalDisplayHelper getInstance() {
69+
if (instance == null) {
70+
throw new IllegalStateException("ExternalDisplayHelper is not initialized. Call initialize() first.");
71+
}
72+
return instance;
73+
}
9274

93-
return dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
94-
}
75+
// Method to clean up the singleton instance
76+
public static synchronized void destroy() {
77+
if (instance != null && instance.dm != null) {
78+
instance.dm.unregisterDisplayListener(instance);
79+
instance = null;
80+
}
81+
}
82+
public static Map<String, Object> getScreenInfo(Display[] displays) {
83+
HashMap<String, Object> info = new HashMap<>();
84+
for (Display display : displays) {
85+
int displayId = display.getDisplayId();
86+
if (
87+
display.getDisplayId() == Display.DEFAULT_DISPLAY ||
88+
(display.getFlags() & Display.FLAG_PRESENTATION) == 0
89+
) {
90+
continue;
91+
}
92+
HashMap<String, Object> data = new HashMap<>();
93+
DisplayMetrics displayMetrics = new DisplayMetrics();
94+
display.getMetrics(displayMetrics);
95+
data.put("id", displayId);
96+
data.put("width", displayMetrics.widthPixels);
97+
data.put("height", displayMetrics.heightPixels);
98+
info.put(String.valueOf(display.getDisplayId()), data);
99+
}
100+
return info;
101+
}
95102

96-
@Override
97-
public void onDisplayAdded(int displayId) {
98-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayAdded");
103+
@Override
104+
public void onDisplayAdded(int displayId) {
105+
if (listener != null) {
106+
listener.onDisplayAdded(getDisplays(), displayId);
107+
}
108+
}
99109

100-
listener.onDisplayAdded(getDisplays(), displayId);
101-
}
110+
@Override
111+
public void onDisplayChanged(int displayId) {
112+
if (listener != null) {
113+
listener.onDisplayChanged(getDisplays(), displayId);
114+
}
115+
}
102116

103-
@Override
104-
public void onDisplayChanged(int displayId) {
105-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayChanged");
117+
@Override
118+
public void onDisplayRemoved(int displayId) {
119+
if (listener != null) {
120+
listener.onDisplayRemoved(getDisplays(), displayId);
121+
}
122+
}
106123

107-
listener.onDisplayChanged(getDisplays(), displayId);
108-
}
124+
public Display getDisplay(int displayId) {
125+
if (dm != null) {
126+
return dm.getDisplay(displayId);
127+
}
128+
return null;
129+
}
109130

110-
@Override
111-
public void onDisplayRemoved(int displayId) {
112-
Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayRemoved");
131+
public Display[] getDisplays() {
132+
if (dm != null) {
133+
return dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
134+
}
135+
return new Display[0];
136+
}
113137

114-
listener.onDisplayRemoved(getDisplays(), displayId);
115-
}
138+
public interface Listener {
139+
void onDisplayAdded(Display[] displays, int displayId);
140+
void onDisplayChanged(Display[] displays, int displayId);
141+
void onDisplayRemoved(Display[] displays, int displayId);
142+
}
116143
}
Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package com.externaldisplay;
22

33
import androidx.annotation.Nullable;
4+
45
import com.facebook.react.bridge.NativeModule;
56
import com.facebook.react.bridge.ReactApplicationContext;
67
import com.facebook.react.module.model.ReactModuleInfo;
78
import com.facebook.react.module.model.ReactModuleInfoProvider;
89
import com.facebook.react.TurboReactPackage;
910
import com.facebook.react.uimanager.ViewManager;
11+
1012
import android.util.Log;
1113

1214
import java.util.ArrayList;
@@ -16,64 +18,61 @@
1618
import java.util.Map;
1719

1820
import android.util.Log;
21+
1922
import com.externaldisplay.RNExternalDisplayManager;
2023
import com.externaldisplay.RNExternalDisplayModule;
2124

2225
public class RNExternalDisplayPackage extends TurboReactPackage {
26+
private static final String TAG = "RNExternalDisplayEvent";
2327

24-
@Override
25-
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
26-
Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage createViewManagers");
27-
28-
List<ViewManager> viewManagers = new ArrayList<>();
29-
viewManagers.add(new RNExternalDisplayManager(reactContext));
30-
return viewManagers;
31-
}
3228

33-
@Nullable
34-
@Override
35-
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
36-
Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage getModule");
37-
38-
if (name.equals(RNExternalDisplayModule.REACT_CLASS)) {
39-
return new com.externaldisplay.RNExternalDisplayModule(reactContext);
40-
} else {
41-
return null;
29+
@Override
30+
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
31+
List<ViewManager> viewManagers = new ArrayList<>();
32+
viewManagers.add(new RNExternalDisplayManager(reactContext));
33+
return viewManagers;
4234
}
43-
}
4435

45-
@Override
46-
public ReactModuleInfoProvider getReactModuleInfoProvider() {
47-
Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage getReactModuleInfoProvider");
36+
@Nullable
37+
@Override
38+
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
39+
if (name.equals(RNExternalDisplayModule.REACT_CLASS)) {
40+
return new RNExternalDisplayModule(reactContext);
41+
} else {
42+
return null;
43+
}
44+
}
4845

49-
return () -> {
50-
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
51-
boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
52-
moduleInfos.put(
53-
RNExternalDisplayModule.REACT_CLASS,
54-
new ReactModuleInfo(
55-
RNExternalDisplayModule.REACT_CLASS,
56-
RNExternalDisplayModule.REACT_CLASS,
57-
false, // canOverrideExistingModule
58-
false, // needsEagerInit
59-
true, // hasConstants
60-
false, // isCxxModule
61-
isTurboModule // isTurboModule
62-
)
63-
);
64-
moduleInfos.put(
65-
RNExternalDisplayManager.REACT_CLASS,
66-
new ReactModuleInfo(
67-
RNExternalDisplayManager.REACT_CLASS,
68-
RNExternalDisplayManager.REACT_CLASS,
69-
false, // canOverrideExistingModule
70-
false, // needsEagerInit
71-
true, // hasConstants
72-
false, // isCxxModule
73-
isTurboModule // isTurboModule
74-
)
75-
);
76-
return moduleInfos;
77-
};
78-
}
46+
@Override
47+
public ReactModuleInfoProvider getReactModuleInfoProvider() {
48+
return () -> {
49+
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
50+
boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
51+
moduleInfos.put(
52+
RNExternalDisplayModule.REACT_CLASS,
53+
new ReactModuleInfo(
54+
RNExternalDisplayModule.REACT_CLASS,
55+
RNExternalDisplayModule.REACT_CLASS,
56+
false, // canOverrideExistingModule
57+
false, // needsEagerInit
58+
true, // hasConstants
59+
false, // isCxxModule
60+
isTurboModule // isTurboModule
61+
)
62+
);
63+
moduleInfos.put(
64+
RNExternalDisplayManager.REACT_CLASS,
65+
new ReactModuleInfo(
66+
RNExternalDisplayManager.REACT_CLASS,
67+
RNExternalDisplayManager.REACT_CLASS,
68+
false, // canOverrideExistingModule
69+
false, // needsEagerInit
70+
true, // hasConstants
71+
false, // isCxxModule
72+
isTurboModule // isTurboModule
73+
)
74+
);
75+
return moduleInfos;
76+
};
77+
}
7978
}

0 commit comments

Comments
 (0)