提交 ebe1b934 authored 作者: kongdywang's avatar kongdywang

1. Add logic to avoid app exit on the iOS side.

2. Avoid potential memory leak issues. 3. On the iOS side, add handling for potential crash issues that may occur when the app's process is killed under certain circumstances. 4. During plugin registration on the iOS side, add a `publish` method to register the plugin and ensure that the deregistration callback occurs. 5. Fix known issues.
上级 44800b08
......@@ -3,7 +3,6 @@
package com.tencent.vod.flutter;
import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
......@@ -18,7 +17,6 @@ import android.os.Looper;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.OrientationEventListener;
import android.view.Window;
......@@ -149,6 +147,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
@Override
public void onLicenceLoaded(int result, String reason) {
super.onLicenceLoaded(result, reason);
LiteavLog.v(TAG, "onLicenceLoaded,result:" + result + ",reason:" + reason);
mMainHandler.post(new Runnable() {
@Override
public void run() {
......@@ -336,19 +335,10 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
@Override
public void onOrientationChanged(int orientation) {
if (isDeviceAutoRotateOn()) {
int orientationEvent = mCurrentOrientation;
// Each direction judges the current direction with an interval
// of 60 degrees, with a total of 6 intervals.
if (((orientation >= 0) && (orientation < 30)) || (orientation > 330)) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_UP;
} else if (orientation > 240 && orientation < 300) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_RIGHT;
} else if (orientation > 150 && orientation < 210) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_DOWN;
} else if (orientation > 60 && orientation < 110) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_LEFT;
}
LiteavLog.v(TAG, "onOrientationChanged:" + orientation);
int orientationEvent = getOrientationEvent(orientation);
if (orientationEvent != mCurrentOrientation) {
LiteavLog.v(TAG, "orientationEvent changed:" + orientationEvent);
mCurrentOrientation = orientationEvent;
Bundle bundle = new Bundle();
bundle.putInt(FTXEvent.EXTRA_NAME_ORIENTATION, orientationEvent);
......@@ -366,6 +356,22 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
return true;
}
private int getOrientationEvent(int orientation) {
int orientationEvent = mCurrentOrientation;
// Each direction judges the current direction with an interval
// of 60 degrees, with a total of 6 intervals.
if (((orientation >= 0) && (orientation < 30)) || (orientation > 330)) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_UP;
} else if (orientation > 240 && orientation < 300) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_RIGHT;
} else if (orientation > 150 && orientation < 210) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_DOWN;
} else if (orientation > 60 && orientation < 110) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_LEFT;
}
return orientationEvent;
}
/**
* Set the current window brightness.
*
......@@ -373,6 +379,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
*/
private void setWindowBrightness(Double brightness) {
if (null != brightness) {
LiteavLog.v(TAG, "setWindowBrightness:" + brightness);
// 保留两位小数
BigDecimal bigDecimal = new BigDecimal(brightness);
brightness = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
......@@ -474,16 +481,12 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
Application application = binding.getActivity().getApplication();
Application application1 = (Application) mFlutterPluginBinding.getApplicationContext();
Log.e(TAG, "");
LiteavLog.v(TAG, "called onAttachedToActivity");
}
@Override
public void onDetachedFromActivity() {
LiteavLog.v(TAG, "called onDetachedFromActivity");
}
void onHandleAudioFocusPause() {
......@@ -518,7 +521,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
*/
public void registerReceiver() {
// volume receiver
mVolumeBroadcastReceiver = new VolumeBroadcastReceiver();
mVolumeBroadcastReceiver = new VolumeBroadcastReceiver(mEventSink);
IntentFilter filter = new IntentFilter();
filter.addAction(VOLUME_CHANGED_ACTION);
ContextCompat.registerReceiver(mFlutterPluginBinding.getApplicationContext(), mVolumeBroadcastReceiver, filter,
......@@ -558,12 +561,11 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
}
}
private Map<String, Object> getParams(int event, Bundle bundle) {
private static Map<String, Object> getParams(int event, Bundle bundle) {
Map<String, Object> param = new HashMap<>();
if (event != 0) {
param.put("event", event);
}
if (bundle != null && !bundle.isEmpty()) {
Set<String> keySet = bundle.keySet();
for (String key : keySet) {
......@@ -643,7 +645,13 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
}
}
private class VolumeBroadcastReceiver extends BroadcastReceiver {
private static class VolumeBroadcastReceiver extends BroadcastReceiver {
private final FTXPlayerEventSink mEventSink;
private VolumeBroadcastReceiver(FTXPlayerEventSink eventSink) {
mEventSink = eventSink;
}
public void onReceive(Context context, Intent intent) {
// Notify only when the media volume changes
......
......@@ -29,6 +29,8 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
......@@ -37,6 +39,8 @@
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiresFullScreen</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
......@@ -54,7 +58,5 @@
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
......@@ -10,6 +10,7 @@
#import "FtxMessages.h"
#import "TXCommonUtil.h"
#import "FTXLog.h"
#import <stdatomic.h>
static const int uninitialized = -1;
......@@ -24,7 +25,7 @@ static const int uninitialized = -1;
FlutterEventChannel *_eventChannel;
FlutterEventChannel *_netStatusChannel;
// The latest frame.
CVPixelBufferRef volatile _latestPixelBuffer;
CVPixelBufferRef _Atomic _latestPixelBuffer;
// The old frame.
CVPixelBufferRef _lastBuffer;
int64_t _textureId;
......@@ -59,9 +60,12 @@ static const int uninitialized = -1;
- (void)destory
{
FTXLOGV(@"livePlayer start called destory");
[self stopPlay];
if (nil != _txLivePlayer) {
[_txLivePlayer removeVideoWidget];
_txLivePlayer = nil;
}
if (_textureId >= 0) {
[_textureRegistry unregisterTexture:_textureId];
......@@ -70,8 +74,7 @@ static const int uninitialized = -1;
}
CVPixelBufferRef old = _latestPixelBuffer;
while (!OSAtomicCompareAndSwapPtrBarrier(old, nil,
(void **)&_latestPixelBuffer)) {
while (!atomic_compare_exchange_strong_explicit(&_latestPixelBuffer, &old, nil, memory_order_release, memory_order_relaxed)) {
old = _latestPixelBuffer;
}
if (old) {
......@@ -83,17 +86,46 @@ static const int uninitialized = -1;
_lastBuffer = nil;
}
if (nil != _eventSink) {
[_eventSink setDelegate:nil];
_eventSink = nil;
}
if (nil != _eventChannel) {
[_eventChannel setStreamHandler:nil];
_eventChannel = nil;
}
if (nil != _netStatusSink) {
[_netStatusSink setDelegate:nil];
_netStatusSink = nil;
}
}
- (void)notifyAppTerminate:(UIApplication *)application {
if (!_isTerminate) {
FTXLOGW(@"livePlayer is called notifyAppTerminate terminate");
[self notifyPlayerTerminate];
}
}
- (void)dealloc
{
if (!_isTerminate) {
FTXLOGW(@"livePlayer is called delloc terminate");
[self notifyPlayerTerminate];
}
}
- (void)notifyPlayerTerminate {
FTXLOGW(@"livePlayer notifyPlayerTerminate");
_isTerminate = YES;
_textureRegistry = nil;
[self stopPlay];
if (nil != _txLivePlayer) {
[_txLivePlayer removeVideoWidget];
_txLivePlayer.videoProcessDelegate = nil;
_txLivePlayer = nil;
}
_textureId = -1;
}
- (void)setupPlayerWithBool:(BOOL)onlyAudio
......@@ -283,9 +315,11 @@ static const int uninitialized = -1;
- (CVPixelBufferRef _Nullable)copyPixelBuffer
{
if(_isTerminate || _isStoped){
return nil;
}
CVPixelBufferRef pixelBuffer = _latestPixelBuffer;
while (!OSAtomicCompareAndSwapPtrBarrier(pixelBuffer, nil,
(void **)&_latestPixelBuffer)) {
while (!atomic_compare_exchange_strong_explicit(&_latestPixelBuffer, &pixelBuffer, NULL, memory_order_release, memory_order_relaxed)) {
pixelBuffer = _latestPixelBuffer;
}
return pixelBuffer;
......@@ -339,10 +373,11 @@ static const int uninitialized = -1;
}
CVPixelBufferRef newBuffer = pixelBuffer;
CVPixelBufferRef old = _latestPixelBuffer;
while (!OSAtomicCompareAndSwapPtrBarrier(old, newBuffer,
(void **)&_latestPixelBuffer)) {
while (!atomic_compare_exchange_strong_explicit(&_latestPixelBuffer, &old, newBuffer, memory_order_release, memory_order_relaxed)) {
if (_isTerminate) {
break;
}
old = _latestPixelBuffer;
}
......
......@@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)onPlayerPipStateError:(NSInteger)errorId;
- (void) releasePlayerInner:(NSNumber*)playerId;
@end
@interface FTXVodPlayer : FTXBasePlayer
......
......@@ -12,6 +12,7 @@
#import "FtxMessages.h"
#import "TXCommonUtil.h"
#import "FTXLog.h"
#import <stdatomic.h>
static const int uninitialized = -1;
static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
......@@ -36,7 +37,7 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
FlutterEventChannel *_eventChannel;
FlutterEventChannel *_netStatusChannel;
// The latest frame.
CVPixelBufferRef volatile _latestPixelBuffer;
CVPixelBufferRef _Atomic _latestPixelBuffer;
// The old frame.
CVPixelBufferRef _lastBuffer;
int64_t _textureId;
......@@ -95,36 +96,53 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
}
- (void)notifyAppTerminate:(UIApplication *)application {
if (!_isTerminate) {
FTXLOGW(@"vodPlayer is called _isTerminate terminate");
[self notifyPlayerTerminate];
}
}
- (void)dealloc
{
if (!_isTerminate) {
FTXLOGW(@"vodPlayer is called delloc terminate");
[self notifyPlayerTerminate];
}
}
- (void)notifyPlayerTerminate {
FTXLOGW(@"vodPlayer notifyPlayerTerminate");
_isTerminate = YES;
_textureRegistry = nil;
[self stopPlay];
if (nil != _txVodPlayer) {
[_txVodPlayer removeVideoWidget];
_txVodPlayer = nil;
_txVodPlayer.videoProcessDelegate = nil;
_txVodPlayer = nil;
}
_textureId = -1;
}
- (void)destory
{
FTXLOGV(@"vodPlayer start called destory");
[self stopPlay];
if (nil != _txVodPlayer) {
[_txVodPlayer removeVideoWidget];
_txVodPlayer = nil;
}
self.txPipView = nil;
_hasEnteredPipMode = NO;
_restoreUI = NO;
if (_textureId >= 0) {
if (_textureId >= 0 && _textureRegistry) {
[_textureRegistry unregisterTexture:_textureId];
_textureId = -1;
_textureRegistry = nil;
}
CVPixelBufferRef old = _latestPixelBuffer;
while (!OSAtomicCompareAndSwapPtrBarrier(old, nil,
(void **)&_latestPixelBuffer)) {
while (!atomic_compare_exchange_strong_explicit(&_latestPixelBuffer, &old, nil, memory_order_release, memory_order_relaxed)) {
old = _latestPixelBuffer;
}
if (old) {
......@@ -136,16 +154,22 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
_lastBuffer = nil;
}
if (nil != _eventSink) {
[_eventSink setDelegate:nil];
_eventSink = nil;
}
if (nil != _netStatusSink) {
[_netStatusSink setDelegate:nil];
_netStatusSink = nil;
}
if (nil != _eventChannel) {
[_eventChannel setStreamHandler:nil];
_eventChannel = nil;
}
if (nil != _netStatusChannel) {
[_netStatusChannel setStreamHandler:nil];
_netStatusChannel = nil;
}
[self releaseImageSprite];
}
......@@ -423,13 +447,14 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
- (CVPixelBufferRef _Nullable)copyPixelBuffer
{
if(_isTerminate || _isStoped){
return nil;
}
if (self.hasEnteredPipMode) {
return [self getPipImagePixelBuffer];
}
CVPixelBufferRef pixelBuffer = _latestPixelBuffer;
while (!OSAtomicCompareAndSwapPtrBarrier(pixelBuffer, nil,
(void **)&_latestPixelBuffer)) {
while (!atomic_compare_exchange_strong_explicit(&_latestPixelBuffer, &pixelBuffer, NULL, memory_order_release, memory_order_relaxed)) {
pixelBuffer = _latestPixelBuffer;
}
return pixelBuffer;
......@@ -521,10 +546,8 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
}
CVPixelBufferRef newBuffer = pixelBuffer;
CVPixelBufferRef old = _latestPixelBuffer;
while (!OSAtomicCompareAndSwapPtrBarrier(old, newBuffer,
(void **)&_latestPixelBuffer)) {
while (!atomic_compare_exchange_strong_explicit(&_latestPixelBuffer, &old, newBuffer, memory_order_release, memory_order_relaxed)) {
if (_isTerminate) {
break;
}
......
......@@ -35,6 +35,7 @@
SuperPlayerPlugin* instance;
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FTXLOGV(@"called registerWithRegistrar");
instance = [[SuperPlayerPlugin alloc] initWithRegistrar:registrar];
TXFlutterSuperPlayerPluginAPISetup([registrar messenger], instance);
TXFlutterNativeAPISetup([registrar messenger], instance);
......@@ -45,6 +46,7 @@ SuperPlayerPlugin* instance;
}
- (void)detachFromEngineForRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FTXLOGV(@"called detachFromEngineForRegistrar");
if(nil != instance) {
[instance destory];
}
......@@ -58,6 +60,7 @@ SuperPlayerPlugin* instance;
(NSObject<FlutterPluginRegistrar> *)registrar {
self = [super init];
if (self) {
[registrar publish:self];
_registrar = registrar;
_players = @{}.mutableCopy;
}
......@@ -109,6 +112,7 @@ SuperPlayerPlugin* instance;
}
-(void) setSysBrightness:(NSNumber*)brightness {
FTXLOGV(@"called setSysBrightness,%@", brightness);
if(brightness.floatValue > 1.0) {
brightness = [NSNumber numberWithFloat:1.0];
}
......@@ -122,6 +126,15 @@ SuperPlayerPlugin* instance;
}
}
-(void) releasePlayerInner:(NSNumber*)playerId {
FTXLOGV(@"called releasePlayerInner,%@ is start release", playerId);
FTXBasePlayer *player = [_players objectForKey:playerId];
[player destory];
if (player != nil) {
[_players removeObjectForKey:playerId];
}
}
/**
Brightness change.
*/
......@@ -133,6 +146,7 @@ SuperPlayerPlugin* instance;
#pragma mark - FlutterPlugin
- (void)applicationWillTerminate:(UIApplication *)application {
FTXLOGV(@"called applicationWillTerminate");
for(id key in self.players) {
id player = self.players[key];
if([player respondsToSelector:@selector(notifyAppTerminate:)]) {
......@@ -260,11 +274,7 @@ SuperPlayerPlugin* instance;
- (void)releasePlayerPlayerId:(nonnull PlayerMsg *)playerId error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
NSNumber *pid = playerId.playerId;
FTXBasePlayer *player = [_players objectForKey:pid];
[player destory];
if (player != nil) {
[_players removeObjectForKey:pid];
}
[self releasePlayerInner:pid];
}
- (void)setConsoleEnabledEnabled:(nonnull BoolMsg *)enabled error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
......@@ -392,6 +402,7 @@ SuperPlayerPlugin* instance;
}
- (void)onLicenceLoaded:(int)result Reason:(NSString *)reason {
FTXLOGV(@"onLicenceLoaded,result:%d, reason:%@", result, reason);
[_eventSink success:[SuperPlayerPlugin getParamsWithEvent:EVENT_ON_LICENCE_LOADED withParams:@{
@(EVENT_RESULT) : @(result),
@(EVENT_REASON) : reason,
......
......@@ -309,9 +309,10 @@ abstract class TXVodPlayEvent {
// PIP UI status changed (only support Android > 31).
// pip UI状态发生变动,only support android > 31
static const EVENT_PIP_MODE_UI_STATE_CHANGED = 4;
// Reset UI (only support iOS).
// 重置UI only support iOS
// Reset UI
// 重置UI,从画中画窗口恢复
static const EVENT_IOS_PIP_MODE_RESTORE_UI = 5;
static const EVENT_PIP_MODE_RESTORE_UI = EVENT_IOS_PIP_MODE_RESTORE_UI;
// Will exit picture-in-picture mode (only support iOS).
// 将要退出画中画 only support iOS
static const EVENT_IOS_PIP_MODE_WILL_EXIT = 6;
......
......@@ -59,7 +59,7 @@ class TXPipController {
* exitAndReleaseCurrentPip must be called, otherwise there may be a obj leak
*/
await exitAndReleaseCurrentPip();
} else if (eventCode == TXVodPlayEvent.EVENT_IOS_PIP_MODE_RESTORE_UI) {
} else if (eventCode == TXVodPlayEvent.EVENT_PIP_MODE_RESTORE_UI) {
_extParams[ARGUMENT_PIP_START_TIME] = event["playTime"];
await exitAndReleaseCurrentPip();
_onJumpToPipPlayer?.call(_extParams);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论