Android 如何将ExoPlayer内部服务与ExoPlayerView内部活动连接起来?

Android 如何将ExoPlayer内部服务与ExoPlayerView内部活动连接起来?,android,pass-by-reference,exoplayer,Android,Pass By Reference,Exoplayer,我想在Google的标准SimpleXoPlayer实现中添加“全屏”按钮。我添加了ImageButton,到目前为止一切正常 然后我决定全屏将以下一种方式工作:按下on按钮后,我用全屏SimpleExoPlayerView打开新的活动,传递视频uri和当前位置,初始化播放器并搜索给定位置。它可以工作,但是播放器重新初始化需要1-3秒,这取决于设备不想要什么 现在我想在intent service中创建一个player实例,并将现有player重新连接到任何想要显示它的视图(预览或全屏视图),如

我想在Google的标准SimpleXoPlayer实现中添加“全屏”按钮。我添加了ImageButton,到目前为止一切正常

然后我决定全屏将以下一种方式工作:按下on按钮后,我用全屏SimpleExoPlayerView打开新的活动,传递视频uri和当前位置,初始化播放器并搜索给定位置。它可以工作,但是播放器重新初始化需要1-3秒,这取决于设备不想要什么

现在我想在intent service中创建一个player实例,并将现有player重新连接到任何想要显示它的视图(预览或全屏视图),如下所示:

mPlayerView.setPlayer(mPlayer);
private MediaPlayer mediaPlayer;

@Override
public IBinder onBind(Intent intent) {
    if (intent.getAction().equals("YOUR_INTENT")) {
        return new LocalBinder();
    }
    return super.onBind(intent);
}

public class LocalBinder extends Binder{
    public AudioService getService(){
        return AudioService.this;
    }
}

public MediaPlayer getMediaPlayer() {
    return mediaPlayer;
}
问题是服务将拥有玩家,而活动将拥有视图。他们中的任何一个都不能同时让玩家观看。作为一种解决方法,我考虑让服务类可以有一个到播放器的静态链接,这样活动就可以通过静态引用获得它。但这似乎有点代码味道,我不知道线程之间的通信是否会出现问题


那么,如何将播放机从服务(不可序列化或打包)传递到活动,或者如何将播放机视图传递到服务?

exoPlayer处理全屏足够好-尝试更改playerView的布局参数,以匹配旋转或按下按钮时的屏幕

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    int width;
    int height;

    View decorView = getWindow().getDecorView();
    int uiOptions;

    if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Resources r = getResources();
        float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 300, r.getDisplayMetrics());
        width = CoordinatorLayout.LayoutParams.MATCH_PARENT;
        height = (int)px;
        uiOptions = View.SYSTEM_UI_FLAG_VISIBLE;
    } else {
        uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
    }

    decorView.setSystemUiVisibility(uiOptions);
    final CoordinatorLayout.LayoutParams lp = new CoordinatorLayout.LayoutParams(width, height);
    mAppBar.setLayoutParams(lp);
}
另外,不要忘记将此项添加到活动清单中,以防止活动重新加载:

android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"

在使用MediaPlayer进行视频播放时,我也遇到了类似的问题。我已使用IBinder绑定到MediaBrowserService,然后获取MediaPlayer实例。在您的服务中,提供一个返回对MediaPlayer的引用的方法。大概是这样的:

mPlayerView.setPlayer(mPlayer);
private MediaPlayer mediaPlayer;

@Override
public IBinder onBind(Intent intent) {
    if (intent.getAction().equals("YOUR_INTENT")) {
        return new LocalBinder();
    }
    return super.onBind(intent);
}

public class LocalBinder extends Binder{
    public AudioService getService(){
        return AudioService.this;
    }
}

public MediaPlayer getMediaPlayer() {
    return mediaPlayer;
}
在活动/片段中,然后使用IBinder绑定到MediaBrowserService。在我的实现中,我使用了MediaPlayer,但我认为它也可以以类似的方式用于Exoplayer

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{

private MediaPlayer mediaPlayer;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private boolean isServiceBounded;
private boolean isSurfaceReady;

private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        isServiceBounded = true;
        mediaPlayer = ((AudioService)service).getMediaPlayer();
        if (isSurfaceReady) {
            mediaPlayer.setDisplay(surfaceHolder);
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        isServiceBounded = false;
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    surfaceView = findViewById(R.id.surfaceView);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);
    bindService(new Intent("YOUR_INTENT"), serviceConnection, BIND_AUTO_CREATE);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    surfaceHolder = holder;
    isSurfaceReady = true;
    if (mediaPlayer != null) {
        mediaPlayer.setDisplay(holder);
    }
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    isSurfaceReady = false;
    if (mediaPlayer != null) {
        mediaPlayer.setDisplay(null);
    }
    surfaceHolder = null;
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unbindService(serviceConnection);
}

}

尝试绑定服务以获取播放器实例。这并不能回答问题。问题是“如何将玩家从服务传递到活动,或者如何将玩家视图传递到服务?”。