Support rtmp

pull/123/head
FongMi 3 years ago
parent 5474a1af50
commit a533d0e0ce
  1. 13
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  2. 2
      app/src/main/java/com/fongmi/android/tv/api/LiveConfig.java
  3. 26
      app/src/main/java/com/fongmi/android/tv/bean/Channel.java
  4. 52
      app/src/main/java/com/fongmi/android/tv/model/LiveViewModel.java
  5. 2
      app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java
  6. 70
      app/src/main/java/com/fongmi/android/tv/player/source/Force.java
  7. 4
      settings.gradle

@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.ItemBridgeAdapter;
import androidx.leanback.widget.OnChildViewHolderSelectedListener;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
@ -20,7 +21,9 @@ import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.databinding.ActivityLiveBinding;
import com.fongmi.android.tv.event.PlayerEvent;
import com.fongmi.android.tv.model.LiveViewModel;
import com.fongmi.android.tv.player.Players;
import com.fongmi.android.tv.player.source.Force;
import com.fongmi.android.tv.ui.custom.CustomKeyDownLive;
import com.fongmi.android.tv.ui.presenter.ChannelPresenter;
import com.fongmi.android.tv.ui.presenter.GroupPresenter;
@ -40,6 +43,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
private ArrayObjectAdapter mChannelAdapter;
private ArrayObjectAdapter mGroupAdapter;
private CustomKeyDownLive mKeyDown;
private LiveViewModel mViewModel;
private Runnable mRunnable;
private Handler mHandler;
private Players mPlayers;
@ -80,6 +84,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
mHandler = new Handler(Looper.getMainLooper());
mKeyDown = CustomKeyDownLive.create(this);
setRecyclerView();
setViewModel();
setVideoView();
getLive();
}
@ -101,6 +106,11 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
mBinding.channel.setAdapter(new ItemBridgeAdapter(mChannelAdapter = new ArrayObjectAdapter(new ChannelPresenter(this))));
}
private void setViewModel() {
mViewModel = new ViewModelProvider(this).get(LiveViewModel.class);
mViewModel.result.observe(this, result -> mPlayers.start(result));
}
private void setVideoView() {
getPlayerView().setPlayer(mPlayers.exo());
getPlayerView().setVisibility(View.VISIBLE);
@ -144,7 +154,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
}
private void getUrl(Channel item) {
mPlayers.start(item);
mViewModel.getUrl(item);
}
private void hideUI() {
@ -293,6 +303,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
protected void onDestroy() {
super.onDestroy();
mPlayers.release();
Force.get().destroy();
EventBus.getDefault().unregister(this);
}
}

