From 1584a3e2748a9c3ade93f291d1569231056453db Mon Sep 17 00:00:00 2001 From: okjackcaptain <378702538@qq.com> Date: Sun, 18 Sep 2022 20:31:20 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A4=96=E9=83=A8=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E5=A2=9E=E5=8A=A0Kodi=20-=20=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E9=80=89=E6=8B=A9=E6=92=AD=E6=94=BE=E5=99=A8?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../osc/player/controller/VodController.java | 76 ++++++++----- .../tvbox/osc/player/thirdparty/Kodi.java | 106 ++++++++++++++++++ .../tvbox/osc/ui/activity/PlayActivity.java | 13 +-- .../osc/ui/fragment/ModelSettingFragment.java | 25 +++-- .../tvbox/osc/ui/fragment/PlayFragment.java | 13 +-- .../github/tvbox/osc/util/PlayerHelper.java | 87 ++++++++++++-- 6 files changed, 253 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/com/github/tvbox/osc/player/thirdparty/Kodi.java diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java index 5809be2b..2c1ca73f 100644 --- a/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java +++ b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java @@ -12,16 +12,17 @@ import android.widget.SeekBar; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DiffUtil; import com.chad.library.adapter.base.BaseQuickAdapter; import com.github.tvbox.osc.R; import com.github.tvbox.osc.api.ApiConfig; import com.github.tvbox.osc.bean.IJKCode; import com.github.tvbox.osc.bean.ParseBean; -import com.github.tvbox.osc.player.thirdparty.MXPlayer; -import com.github.tvbox.osc.player.thirdparty.ReexPlayer; import com.github.tvbox.osc.subtitle.widget.SimpleSubtitleView; import com.github.tvbox.osc.ui.adapter.ParseAdapter; +import com.github.tvbox.osc.ui.adapter.SelectDialogAdapter; +import com.github.tvbox.osc.ui.dialog.SelectDialog; import com.github.tvbox.osc.util.HawkConfig; import com.github.tvbox.osc.util.PlayerHelper; import com.orhanobut.hawk.Hawk; @@ -33,6 +34,7 @@ import org.json.JSONException; import org.json.JSONObject; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.List; import java.util.Date; @@ -334,29 +336,56 @@ public class VodController extends BaseController { // myHandle.postDelayed(myRunnable, myHandleSeconds); try { int playerType = mPlayerConfig.getInt("pl"); - boolean playerVail = false; - do { - playerType++; - if (playerType <= 2) { - playerVail = true; - } else if (playerType == 10) { - playerVail = mxPlayerExist; - } else if (playerType == 11) { - playerVail = reexPlayerExist; - } else if (playerType > 11) { - playerType = 0; - playerVail = true; + int defaultPos = 0; + ArrayList players = PlayerHelper.getExistPlayerTypes(); + ArrayList renders = new ArrayList<>(); + for(int p = 0; p dialog = new SelectDialog<>(mActivity); + dialog.setTip("请选择播放器"); + dialog.setAdapter(new SelectDialogAdapter.SelectDialogInterface() { + @Override + public void click(Integer value, int pos) { + try { + dialog.cancel(); + int thisPlayType = players.get(pos); + if (thisPlayType != playerType) { + mPlayerConfig.put("pl", thisPlayType); + updatePlayerCfgView(); + listener.updatePlayerCfg(); + listener.replay(false); + mPlayerBtn.requestFocus(); +// hideBottom(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public String getDisplay(Integer val) { + Integer playerType = players.get(val); + return PlayerHelper.getPlayerName(playerType); + } + }, new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull @NotNull Integer oldItem, @NonNull @NotNull Integer newItem) { + return oldItem.intValue() == newItem.intValue(); + } + + @Override + public boolean areContentsTheSame(@NonNull @NotNull Integer oldItem, @NonNull @NotNull Integer newItem) { + return oldItem.intValue() == newItem.intValue(); + } + }, renders, defaultPos); + dialog.show(); } catch (JSONException e) { e.printStackTrace(); } - mPlayerBtn.requestFocus(); } }); mPlayerIJKBtn.setOnClickListener(new OnClickListener() { @@ -506,14 +535,9 @@ public class VodController extends BaseController { private JSONObject mPlayerConfig = null; - private boolean mxPlayerExist = false; - private boolean reexPlayerExist = false; - public void setPlayerConfig(JSONObject playerCfg) { this.mPlayerConfig = playerCfg; updatePlayerCfgView(); - mxPlayerExist = MXPlayer.getPackageInfo() != null; - reexPlayerExist = ReexPlayer.getPackageInfo() != null; } void updatePlayerCfgView() { diff --git a/app/src/main/java/com/github/tvbox/osc/player/thirdparty/Kodi.java b/app/src/main/java/com/github/tvbox/osc/player/thirdparty/Kodi.java new file mode 100644 index 00000000..5b06e367 --- /dev/null +++ b/app/src/main/java/com/github/tvbox/osc/player/thirdparty/Kodi.java @@ -0,0 +1,106 @@ +package com.github.tvbox.osc.player.thirdparty; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.util.Log; + +import com.github.tvbox.osc.base.App; + +import java.util.HashMap; + +public class Kodi { + public static final String TAG = "ThirdParty.Kodi"; + + private static final String PACKAGE_NAME = "org.xbmc.kodi"; + private static final String PLAYBACK_ACTIVITY = "org.xbmc.kodi.Splash"; + + private static class KodiPackageInfo { + final String packageName; + final String activityName; + + KodiPackageInfo(String packageName, String activityName) { + this.packageName = packageName; + this.activityName = activityName; + } + } + + private static final KodiPackageInfo[] PACKAGES = { + new KodiPackageInfo(PACKAGE_NAME, PLAYBACK_ACTIVITY), + }; + + /** + * @return null if any Kodi packages not exist. + */ + public static KodiPackageInfo getPackageInfo() { + for (KodiPackageInfo pkg : PACKAGES) { + try { + ApplicationInfo info = App.getInstance().getPackageManager().getApplicationInfo(pkg.packageName, 0); + if (info.enabled) + return pkg; + else + Log.v(TAG, "Kodi package `" + pkg.packageName + "` is disabled."); + } catch (PackageManager.NameNotFoundException ex) { + Log.v(TAG, "Kodi package `" + pkg.packageName + "` does not exist."); + } + } + return null; + } + + private static class Subtitle { + final Uri uri; + String name; + String filename; + + Subtitle(Uri uri) { + if (uri.getScheme() == null) + throw new IllegalStateException("Scheme is missed for subtitle URI " + uri); + + this.uri = uri; + } + + Subtitle(String uriStr) { + this(Uri.parse(uriStr)); + } + } + + + public static boolean run(Activity activity, String url, String title, String subtitle, HashMap headers) { + KodiPackageInfo packageInfo = getPackageInfo(); + if (packageInfo == null) + return false; + + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setPackage(packageInfo.packageName); + intent.setClassName(packageInfo.packageName, packageInfo.activityName); + + intent.setData(Uri.parse(url)); + intent.putExtra("title", title); + intent.putExtra("name", title); + if (headers != null && headers.size() > 0) { + String[] hds = new String[headers.size() * 2]; + int idx = 0; + for (String hk : headers.keySet()) { + hds[idx] = hk; + hds[idx + 1] = headers.get(hk).trim(); + idx += 2; + } + intent.putExtra("headers", headers); + } + + if (subtitle != null && !subtitle.isEmpty()) { + intent.putExtra("subs", subtitle); + } + + try { + activity.startActivity(intent); + return true; + } catch (ActivityNotFoundException ex) { + Log.e(TAG, "Can't run Kodi", ex); + return false; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java index e98b74fa..9b853a33 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java @@ -46,8 +46,6 @@ import com.github.tvbox.osc.cache.CacheManager; import com.github.tvbox.osc.event.RefreshEvent; import com.github.tvbox.osc.player.MyVideoView; import com.github.tvbox.osc.player.controller.VodController; -import com.github.tvbox.osc.player.thirdparty.MXPlayer; -import com.github.tvbox.osc.player.thirdparty.ReexPlayer; import com.github.tvbox.osc.ui.dialog.SearchSubtitleDialog; import com.github.tvbox.osc.ui.dialog.SubtitleDialog; import com.github.tvbox.osc.util.AdBlocker; @@ -300,16 +298,7 @@ public class PlayActivity extends BaseActivity { String playTitle = mVodInfo.name + " " + vs.name; setTip("调用外部播放器" + PlayerHelper.getPlayerName(playerType) + "进行播放", true, false); boolean callResult = false; - switch (playerType) { - case 10: { - callResult = MXPlayer.run(PlayActivity.this, url, playTitle, playSubtitle, headers); - break; - } - case 11: { - callResult = ReexPlayer.run(PlayActivity.this, url, playTitle, playSubtitle, headers); - break; - } - } + callResult = PlayerHelper.runExternalPlayer(playerType, PlayActivity.this, url, playTitle, playSubtitle, headers); setTip("调用外部播放器" + PlayerHelper.getPlayerName(playerType) + (callResult ? "成功" : "失败"), callResult, !callResult); return; } diff --git a/app/src/main/java/com/github/tvbox/osc/ui/fragment/ModelSettingFragment.java b/app/src/main/java/com/github/tvbox/osc/ui/fragment/ModelSettingFragment.java index e95c462f..ed0ede30 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/fragment/ModelSettingFragment.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/fragment/ModelSettingFragment.java @@ -372,24 +372,31 @@ public class ModelSettingFragment extends BaseLazyFragment { @Override public void onClick(View v) { FastClickCheckUtil.check(v); - int defaultPos = Hawk.get(HawkConfig.PLAY_TYPE, 0); - ArrayList players = new ArrayList<>(); - players.add(0); - players.add(1); - players.add(2); + int playerType = Hawk.get(HawkConfig.PLAY_TYPE, 0); + int defaultPos = 0; + ArrayList players = PlayerHelper.getExistPlayerTypes(); + ArrayList renders = new ArrayList<>(); + for(int p = 0; p dialog = new SelectDialog<>(mActivity); dialog.setTip("请选择默认播放器"); dialog.setAdapter(new SelectDialogAdapter.SelectDialogInterface() { @Override public void click(Integer value, int pos) { - Hawk.put(HawkConfig.PLAY_TYPE, value); - tvPlay.setText(PlayerHelper.getPlayerName(value)); + Integer thisPlayerType = players.get(pos); + Hawk.put(HawkConfig.PLAY_TYPE, thisPlayerType); + tvPlay.setText(PlayerHelper.getPlayerName(thisPlayerType)); PlayerHelper.init(); } @Override public String getDisplay(Integer val) { - return PlayerHelper.getPlayerName(val); + Integer playerType = players.get(val); + return PlayerHelper.getPlayerName(playerType); } }, new DiffUtil.ItemCallback() { @Override @@ -401,7 +408,7 @@ public class ModelSettingFragment extends BaseLazyFragment { public boolean areContentsTheSame(@NonNull @NotNull Integer oldItem, @NonNull @NotNull Integer newItem) { return oldItem.intValue() == newItem.intValue(); } - }, players, defaultPos); + }, renders, defaultPos); dialog.show(); } }); diff --git a/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java b/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java index 44e67547..2b12950b 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java @@ -45,8 +45,6 @@ import com.github.tvbox.osc.cache.CacheManager; import com.github.tvbox.osc.event.RefreshEvent; import com.github.tvbox.osc.player.MyVideoView; import com.github.tvbox.osc.player.controller.VodController; -import com.github.tvbox.osc.player.thirdparty.MXPlayer; -import com.github.tvbox.osc.player.thirdparty.ReexPlayer; import com.github.tvbox.osc.ui.dialog.SearchSubtitleDialog; import com.github.tvbox.osc.ui.dialog.SubtitleDialog; import com.github.tvbox.osc.util.AdBlocker; @@ -298,16 +296,7 @@ public class PlayFragment extends BaseLazyFragment { String playTitle = mVodInfo.name + " " + vs.name; setTip("调用外部播放器" + PlayerHelper.getPlayerName(playerType) + "进行播放", true, false); boolean callResult = false; - switch (playerType) { - case 10: { - callResult = MXPlayer.run(requireActivity(), url, playTitle, playSubtitle, headers); - break; - } - case 11: { - callResult = ReexPlayer.run(requireActivity(), url, playTitle, playSubtitle, headers); - break; - } - } + callResult = PlayerHelper.runExternalPlayer(playerType, requireActivity(), url, playTitle, playSubtitle, headers); setTip("调用外部播放器" + PlayerHelper.getPlayerName(playerType) + (callResult ? "成功" : "失败"), callResult, !callResult); return; } diff --git a/app/src/main/java/com/github/tvbox/osc/util/PlayerHelper.java b/app/src/main/java/com/github/tvbox/osc/util/PlayerHelper.java index 65a0a702..11587ced 100644 --- a/app/src/main/java/com/github/tvbox/osc/util/PlayerHelper.java +++ b/app/src/main/java/com/github/tvbox/osc/util/PlayerHelper.java @@ -1,16 +1,23 @@ package com.github.tvbox.osc.util; +import android.app.Activity; import android.content.Context; import com.github.tvbox.osc.api.ApiConfig; import com.github.tvbox.osc.bean.IJKCode; import com.github.tvbox.osc.player.IjkMediaPlayer; import com.github.tvbox.osc.player.render.SurfaceRenderViewFactory; +import com.github.tvbox.osc.player.thirdparty.Kodi; +import com.github.tvbox.osc.player.thirdparty.MXPlayer; +import com.github.tvbox.osc.player.thirdparty.ReexPlayer; import com.orhanobut.hawk.Hawk; import org.json.JSONException; import org.json.JSONObject; +import java.util.ArrayList; +import java.util.HashMap; + import tv.danmaku.ijk.media.player.IjkLibLoader; import xyz.doikki.videoplayer.exo.ExoMediaPlayerFactory; import xyz.doikki.videoplayer.player.AndroidMediaPlayerFactory; @@ -139,19 +146,83 @@ public class PlayerHelper { } public static String getPlayerName(int playType) { - if (playType == 1) { - return "IJK播放器"; - } else if (playType == 2) { - return "Exo播放器"; - } else if (playType == 10) { - return "MXPlayer"; - } else if (playType == 11) { - return "Reex"; + HashMap playersInfo = getPlayersInfo(); + if (playersInfo.containsKey(playType)) { + return playersInfo.get(playType); } else { return "系统播放器"; } } + private static HashMap mPlayersInfo = null; + public static HashMap getPlayersInfo() { + if (mPlayersInfo == null) { + HashMap playersInfo = new HashMap<>(); + playersInfo.put(0, "系统播放器"); + playersInfo.put(1, "IJK播放器"); + playersInfo.put(2, "Exo播放器"); + playersInfo.put(10, "MX播放器"); + playersInfo.put(11, "Reex播放器"); + playersInfo.put(12, "Kodi播放器"); + mPlayersInfo = playersInfo; + } + return mPlayersInfo; + } + + private static HashMap mPlayersExistInfo = null; + public static HashMap getPlayersExistInfo() { + if (mPlayersExistInfo == null) { + HashMap playersExist = new HashMap<>(); + playersExist.put(0, true); + playersExist.put(1, true); + playersExist.put(2, true); + playersExist.put(10, MXPlayer.getPackageInfo() != null); + playersExist.put(11, ReexPlayer.getPackageInfo() != null); + playersExist.put(12, Kodi.getPackageInfo() != null); + mPlayersExistInfo = playersExist; + } + return mPlayersExistInfo; + } + + public static Boolean getPlayerExist(int playType) { + HashMap playersExistInfo = getPlayersExistInfo(); + if (playersExistInfo.containsKey(playType)) { + return playersExistInfo.get(playType); + } else { + return false; + } + } + + public static ArrayList getExistPlayerTypes() { + HashMap playersExistInfo = getPlayersExistInfo(); + ArrayList existPlayers = new ArrayList<>(); + for(Integer playerType : playersExistInfo.keySet()) { + if (playersExistInfo.get(playerType)) { + existPlayers.add(playerType); + } + } + return existPlayers; + } + + public static Boolean runExternalPlayer(int playerType, Activity activity, String url, String title, String subtitle, HashMap headers) { + boolean callResult = false; + switch (playerType) { + case 10: { + callResult = MXPlayer.run(activity, url, title, subtitle, headers); + break; + } + case 11: { + callResult = ReexPlayer.run(activity, url, title, subtitle, headers); + break; + } + case 12: { + callResult = Kodi.run(activity, url, title, subtitle, headers); + break; + } + } + return callResult; + } + public static String getRenderName(int renderType) { if (renderType == 1) { return "SurfaceView";