Support video wallpaper

pull/594/head
jhengazuki 3 months ago
parent 767bc6d7de
commit 3a85186046
  1. 1
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
  2. 19
      app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseActivity.java
  3. 55
      app/src/main/java/com/fongmi/android/tv/api/config/WallConfig.java
  4. 100
      app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWallView.java
  5. 8
      app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java
  6. 3
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
  7. 19
      app/src/mobile/java/com/fongmi/android/tv/ui/base/BaseActivity.java

@ -297,7 +297,6 @@ public class HomeActivity extends BaseActivity implements CustomTitleView.Listen
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) {
super.onRefreshEvent(event);
switch (event.getType()) {
case CONFIG:
setLogo();

@ -1,7 +1,6 @@
package com.fongmi.android.tv.ui.base;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.widget.ImageView.ScaleType.CENTER_CROP;
import android.app.Activity;
import android.content.res.Configuration;
@ -10,7 +9,6 @@ import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
@ -21,8 +19,7 @@ import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.fongmi.android.tv.api.config.WallConfig;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.ui.custom.CustomWallView;
import com.fongmi.android.tv.utils.Util;
import org.greenrobot.eventbus.EventBus;
@ -34,7 +31,6 @@ import me.jessyan.autosize.AutoSizeCompat;
public abstract class BaseActivity extends AppCompatActivity {
private OnBackInvokedCallback callback;
private ImageView wall;
protected abstract ViewBinding getBinding();
@ -52,7 +48,8 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
public void setContentView(View view) {
super.setContentView(view);
if (customWall()) addWallView();
if (!customWall()) return;
((ViewGroup) findViewById(android.R.id.content)).addView(new CustomWallView(this), 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
protected Activity getActivity() {
@ -94,13 +91,6 @@ public abstract class BaseActivity extends AppCompatActivity {
}
}
private void addWallView() {
wall = new ImageView(this);
wall.setScaleType(CENTER_CROP);
((ViewGroup) findViewById(android.R.id.content)).addView(wall, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
WallConfig.refresh(wall);
}
private Resources hackResources(Resources resources) {
try {
AutoSizeCompat.autoConvertDensityOfGlobal(resources);
@ -111,8 +101,7 @@ public abstract class BaseActivity extends AppCompatActivity {
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) {
if (event.getType() == RefreshEvent.Type.WALL && customWall()) WallConfig.refresh(wall);
public void onSubscribe(Object o) {
}
@Override

@ -1,7 +1,10 @@
package com.fongmi.android.tv.api.config;
import android.net.Uri;
import android.text.TextUtils;
import android.widget.ImageView;
import androidx.media3.common.MediaItem;
import androidx.media3.exoplayer.ExoPlayer;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.R;
@ -10,9 +13,7 @@ import com.fongmi.android.tv.bean.Config;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.utils.FileUtil;
import com.fongmi.android.tv.utils.ImgUtil;
import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.ResUtil;
import com.fongmi.android.tv.utils.UrlUtil;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Path;
@ -24,6 +25,7 @@ import java.util.concurrent.Executors;
public class WallConfig {
private Config config;
private ExoPlayer player;
private ExecutorService executor;
private boolean sync;
@ -49,6 +51,7 @@ public class WallConfig {
}
public WallConfig init() {
createPlayer();
return config(Config.wall());
}
@ -60,6 +63,7 @@ public class WallConfig {
}
public WallConfig clear() {
getPlayer().clearMediaItems();
this.config = null;
return this;
}
@ -68,6 +72,10 @@ public class WallConfig {
return config == null ? Config.wall() : config;
}
public ExoPlayer getPlayer() {
return player == null ? createPlayer() : player;
}
public void load(Callback callback) {
if (executor != null) executor.shutdownNow();
executor = Executors.newSingleThreadExecutor();
@ -76,40 +84,39 @@ public class WallConfig {
private void loadConfig(Callback callback) {
try {
File file = write(FileUtil.getWall(0));
if (Path.exists(file)) refresh(0);
else config(Config.find(VodConfig.get().getWall(), 2));
byte[] data = OkHttp.bytes(UrlUtil.convert(getUrl()));
if (data.length == 0) throw new RuntimeException();
Path.write(FileUtil.getWall(0), data);
App.post(callback::success);
config.update();
refresh(0);
} catch (Throwable e) {
App.post(() -> callback.error(Notify.getError(R.string.error_config_parse, e)));
config(Config.find(VodConfig.get().getWall(), 2));
if (TextUtils.isEmpty(config.getUrl())) App.post(() -> callback.error(""));
else App.post(() -> callback.error(Notify.getError(R.string.error_config_get, e)));
e.printStackTrace();
}
}
private File write(File file) {
if (TextUtils.isEmpty(getUrl())) return file;
Path.write(file, OkHttp.bytes(UrlUtil.convert(getUrl())));
return file;
}
public boolean needSync(String url) {
return sync || TextUtils.isEmpty(config.getUrl()) || url.equals(config.getUrl());
}
private ExoPlayer createPlayer() {
player = new ExoPlayer.Builder(App.get()).build();
player.setRepeatMode(ExoPlayer.REPEAT_MODE_ALL);
player.setPlayWhenReady(true);
player.setVolume(0);
return player;
}
public static void load(File file) {
if (get().getPlayer().getMediaItemCount() > 0) return;
get().getPlayer().setMediaItem(MediaItem.fromUri(Uri.fromFile(file)));
get().getPlayer().prepare();
}
public static void refresh(int index) {
Setting.putWall(index);
RefreshEvent.wall();
}
public static void refresh(ImageView view) {
try {
File file = FileUtil.getWall(Setting.getWall());
if (Path.exists(file)) ImgUtil.load(file, view);
else view.setImageResource(ResUtil.getDrawable(file.getName()));
} catch (Exception e) {
view.setImageResource(R.drawable.wallpaper_1);
}
}
}

@ -0,0 +1,100 @@
package com.fongmi.android.tv.ui.custom;
import static android.widget.ImageView.ScaleType.CENTER_CROP;
import android.content.Context;
import android.media.MediaMetadataRetriever;
import android.widget.FrameLayout;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.media3.ui.AspectRatioFrameLayout;
import androidx.media3.ui.PlayerView;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.api.config.WallConfig;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.utils.FileUtil;
import com.fongmi.android.tv.utils.ImgUtil;
import com.fongmi.android.tv.utils.ResUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.io.File;
public class CustomWallView extends FrameLayout {
private ImageView image;
private PlayerView video;
public CustomWallView(@NonNull Context context) {
super(context);
init(context);
}
private void init(Context context) {
image = new ImageView(context);
image.setScaleType(CENTER_CROP);
video = new PlayerView(context);
video.setUseController(false);
video.setKeepContentOnPlayerReset(true);
video.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM);
addView(image, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addView(video, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
refresh();
}
private boolean isVideo(File file) {
try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
retriever.setDataSource(file.getAbsolutePath());
return "yes".equalsIgnoreCase(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO));
} catch (Exception e) {
return false;
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) {
if (event.getType() == RefreshEvent.Type.WALL) refresh();
}
private void refresh() {
if (Setting.getWall() == 0) load(FileUtil.getWall(Setting.getWall()));
else image.setImageResource(ResUtil.getDrawable("wallpaper_" + Setting.getWall()));
}
private void load(File file) {
if (isVideo(file)) loadVideo(file);
else loadImage(file);
}
private void loadImage(File file) {
video.setPlayer(null);
ImgUtil.load(file, image);
video.setVisibility(GONE);
image.setVisibility(VISIBLE);
WallConfig.get().getPlayer().clearMediaItems();
}
private void loadVideo(File file) {
WallConfig.load(file);
image.setVisibility(GONE);
video.setVisibility(VISIBLE);
image.setImageDrawable(null);
video.setPlayer(WallConfig.get().getPlayer());
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
EventBus.getDefault().unregister(this);
}
}

@ -23,6 +23,7 @@ import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.signature.ObjectKey;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.impl.CustomTarget;
import com.github.catvod.utils.Json;
import com.google.common.net.HttpHeaders;
@ -53,12 +54,17 @@ public class ImgUtil {
}
public static void load(File file, ImageView view) {
Glide.with(view).load(file).diskCacheStrategy(DiskCacheStrategy.NONE).signature(new ObjectKey(file.lastModified())).into(new CustomTarget<Drawable>() {
Glide.with(view).load(file).diskCacheStrategy(DiskCacheStrategy.NONE).error(R.drawable.wallpaper_1).signature(new ObjectKey(file.lastModified())).into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
if (resource instanceof GifDrawable) ((GifDrawable) resource).start();
view.setImageDrawable(resource);
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
view.setImageDrawable(errorDrawable);
}
});
}

@ -171,9 +171,8 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt
mManager.change(position);
}
@Override
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) {
super.onRefreshEvent(event);
if (event.getType().equals(RefreshEvent.Type.CONFIG)) setNavigation();
}

@ -1,7 +1,6 @@
package com.fongmi.android.tv.ui.base;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.widget.ImageView.ScaleType.CENTER_CROP;
import android.app.Activity;
import android.graphics.Color;
@ -11,7 +10,6 @@ import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
@ -19,8 +17,7 @@ import androidx.activity.OnBackPressedCallback;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewbinding.ViewBinding;
import com.fongmi.android.tv.api.config.WallConfig;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.ui.custom.CustomWallView;
import com.fongmi.android.tv.utils.ResUtil;
import org.greenrobot.eventbus.EventBus;
@ -30,7 +27,6 @@ import org.greenrobot.eventbus.ThreadMode;
public abstract class BaseActivity extends AppCompatActivity {
private OnBackInvokedCallback callback;
private ImageView wall;
protected abstract ViewBinding getBinding();
@ -48,7 +44,8 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
public void setContentView(View view) {
super.setContentView(view);
if (customWall()) addWallView();
if (!customWall()) return;
((ViewGroup) findViewById(android.R.id.content)).addView(new CustomWallView(this), 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
protected Activity getActivity() {
@ -117,16 +114,8 @@ public abstract class BaseActivity extends AppCompatActivity {
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
}
private void addWallView() {
wall = new ImageView(this);
wall.setScaleType(CENTER_CROP);
((ViewGroup) findViewById(android.R.id.content)).addView(wall, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
WallConfig.refresh(wall);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) {
if (event.getType() == RefreshEvent.Type.WALL && customWall()) WallConfig.refresh(wall);
public void onSubscribe(Object o) {
}
protected void onBackInvoked() {

Loading…
Cancel
Save