@ -91,7 +91,7 @@ public class LiveConfig {
public void parse(Live live) {
try {
if (live.isProxy()) live = new Live(live.getChannels().get(0).getName(), live.getChannels().get(0).getUrl().split("ext=")[1]);
if (live.isProxy()) live = new Live(live.getChannels().get(0).getName(), live.getChannels().get(0).getUrls().get(0).split("ext=")[1]);
if (live.getType() == 0) parse(live, getTxt(live.getUrl()));
if (live.getGroups().size() > 0) lives.add(live);
if (live.getName().equals(config.getHome())) setHome(live);

@ -1,5 +1,6 @@
package com.fongmi.android.tv.bean;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
@ -33,6 +34,7 @@ public class Channel {
private String ua;
private boolean activated;
private String url;
private int line;
public static Channel objectFrom(JsonElement element) {
@ -99,6 +101,14 @@ public class Channel {
this.ua = ua;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getLine() {
return line;
}
@ -127,10 +137,6 @@ public class Channel {
return getLine() == getUrls().size() - 1;
}
public String getUrl() {
return getUrls().get(getLine());
}
public String getLineText() {
return ResUtil.getString(R.string.live_line, getLine() + 1, getUrls().size());
}
@ -150,6 +156,18 @@ public class Channel {
return this;
}
public String getScheme() {
return Uri.parse(getUrls().get(getLine())).getScheme().toLowerCase();
}
public boolean isTVBus() {
return getScheme().equals("tvbus");
}
public boolean isForce() {
return getScheme().startsWith("p") || getScheme().equals("mitv");
}
public Map<String, String> getHeaders() {
HashMap<String, String> map = new HashMap<>();
if (getUa().isEmpty()) return map;

@ -0,0 +1,52 @@
package com.fongmi.android.tv.model;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.player.source.Force;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class LiveViewModel extends ViewModel {
public MutableLiveData<Channel> result;
public ExecutorService executor;
public LiveViewModel() {
this.result = new MutableLiveData<>();
}
public MutableLiveData<Channel> getResult() {
return result;
}
public void getUrl(Channel item) {
execute(() -> {
String url = item.getUrls().get(item.getLine());
if (item.isForce()) item.setUrl(Force.get().fetch(url));
else item.setUrl(url);
return item;
});
}
private void execute(Callable<Channel> callable) {
if (executor != null) executor.shutdownNow();
executor = Executors.newFixedThreadPool(2);
executor.execute(() -> {
try {
if (!Thread.interrupted()) result.postValue(executor.submit(callable).get(5, TimeUnit.SECONDS));
} catch (Throwable e) {
e.printStackTrace();
}
});
}
@Override
protected void onCleared() {
if (executor != null) executor.shutdownNow();
}
}

@ -47,7 +47,7 @@ public class ExoUtil {
private static MediaSource getSource(Map<String, String> headers, String url, int errorCode, List<MediaItem.SubtitleConfiguration> config) {
SpiderDebug.log(errorCode + "," + url + "," + headers);
MediaItem.Builder builder = new MediaItem.Builder().setUri(Uri.parse(url));
MediaItem.Builder builder = new MediaItem.Builder().setUri(Uri.parse(url.trim()));
if (errorCode == PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED) builder.setMimeType(MimeTypes.APPLICATION_OCTET);
else if (errorCode == PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED) builder.setMimeType(MimeTypes.APPLICATION_M3U8);
if (config.size() > 0) builder.setSubtitleConfigurations(config);

@ -0,0 +1,70 @@
package com.fongmi.android.tv.player.source;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.IBinder;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.net.OKHttp;
import com.forcetech.Port;
import com.forcetech.service.ForceService;
import com.gsoft.mitv.MainActivity;
import okhttp3.Headers;
public class Force {
private boolean init;
private static class Loader {
static volatile Force INSTANCE = new Force();
}
public static Force get() {
return Loader.INSTANCE;
}
private void init() {
App.get().bindService(new Intent(App.get(), MainActivity.class), mConn, Context.BIND_AUTO_CREATE);
App.get().bindService(new Intent(App.get(), ForceService.class), mConn, Context.BIND_AUTO_CREATE);
init = true;
}
public void destroy() {
try {
if (init) App.get().unbindService(mConn);
} catch (Exception e) {
e.printStackTrace();
}
}
public String fetch(String url) {
try {
if (!init) init();
int port = Port.get(url);
Uri uri = Uri.parse(url);
String id = uri.getLastPathSegment();
String cmd = "http://127.0.0.1:" + port + "/cmd.xml?cmd=switch_chan&server=" + uri.getHost() + ":" + uri.getPort() + "&id=" + id;
String result = "http://127.0.0.1:" + port + "/" + id;
OKHttp.newCall(cmd, Headers.of("user-agent", "MTV")).execute();
return result;
} catch (Exception e) {
return url;
}
}
private final ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}

@ -15,10 +15,10 @@ dependencyResolutionManagement {
}
}
include ':app'
include ':tvbus'
include ':catvod'
include ':pyramid'
include ':forcetech'
rootProject.name = "TV"
gradle.ext.exoplayerModulePrefix = 'exoplayer-'
apply from: file("/exo/core_settings.gradle")
include ':tvbus'
include ':forcetech'

Loading…
Cancel
Save