From 90855f44468dd47ce6b47c540aa73de080ebfcd0 Mon Sep 17 00:00:00 2001 From: lixiaoxiao Date: Tue, 8 Jan 2019 19:56:53 +0800 Subject: [PATCH 1/3] =?UTF-8?q?[fix]=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/chat/base/ChatApplication.java | 4 - .../com/example/chat/base/ConstantUtil.java | 1 - commonlibrary/build.gradle | 4 + .../commonlibrary/BaseApplication.java | 50 +- .../adaptScreen/ScreenAdaptManager.java | 12 +- .../foot/OnLoadMoreScrollListener.java | 3 +- .../bean/video/VideoInfoBean.java | 57 + .../bean/{news => video}/VideoTabBean.java | 2 +- .../customview/CustomWebView.java | 35 + .../commonlibrary/manager/IVideoPlayer.java | 1 + .../manager/video/DefaultVideoController.java | 4 +- .../manager/video/DefaultVideoPlayer.java | 52 +- .../example/commonlibrary/utils/AppUtil.java | 21 + .../example/commonlibrary/utils/Constant.java | 1 + .../commonlibrary/utils/EncryptUtils.java | 1203 +++++++++++++++++ .../example/commonlibrary/utils/FileUtil.java | 3 + config.gradle | 2 +- .../com/example/video/api/OtherNewsApi.java | 1 + video/build.gradle | 22 +- .../java/com/snew/video/api/VideoApi.java | 22 +- .../com/snew/video/base/VideoApplication.java | 3 +- .../interceptor/CacheControlInterceptor.java | 5 +- .../video/mvp/qq/QQVideoListFragment.java | 33 +- .../video/mvp/qq/QQVideoListPresenter.java | 9 +- .../mvp/qq/detail/QQVideoDetailActivity.java | 22 +- .../mvp/qq/detail/QQVideoDetailPresenter.java | 240 ++-- .../snew/video/mvp/video/VideoFragment.java | 2 +- video/src/main/module/AndroidManifest.xml | 9 +- .../java/com/snew/video/VideoActivity.java | 6 +- .../res/layout/fragment_qq_video_list.xml | 20 +- 30 files changed, 1659 insertions(+), 190 deletions(-) create mode 100644 commonlibrary/src/main/java/com/example/commonlibrary/bean/video/VideoInfoBean.java rename commonlibrary/src/main/java/com/example/commonlibrary/bean/{news => video}/VideoTabBean.java (95%) create mode 100644 commonlibrary/src/main/java/com/example/commonlibrary/customview/CustomWebView.java create mode 100644 commonlibrary/src/main/java/com/example/commonlibrary/utils/EncryptUtils.java diff --git a/chat/src/main/java/com/example/chat/base/ChatApplication.java b/chat/src/main/java/com/example/chat/base/ChatApplication.java index 934e9ee..8cab2ae 100644 --- a/chat/src/main/java/com/example/chat/base/ChatApplication.java +++ b/chat/src/main/java/com/example/chat/base/ChatApplication.java @@ -4,8 +4,6 @@ import android.app.Application; import android.content.Context; -import com.example.chat.base.ConstantUtil; -import com.example.chat.base.RandomData; import com.example.chat.bean.CustomInstallation; import com.example.chat.dagger.ChatMainComponent; import com.example.chat.dagger.ChatMainModule; @@ -29,7 +27,6 @@ import java.util.Map; import cn.bmob.push.BmobPush; -import cn.bmob.v3.Bmob; /** * 项目名称: NewFastFrame @@ -57,7 +54,6 @@ public static ChatMainComponent getChatMainComponent() { public void onCreate(Application application) { chatMainComponent = DaggerChatMainComponent.builder().appComponent(BaseApplication.getAppComponent()) .chatMainModule(new ChatMainModule()).build(); - Bmob.initialize(application, ConstantUtil.KEY); // AppStat.i(ConstantUtil.KEY, null); LogUtil.e("1服务器端初始化完成"); CustomInstallation customInstallation = new CustomInstallation(); diff --git a/chat/src/main/java/com/example/chat/base/ConstantUtil.java b/chat/src/main/java/com/example/chat/base/ConstantUtil.java index 3778c25..1946dd2 100644 --- a/chat/src/main/java/com/example/chat/base/ConstantUtil.java +++ b/chat/src/main/java/com/example/chat/base/ConstantUtil.java @@ -109,7 +109,6 @@ public class ConstantUtil { public static final int REQUEST_CODE_SELECT_FROM_LOCAL = 1; public static final int REQUEST_CODE_LOCATION = 5; // 4de21dc60adabe2dff4e81a3a592459f - public static final String KEY = "06cefecaee1c01cac71cb2f7de18dc9c"; /** * 系统通知ID */ diff --git a/commonlibrary/build.gradle b/commonlibrary/build.gradle index 57637a0..6e9d127 100644 --- a/commonlibrary/build.gradle +++ b/commonlibrary/build.gradle @@ -56,6 +56,10 @@ dependencies { api(rootProject.ext.dependencies.support_v4) { exclude module: "support-annotations" } + + + api 'com.danikula:videocache:2.7.1' + api rootProject.ext.dependencies.annotations api rootProject.ext.dependencies.rxjava2 api(rootProject.ext.dependencies.rxjava2_android) { diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/BaseApplication.java b/commonlibrary/src/main/java/com/example/commonlibrary/BaseApplication.java index a9862d7..fd66105 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/BaseApplication.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/BaseApplication.java @@ -8,6 +8,7 @@ import android.view.View; import android.widget.TextView; +import com.danikula.videocache.HttpProxyCacheServer; import com.example.commonlibrary.adaptScreen.ScreenAdaptManager; import com.example.commonlibrary.customview.CommonDialog; import com.example.commonlibrary.dagger.component.AppComponent; @@ -15,13 +16,14 @@ import com.example.commonlibrary.dagger.module.GlobalConfigModule; import com.example.commonlibrary.keeplive.service.JobSchedulerManager; import com.example.commonlibrary.keeplive.service.KeepLiveService; +import com.example.commonlibrary.utils.AppUtil; import com.example.commonlibrary.utils.CommonLogger; import com.example.commonlibrary.utils.Constant; import com.example.commonlibrary.utils.DataCleanUtil; +import com.example.commonlibrary.utils.FileUtil; import com.example.commonlibrary.utils.TimeUtil; import com.example.commonlibrary.utils.ToastUtils; import com.meituan.android.walle.WalleChannelReader; -import com.squareup.leakcanary.LeakCanary; import com.tencent.bugly.Bugly; import com.tencent.bugly.beta.Beta; import com.tencent.bugly.beta.UpgradeInfo; @@ -32,7 +34,10 @@ import com.umeng.analytics.MobclickAgent; import com.umeng.commonsdk.UMConfigure; +import java.io.File; + import androidx.multidex.MultiDex; +import cn.bmob.v3.Bmob; /** * Created by COOTEK on 2017/7/28. @@ -64,12 +69,12 @@ protected void attachBaseContext(Context base) { @Override public void onCreate() { super.onCreate(); - if (LeakCanary.isInAnalyzerProcess(this)) { - // This process is dedicated to LeakCanary for heap analysis. - // You should not init your app in this process. - return; - } - LeakCanary.install(this); + // if (LeakCanary.isInAnalyzerProcess(this)) { + // // This process is dedicated to LeakCanary for heap analysis. + // // You should not init your app in this process. + // return; + // } + // LeakCanary.install(this); instance = this; initDagger(); initFont(); @@ -77,9 +82,32 @@ public void onCreate() { initScreenAdapt(); initBugly(); initKeepLive(); + initBmob(); + initVideoCache(); applicationDelegate.onCreate(this); } + private void initVideoCache() { + proxy = new HttpProxyCacheServer.Builder(BaseApplication.getInstance()) + .maxCacheSize(1024 * 1024 * 1024 * 10L) // 10 Gb for cache + .cacheDirectory(new File(FileUtil.getDefaultCacheFile(this), "video_cache")) + .fileNameGenerator(AppUtil::md5) + .build(); + // proxy = new HttpProxyCacheServer(BaseApplication.getInstance()); + } + + + private static HttpProxyCacheServer proxy; + + public static HttpProxyCacheServer getVideoProxy() { + return proxy; + } + + + private void initBmob() { + Bmob.initialize(this, Constant.KEY); + } + // 保活策略 protected void initKeepLive() { @@ -265,10 +293,10 @@ private void initUM() { } private void initFont() { -// CalligraphyConfig.initDefault(new CalligraphyConfig.Builder() -// .setDefaultFontPath("fonts/PingFang_Medium.ttf") -// .setFontAttrId(R.attr.fontPath) -// .build()); + // CalligraphyConfig.initDefault(new CalligraphyConfig.Builder() + // .setDefaultFontPath("fonts/PingFang_Medium.ttf") + // .setFontAttrId(R.attr.fontPath) + // .build()); } diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/adaptScreen/ScreenAdaptManager.java b/commonlibrary/src/main/java/com/example/commonlibrary/adaptScreen/ScreenAdaptManager.java index 8318fce..0796d2d 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/adaptScreen/ScreenAdaptManager.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/adaptScreen/ScreenAdaptManager.java @@ -170,7 +170,7 @@ private void adaptScreen(Activity activity, boolean isBaseOnWidth, int screenSiz } - private void resetScreen(Activity activity) { + public void resetScreen(Activity activity) { update(activity, adaptInfoMap.get(getKey(true, designedWidth))); } @@ -205,6 +205,13 @@ private void update(Activity activity, AdaptInfo adaptInfo) { } + private static ScreenAdaptManager sInstance; + + + public static ScreenAdaptManager getInstance() { + return sInstance; + } + private static class AdaptInfo { private float density; private int densityDpi; @@ -258,7 +265,8 @@ public Builder designedHeight(int val) { } public ScreenAdaptManager build() { - return new ScreenAdaptManager(this); + sInstance = new ScreenAdaptManager(this); + return sInstance; } } } diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/baseadapter/foot/OnLoadMoreScrollListener.java b/commonlibrary/src/main/java/com/example/commonlibrary/baseadapter/foot/OnLoadMoreScrollListener.java index f48a452..28914e7 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/baseadapter/foot/OnLoadMoreScrollListener.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/baseadapter/foot/OnLoadMoreScrollListener.java @@ -3,7 +3,6 @@ import android.view.View; import com.example.commonlibrary.baseadapter.SuperRecyclerView; -import com.example.commonlibrary.utils.CommonLogger; import androidx.recyclerview.widget.RecyclerView; @@ -13,7 +12,7 @@ public abstract class OnLoadMoreScrollListener extends RecyclerView.OnScrollList @Override public void onScrolled(final RecyclerView recyclerView, int dx, int dy) { if (recyclerView.getLayoutManager().findViewByPosition(0) != null) { - CommonLogger.e("top:" + recyclerView.getLayoutManager().findViewByPosition(0).getTop()); + } } diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/bean/video/VideoInfoBean.java b/commonlibrary/src/main/java/com/example/commonlibrary/bean/video/VideoInfoBean.java new file mode 100644 index 0000000..08d4bbe --- /dev/null +++ b/commonlibrary/src/main/java/com/example/commonlibrary/bean/video/VideoInfoBean.java @@ -0,0 +1,57 @@ +package com.example.commonlibrary.bean.video; + +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Generated; + +/** + * 项目名称: NewFastFrame + * 创建人: 陈锦军 + * 创建时间: 2019/1/8 18:11 + */ +@Entity +public class VideoInfoBean { + @Id + private String path; + + private String name; + + private String url; + + @Generated(hash = 983100739) + public VideoInfoBean(String path, String name, String url) { + this.path = path; + this.name = name; + this.url = url; + } + + @Generated(hash = 2130650952) + public VideoInfoBean() { + } + + public String getPath() { + return this.path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return this.url; + } + + public void setUrl(String url) { + this.url = url; + } + + +} diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/bean/news/VideoTabBean.java b/commonlibrary/src/main/java/com/example/commonlibrary/bean/video/VideoTabBean.java similarity index 95% rename from commonlibrary/src/main/java/com/example/commonlibrary/bean/news/VideoTabBean.java rename to commonlibrary/src/main/java/com/example/commonlibrary/bean/video/VideoTabBean.java index 83da52c..4f990c5 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/bean/news/VideoTabBean.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/bean/video/VideoTabBean.java @@ -1,4 +1,4 @@ -package com.example.commonlibrary.bean.news; +package com.example.commonlibrary.bean.video; import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/customview/CustomWebView.java b/commonlibrary/src/main/java/com/example/commonlibrary/customview/CustomWebView.java new file mode 100644 index 0000000..a6f19ff --- /dev/null +++ b/commonlibrary/src/main/java/com/example/commonlibrary/customview/CustomWebView.java @@ -0,0 +1,35 @@ +package com.example.commonlibrary.customview; + +import android.app.Activity; +import android.content.Context; +import android.util.AttributeSet; +import android.webkit.WebView; + +import com.example.commonlibrary.adaptScreen.ScreenAdaptManager; + +/** + * 项目名称: NewFastFrame + * 创建人: 陈锦军 + * 创建时间: 2019/1/7 16:39 + */ +public class CustomWebView extends WebView { + public CustomWebView(Context context) { + super(context); + } + + public CustomWebView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CustomWebView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + + @Override + public void setOverScrollMode(int mode) { + super.setOverScrollMode(mode); + ScreenAdaptManager.getInstance().resetScreen((Activity) getContext()); + } + +} diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/manager/IVideoPlayer.java b/commonlibrary/src/main/java/com/example/commonlibrary/manager/IVideoPlayer.java index 691c613..99d1777 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/manager/IVideoPlayer.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/manager/IVideoPlayer.java @@ -33,6 +33,7 @@ public interface IVideoPlayer { long getDuration(); + void prepareAsync(); String getTitle(); diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java index a75e4ee..edcd509 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java @@ -313,7 +313,6 @@ private void cancelTimer() { } private void updateProgress() { - CommonLogger.e("updateProgress"); long currentPosition = mIVideoPlayer.getPosition(); long duration = mIVideoPlayer.getDuration(); int buffered = mIVideoPlayer.getBufferedPercentage(); @@ -521,7 +520,8 @@ public void onClick(View v) { clarityContainer.setVisibility(GONE); } else if (id == R.id.tv_view_video_control_error_retry) { if (AppUtil.isNetworkAvailable()) { - mIVideoPlayer.start(); + mIVideoPlayer.reset(); + mIVideoPlayer.prepareAsync(); } else { ToastUtils.showShortToast("网络连接失败,请检查网络配置"); } diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java index 9825c3b..c25e088 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java @@ -16,12 +16,15 @@ import android.widget.FrameLayout; import android.widget.RelativeLayout; +import com.danikula.videocache.CacheListener; import com.example.commonlibrary.BaseApplication; +import com.example.commonlibrary.bean.video.VideoInfoBean; import com.example.commonlibrary.manager.IVideoPlayer; import com.example.commonlibrary.utils.AppUtil; import com.example.commonlibrary.utils.CommonLogger; import com.example.commonlibrary.utils.DensityUtil; +import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; @@ -39,7 +42,7 @@ * 创建人: 陈锦军 * 创建时间: 2018/11/22 11:04 */ -public class DefaultVideoPlayer extends FrameLayout implements IVideoPlayer, TextureView.SurfaceTextureListener, IMediaPlayer.OnPreparedListener, IMediaPlayer.OnInfoListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnVideoSizeChangedListener { +public class DefaultVideoPlayer extends FrameLayout implements IVideoPlayer, TextureView.SurfaceTextureListener, IMediaPlayer.OnPreparedListener, IMediaPlayer.OnInfoListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnVideoSizeChangedListener, CacheListener { private static final int MAX_SWITCH_NUM = 1; IMediaPlayer mMediaPlayer; @@ -123,6 +126,7 @@ public IVideoPlayer setUp(String url, Map headers) { switchNum = 0; this.url = url; this.headers = headers; + BaseApplication.getVideoProxy().unregisterCacheListener(this); return this; } @@ -338,16 +342,16 @@ public void reset() { } mState = PLAY_STATE_IDLE; mVideoController.onPlayStateChanged(mState); - + if (mSurfaceTexture != null) { + mSurfaceTexture.release(); + mSurfaceTexture = null; + } + BaseApplication.getVideoProxy().unregisterCacheListener(this); } @Override public void release() { reset(); - if (mSurfaceTexture != null) { - mSurfaceTexture.release(); - mSurfaceTexture = null; - } container.removeView(defaultTextureView); } @@ -385,15 +389,24 @@ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, } } - private void prepareAsync() { - if (mMediaPlayer == null) + @Override + public void prepareAsync() { + if (mMediaPlayer == null || url == null) return; container.setKeepScreenOn(true); try { mState = PLAY_STATE_PREPARING; mVideoController.onPlayStateChanged(mState); if (AppUtil.isNetworkAvailable()) { - mMediaPlayer.setDataSource(getContext(), Uri.parse(url), headers); + String realUrl; + if (url.startsWith("http")) { + realUrl = BaseApplication.getVideoProxy().getProxyUrl(url); + CommonLogger.e("proxyUrl:" + realUrl); + BaseApplication.getVideoProxy().registerCacheListener(this, url); + }else { + realUrl=url; + } + mMediaPlayer.setDataSource(getContext(), Uri.parse(realUrl), headers); mMediaPlayer.prepareAsync(); } else { mState = PLAY_STATE_ERROR; @@ -492,8 +505,7 @@ public boolean onError(IMediaPlayer iMediaPlayer, int what, int extra) { // 1extra -2147483648 if ((what == 1 && extra == -2147483648) && !url.contains(".mp4") && !url.contains(".m3u8") && switchNum < MAX_SWITCH_NUM) { switchNum++; - switchMediaPlayer(false); - return true; + // switchMediaPlayer(false); } mState = PLAY_STATE_ERROR; mVideoController.onPlayStateChanged(mState); @@ -514,7 +526,7 @@ private void switchMediaPlayer(boolean isCheckAndroid) { @Override public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int percent) { - mBufferedPercent = percent; + // mBufferedPercent = percent; } @Override @@ -529,4 +541,20 @@ public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height, public void setSwitchFlag(boolean isSwitch) { this.isSwitch = isSwitch; } + + @Override + public void onCacheAvailable(File cacheFile, String url, int percentsAvailable) { + CommonLogger.e("缓存文件:" + cacheFile.getAbsolutePath() + "\n" + + "缓存url:" + url + "\n" + + "缓存进度:" + percentsAvailable); + mBufferedPercent = percentsAvailable; + if (percentsAvailable == 100) { + VideoInfoBean videoInfoBean = new VideoInfoBean(); + videoInfoBean.setUrl(url); + videoInfoBean.setPath(cacheFile.getAbsolutePath()); + videoInfoBean.setName(getTitle()); + BaseApplication.getAppComponent().getDaoSession() + .getVideoInfoBeanDao().insertOrReplace(videoInfoBean); + } + } } diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/utils/AppUtil.java b/commonlibrary/src/main/java/com/example/commonlibrary/utils/AppUtil.java index 8e36f93..91cadd8 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/utils/AppUtil.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/utils/AppUtil.java @@ -17,6 +17,8 @@ import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -54,6 +56,25 @@ public static boolean isNetworkAvailable() { } + public static String md5(String string) { + try { + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + byte[] digestBytes = messageDigest.digest(string.getBytes()); + return bytesToHexString(digestBytes); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + } + + private static String bytesToHexString(byte[] bytes) { + StringBuffer sb = new StringBuffer(); + for (byte b : bytes) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } + + public static boolean checkPackInfo(Context context, String packageName) { PackageInfo packageInfo = null; try { diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/utils/Constant.java b/commonlibrary/src/main/java/com/example/commonlibrary/utils/Constant.java index da23a15..ae0c0b6 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/utils/Constant.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/utils/Constant.java @@ -31,6 +31,7 @@ public class Constant { public static final String RECENT_SONG_URL_LIST = "recent_song_list"; public static final String VIEW = "view"; public static final String FLAG = "flag"; + public static final String KEY = "06cefecaee1c01cac71cb2f7de18dc9c"; private static final String BASE_CACHE_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "common" + File.separator; /** * 声音的缓存目录 diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/utils/EncryptUtils.java b/commonlibrary/src/main/java/com/example/commonlibrary/utils/EncryptUtils.java new file mode 100644 index 0000000..e106c87 --- /dev/null +++ b/commonlibrary/src/main/java/com/example/commonlibrary/utils/EncryptUtils.java @@ -0,0 +1,1203 @@ +package com.example.commonlibrary.utils; + +import android.util.Base64; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.DigestInputStream; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.Mac; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * 项目名称: NewFastFrame + * 创建人: 陈锦军 + * 创建时间: 2019/1/8 18:23 + */ +public final class EncryptUtils { + + private EncryptUtils() { + throw new UnsupportedOperationException("u can't instantiate me..."); + } + + /////////////////////////////////////////////////////////////////////////// + // hash encryption + /////////////////////////////////////////////////////////////////////////// + + /** + * Return the hex string of MD2 encryption. + * + * @param data The data. + * @return the hex string of MD2 encryption + */ + public static String encryptMD2ToString(final String data) { + if (data == null || data.length() == 0) return ""; + return encryptMD2ToString(data.getBytes()); + } + + /** + * Return the hex string of MD2 encryption. + * + * @param data The data. + * @return the hex string of MD2 encryption + */ + public static String encryptMD2ToString(final byte[] data) { + return bytes2HexString(encryptMD2(data)); + } + + /** + * Return the bytes of MD2 encryption. + * + * @param data The data. + * @return the bytes of MD2 encryption + */ + public static byte[] encryptMD2(final byte[] data) { + return hashTemplate(data, "MD2"); + } + + /** + * Return the hex string of MD5 encryption. + * + * @param data The data. + * @return the hex string of MD5 encryption + */ + public static String encryptMD5ToString(final String data) { + if (data == null || data.length() == 0) return ""; + return encryptMD5ToString(data.getBytes()); + } + + /** + * Return the hex string of MD5 encryption. + * + * @param data The data. + * @param salt The salt. + * @return the hex string of MD5 encryption + */ + public static String encryptMD5ToString(final String data, final String salt) { + if (data == null && salt == null) return ""; + if (salt == null) return bytes2HexString(encryptMD5(data.getBytes())); + if (data == null) return bytes2HexString(encryptMD5(salt.getBytes())); + return bytes2HexString(encryptMD5((data + salt).getBytes())); + } + + /** + * Return the hex string of MD5 encryption. + * + * @param data The data. + * @return the hex string of MD5 encryption + */ + public static String encryptMD5ToString(final byte[] data) { + return bytes2HexString(encryptMD5(data)); + } + + /** + * Return the hex string of MD5 encryption. + * + * @param data The data. + * @param salt The salt. + * @return the hex string of MD5 encryption + */ + public static String encryptMD5ToString(final byte[] data, final byte[] salt) { + if (data == null && salt == null) return ""; + if (salt == null) return bytes2HexString(encryptMD5(data)); + if (data == null) return bytes2HexString(encryptMD5(salt)); + byte[] dataSalt = new byte[data.length + salt.length]; + System.arraycopy(data, 0, dataSalt, 0, data.length); + System.arraycopy(salt, 0, dataSalt, data.length, salt.length); + return bytes2HexString(encryptMD5(dataSalt)); + } + + /** + * Return the bytes of MD5 encryption. + * + * @param data The data. + * @return the bytes of MD5 encryption + */ + public static byte[] encryptMD5(final byte[] data) { + return hashTemplate(data, "MD5"); + } + + /** + * Return the hex string of file's MD5 encryption. + * + * @param filePath The path of file. + * @return the hex string of file's MD5 encryption + */ + public static String encryptMD5File2String(final String filePath) { + File file = isSpace(filePath) ? null : new File(filePath); + return encryptMD5File2String(file); + } + + /** + * Return the bytes of file's MD5 encryption. + * + * @param filePath The path of file. + * @return the bytes of file's MD5 encryption + */ + public static byte[] encryptMD5File(final String filePath) { + File file = isSpace(filePath) ? null : new File(filePath); + return encryptMD5File(file); + } + + /** + * Return the hex string of file's MD5 encryption. + * + * @param file The file. + * @return the hex string of file's MD5 encryption + */ + public static String encryptMD5File2String(final File file) { + return bytes2HexString(encryptMD5File(file)); + } + + /** + * Return the bytes of file's MD5 encryption. + * + * @param file The file. + * @return the bytes of file's MD5 encryption + */ + public static byte[] encryptMD5File(final File file) { + if (file == null) return null; + FileInputStream fis = null; + DigestInputStream digestInputStream; + try { + fis = new FileInputStream(file); + MessageDigest md = MessageDigest.getInstance("MD5"); + digestInputStream = new DigestInputStream(fis, md); + byte[] buffer = new byte[256 * 1024]; + while (true) { + if (!(digestInputStream.read(buffer) > 0)) break; + } + md = digestInputStream.getMessageDigest(); + return md.digest(); + } catch (NoSuchAlgorithmException | IOException e) { + e.printStackTrace(); + return null; + } finally { + try { + if (fis != null) { + fis.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Return the hex string of SHA1 encryption. + * + * @param data The data. + * @return the hex string of SHA1 encryption + */ + public static String encryptSHA1ToString(final String data) { + if (data == null || data.length() == 0) return ""; + return encryptSHA1ToString(data.getBytes()); + } + + /** + * Return the hex string of SHA1 encryption. + * + * @param data The data. + * @return the hex string of SHA1 encryption + */ + public static String encryptSHA1ToString(final byte[] data) { + return bytes2HexString(encryptSHA1(data)); + } + + /** + * Return the bytes of SHA1 encryption. + * + * @param data The data. + * @return the bytes of SHA1 encryption + */ + public static byte[] encryptSHA1(final byte[] data) { + return hashTemplate(data, "SHA-1"); + } + + /** + * Return the hex string of SHA224 encryption. + * + * @param data The data. + * @return the hex string of SHA224 encryption + */ + public static String encryptSHA224ToString(final String data) { + if (data == null || data.length() == 0) return ""; + return encryptSHA224ToString(data.getBytes()); + } + + /** + * Return the hex string of SHA224 encryption. + * + * @param data The data. + * @return the hex string of SHA224 encryption + */ + public static String encryptSHA224ToString(final byte[] data) { + return bytes2HexString(encryptSHA224(data)); + } + + /** + * Return the bytes of SHA224 encryption. + * + * @param data The data. + * @return the bytes of SHA224 encryption + */ + public static byte[] encryptSHA224(final byte[] data) { + return hashTemplate(data, "SHA224"); + } + + /** + * Return the hex string of SHA256 encryption. + * + * @param data The data. + * @return the hex string of SHA256 encryption + */ + public static String encryptSHA256ToString(final String data) { + if (data == null || data.length() == 0) return ""; + return encryptSHA256ToString(data.getBytes()); + } + + /** + * Return the hex string of SHA256 encryption. + * + * @param data The data. + * @return the hex string of SHA256 encryption + */ + public static String encryptSHA256ToString(final byte[] data) { + return bytes2HexString(encryptSHA256(data)); + } + + /** + * Return the bytes of SHA256 encryption. + * + * @param data The data. + * @return the bytes of SHA256 encryption + */ + public static byte[] encryptSHA256(final byte[] data) { + return hashTemplate(data, "SHA-256"); + } + + /** + * Return the hex string of SHA384 encryption. + * + * @param data The data. + * @return the hex string of SHA384 encryption + */ + public static String encryptSHA384ToString(final String data) { + if (data == null || data.length() == 0) return ""; + return encryptSHA384ToString(data.getBytes()); + } + + /** + * Return the hex string of SHA384 encryption. + * + * @param data The data. + * @return the hex string of SHA384 encryption + */ + public static String encryptSHA384ToString(final byte[] data) { + return bytes2HexString(encryptSHA384(data)); + } + + /** + * Return the bytes of SHA384 encryption. + * + * @param data The data. + * @return the bytes of SHA384 encryption + */ + public static byte[] encryptSHA384(final byte[] data) { + return hashTemplate(data, "SHA-384"); + } + + /** + * Return the hex string of SHA512 encryption. + * + * @param data The data. + * @return the hex string of SHA512 encryption + */ + public static String encryptSHA512ToString(final String data) { + if (data == null || data.length() == 0) return ""; + return encryptSHA512ToString(data.getBytes()); + } + + /** + * Return the hex string of SHA512 encryption. + * + * @param data The data. + * @return the hex string of SHA512 encryption + */ + public static String encryptSHA512ToString(final byte[] data) { + return bytes2HexString(encryptSHA512(data)); + } + + /** + * Return the bytes of SHA512 encryption. + * + * @param data The data. + * @return the bytes of SHA512 encryption + */ + public static byte[] encryptSHA512(final byte[] data) { + return hashTemplate(data, "SHA-512"); + } + + /** + * Return the bytes of hash encryption. + * + * @param data The data. + * @param algorithm The name of hash encryption. + * @return the bytes of hash encryption + */ + private static byte[] hashTemplate(final byte[] data, final String algorithm) { + if (data == null || data.length <= 0) return null; + try { + MessageDigest md = MessageDigest.getInstance(algorithm); + md.update(data); + return md.digest(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + + /////////////////////////////////////////////////////////////////////////// + // hmac encryption + /////////////////////////////////////////////////////////////////////////// + + /** + * Return the hex string of HmacMD5 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacMD5 encryption + */ + public static String encryptHmacMD5ToString(final String data, final String key) { + if (data == null || data.length() == 0 || key == null || key.length() == 0) return ""; + return encryptHmacMD5ToString(data.getBytes(), key.getBytes()); + } + + /** + * Return the hex string of HmacMD5 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacMD5 encryption + */ + public static String encryptHmacMD5ToString(final byte[] data, final byte[] key) { + return bytes2HexString(encryptHmacMD5(data, key)); + } + + /** + * Return the bytes of HmacMD5 encryption. + * + * @param data The data. + * @param key The key. + * @return the bytes of HmacMD5 encryption + */ + public static byte[] encryptHmacMD5(final byte[] data, final byte[] key) { + return hmacTemplate(data, key, "HmacMD5"); + } + + /** + * Return the hex string of HmacSHA1 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA1 encryption + */ + public static String encryptHmacSHA1ToString(final String data, final String key) { + if (data == null || data.length() == 0 || key == null || key.length() == 0) return ""; + return encryptHmacSHA1ToString(data.getBytes(), key.getBytes()); + } + + /** + * Return the hex string of HmacSHA1 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA1 encryption + */ + public static String encryptHmacSHA1ToString(final byte[] data, final byte[] key) { + return bytes2HexString(encryptHmacSHA1(data, key)); + } + + /** + * Return the bytes of HmacSHA1 encryption. + * + * @param data The data. + * @param key The key. + * @return the bytes of HmacSHA1 encryption + */ + public static byte[] encryptHmacSHA1(final byte[] data, final byte[] key) { + return hmacTemplate(data, key, "HmacSHA1"); + } + + /** + * Return the hex string of HmacSHA224 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA224 encryption + */ + public static String encryptHmacSHA224ToString(final String data, final String key) { + if (data == null || data.length() == 0 || key == null || key.length() == 0) return ""; + return encryptHmacSHA224ToString(data.getBytes(), key.getBytes()); + } + + /** + * Return the hex string of HmacSHA224 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA224 encryption + */ + public static String encryptHmacSHA224ToString(final byte[] data, final byte[] key) { + return bytes2HexString(encryptHmacSHA224(data, key)); + } + + /** + * Return the bytes of HmacSHA224 encryption. + * + * @param data The data. + * @param key The key. + * @return the bytes of HmacSHA224 encryption + */ + public static byte[] encryptHmacSHA224(final byte[] data, final byte[] key) { + return hmacTemplate(data, key, "HmacSHA224"); + } + + /** + * Return the hex string of HmacSHA256 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA256 encryption + */ + public static String encryptHmacSHA256ToString(final String data, final String key) { + if (data == null || data.length() == 0 || key == null || key.length() == 0) return ""; + return encryptHmacSHA256ToString(data.getBytes(), key.getBytes()); + } + + /** + * Return the hex string of HmacSHA256 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA256 encryption + */ + public static String encryptHmacSHA256ToString(final byte[] data, final byte[] key) { + return bytes2HexString(encryptHmacSHA256(data, key)); + } + + /** + * Return the bytes of HmacSHA256 encryption. + * + * @param data The data. + * @param key The key. + * @return the bytes of HmacSHA256 encryption + */ + public static byte[] encryptHmacSHA256(final byte[] data, final byte[] key) { + return hmacTemplate(data, key, "HmacSHA256"); + } + + /** + * Return the hex string of HmacSHA384 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA384 encryption + */ + public static String encryptHmacSHA384ToString(final String data, final String key) { + if (data == null || data.length() == 0 || key == null || key.length() == 0) return ""; + return encryptHmacSHA384ToString(data.getBytes(), key.getBytes()); + } + + /** + * Return the hex string of HmacSHA384 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA384 encryption + */ + public static String encryptHmacSHA384ToString(final byte[] data, final byte[] key) { + return bytes2HexString(encryptHmacSHA384(data, key)); + } + + /** + * Return the bytes of HmacSHA384 encryption. + * + * @param data The data. + * @param key The key. + * @return the bytes of HmacSHA384 encryption + */ + public static byte[] encryptHmacSHA384(final byte[] data, final byte[] key) { + return hmacTemplate(data, key, "HmacSHA384"); + } + + /** + * Return the hex string of HmacSHA512 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA512 encryption + */ + public static String encryptHmacSHA512ToString(final String data, final String key) { + if (data == null || data.length() == 0 || key == null || key.length() == 0) return ""; + return encryptHmacSHA512ToString(data.getBytes(), key.getBytes()); + } + + /** + * Return the hex string of HmacSHA512 encryption. + * + * @param data The data. + * @param key The key. + * @return the hex string of HmacSHA512 encryption + */ + public static String encryptHmacSHA512ToString(final byte[] data, final byte[] key) { + return bytes2HexString(encryptHmacSHA512(data, key)); + } + + /** + * Return the bytes of HmacSHA512 encryption. + * + * @param data The data. + * @param key The key. + * @return the bytes of HmacSHA512 encryption + */ + public static byte[] encryptHmacSHA512(final byte[] data, final byte[] key) { + return hmacTemplate(data, key, "HmacSHA512"); + } + + /** + * Return the bytes of hmac encryption. + * + * @param data The data. + * @param key The key. + * @param algorithm The name of hmac encryption. + * @return the bytes of hmac encryption + */ + private static byte[] hmacTemplate(final byte[] data, + final byte[] key, + final String algorithm) { + if (data == null || data.length == 0 || key == null || key.length == 0) return null; + try { + SecretKeySpec secretKey = new SecretKeySpec(key, algorithm); + Mac mac = Mac.getInstance(algorithm); + mac.init(secretKey); + return mac.doFinal(data); + } catch (InvalidKeyException | NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + + /////////////////////////////////////////////////////////////////////////// + // DES encryption + /////////////////////////////////////////////////////////////////////////// + + /** + * Return the Base64-encode bytes of DES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the Base64-encode bytes of DES encryption + */ + public static byte[] encryptDES2Base64(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return base64Encode(encryptDES(data, key, transformation, iv)); + } + + /** + * Return the hex string of DES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the hex string of DES encryption + */ + public static String encryptDES2HexString(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return bytes2HexString(encryptDES(data, key, transformation, iv)); + } + + /** + * Return the bytes of DES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of DES encryption + */ + public static byte[] encryptDES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return symmetricTemplate(data, key, "DES", transformation, iv, true); + } + + /** + * Return the bytes of DES decryption for Base64-encode bytes. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of DES decryption for Base64-encode bytes + */ + public static byte[] decryptBase64DES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return decryptDES(base64Decode(data), key, transformation, iv); + } + + /** + * Return the bytes of DES decryption for hex string. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of DES decryption for hex string + */ + public static byte[] decryptHexStringDES(final String data, + final byte[] key, + final String transformation, + final byte[] iv) { + return decryptDES(hexString2Bytes(data), key, transformation, iv); + } + + /** + * Return the bytes of DES decryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of DES decryption + */ + public static byte[] decryptDES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return symmetricTemplate(data, key, "DES", transformation, iv, false); + } + + /////////////////////////////////////////////////////////////////////////// + // 3DES encryption + /////////////////////////////////////////////////////////////////////////// + + /** + * Return the Base64-encode bytes of 3DES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the Base64-encode bytes of 3DES encryption + */ + public static byte[] encrypt3DES2Base64(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return base64Encode(encrypt3DES(data, key, transformation, iv)); + } + + /** + * Return the hex string of 3DES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the hex string of 3DES encryption + */ + public static String encrypt3DES2HexString(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return bytes2HexString(encrypt3DES(data, key, transformation, iv)); + } + + /** + * Return the bytes of 3DES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of 3DES encryption + */ + public static byte[] encrypt3DES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return symmetricTemplate(data, key, "DESede", transformation, iv, true); + } + + /** + * Return the bytes of 3DES decryption for Base64-encode bytes. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of 3DES decryption for Base64-encode bytes + */ + public static byte[] decryptBase64_3DES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return decrypt3DES(base64Decode(data), key, transformation, iv); + } + + /** + * Return the bytes of 3DES decryption for hex string. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of 3DES decryption for hex string + */ + public static byte[] decryptHexString3DES(final String data, + final byte[] key, + final String transformation, + final byte[] iv) { + return decrypt3DES(hexString2Bytes(data), key, transformation, iv); + } + + /** + * Return the bytes of 3DES decryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of 3DES decryption + */ + public static byte[] decrypt3DES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return symmetricTemplate(data, key, "DESede", transformation, iv, false); + } + + /////////////////////////////////////////////////////////////////////////// + // AES encryption + /////////////////////////////////////////////////////////////////////////// + + /** + * Return the Base64-encode bytes of AES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the Base64-encode bytes of AES encryption + */ + public static byte[] encryptAES2Base64(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return base64Encode(encryptAES(data, key, transformation, iv)); + } + + /** + * Return the hex string of AES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the hex string of AES encryption + */ + public static String encryptAES2HexString(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return bytes2HexString(encryptAES(data, key, transformation, iv)); + } + + /** + * Return the bytes of AES encryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of AES encryption + */ + public static byte[] encryptAES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return symmetricTemplate(data, key, "AES", transformation, iv, true); + } + + /** + * Return the bytes of AES decryption for Base64-encode bytes. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of AES decryption for Base64-encode bytes + */ + public static byte[] decryptBase64AES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return decryptAES(base64Decode(data), key, transformation, iv); + } + + /** + * Return the bytes of AES decryption for hex string. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of AES decryption for hex string + */ + public static byte[] decryptHexStringAES(final String data, + final byte[] key, + final String transformation, + final byte[] iv) { + return decryptAES(hexString2Bytes(data), key, transformation, iv); + } + + /** + * Return the bytes of AES decryption. + * + * @param data The data. + * @param key The key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param iv The buffer with the IV. The contents of the + * buffer are copied to protect against subsequent modification. + * @return the bytes of AES decryption + */ + public static byte[] decryptAES(final byte[] data, + final byte[] key, + final String transformation, + final byte[] iv) { + return symmetricTemplate(data, key, "AES", transformation, iv, false); + } + + /** + * Return the bytes of symmetric encryption or decryption. + * + * @param data The data. + * @param key The key. + * @param algorithm The name of algorithm. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS5Padding. + * @param isEncrypt True to encrypt, false otherwise. + * @return the bytes of symmetric encryption or decryption + */ + private static byte[] symmetricTemplate(final byte[] data, + final byte[] key, + final String algorithm, + final String transformation, + final byte[] iv, + final boolean isEncrypt) { + if (data == null || data.length == 0 || key == null || key.length == 0) return null; + try { + SecretKey secretKey; + if ("DES".equals(algorithm)) { + DESKeySpec desKey = new DESKeySpec(key); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm); + secretKey = keyFactory.generateSecret(desKey); + } else { + secretKey = new SecretKeySpec(key, algorithm); + } + Cipher cipher = Cipher.getInstance(transformation); + if (iv == null || iv.length == 0) { + cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey); + } else { + AlgorithmParameterSpec params = new IvParameterSpec(iv); + cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, secretKey, params); + } + return cipher.doFinal(data); + } catch (Throwable e) { + e.printStackTrace(); + return null; + } + } + + /////////////////////////////////////////////////////////////////////////// + // RSA encryption + /////////////////////////////////////////////////////////////////////////// + + /** + * Return the Base64-encode bytes of RSA encryption. + * + * @param data The data. + * @param key The key. + * @param isPublicKey True to use public key, false to use private key. + * @param transformation The name of the transformation, e.g., RSA/CBC/PKCS1Padding. + * @return the Base64-encode bytes of RSA encryption + */ + public static byte[] encryptRSA2Base64(final byte[] data, + final byte[] key, + final boolean isPublicKey, + final String transformation) { + return base64Encode(encryptRSA(data, key, isPublicKey, transformation)); + } + + /** + * Return the hex string of RSA encryption. + * + * @param data The data. + * @param key The key. + * @param isPublicKey True to use public key, false to use private key. + * @param transformation The name of the transformation, e.g., RSA/CBC/PKCS1Padding. + * @return the hex string of RSA encryption + */ + public static String encryptRSA2HexString(final byte[] data, + final byte[] key, + final boolean isPublicKey, + final String transformation) { + return bytes2HexString(encryptRSA(data, key, isPublicKey, transformation)); + } + + /** + * Return the bytes of RSA encryption. + * + * @param data The data. + * @param key The key. + * @param isPublicKey True to use public key, false to use private key. + * @param transformation The name of the transformation, e.g., RSA/CBC/PKCS1Padding. + * @return the bytes of RSA encryption + */ + public static byte[] encryptRSA(final byte[] data, + final byte[] key, + final boolean isPublicKey, + final String transformation) { + return rsaTemplate(data, key, isPublicKey, transformation, true); + } + + /** + * Return the bytes of RSA decryption for Base64-encode bytes. + * + * @param data The data. + * @param key The key. + * @param isPublicKey True to use public key, false to use private key. + * @param transformation The name of the transformation, e.g., RSA/CBC/PKCS1Padding. + * @return the bytes of RSA decryption for Base64-encode bytes + */ + public static byte[] decryptBase64RSA(final byte[] data, + final byte[] key, + final boolean isPublicKey, + final String transformation) { + return decryptRSA(base64Decode(data), key, isPublicKey, transformation); + } + + /** + * Return the bytes of RSA decryption for hex string. + * + * @param data The data. + * @param key The key. + * @param isPublicKey True to use public key, false to use private key. + * @param transformation The name of the transformation, e.g., RSA/CBC/PKCS1Padding. + * @return the bytes of RSA decryption for hex string + */ + public static byte[] decryptHexStringRSA(final String data, + final byte[] key, + final boolean isPublicKey, + final String transformation) { + return decryptRSA(hexString2Bytes(data), key, isPublicKey, transformation); + } + + /** + * Return the bytes of RSA decryption. + * + * @param data The data. + * @param key The key. + * @param isPublicKey True to use public key, false to use private key. + * @param transformation The name of the transformation, e.g., RSA/CBC/PKCS1Padding. + * @return the bytes of RSA decryption + */ + public static byte[] decryptRSA(final byte[] data, + final byte[] key, + final boolean isPublicKey, + final String transformation) { + return rsaTemplate(data, key, isPublicKey, transformation, false); + } + + /** + * Return the bytes of RSA encryption or decryption. + * + * @param data The data. + * @param key The key. + * @param isPublicKey True to use public key, false to use private key. + * @param transformation The name of the transformation, e.g., DES/CBC/PKCS1Padding. + * @param isEncrypt True to encrypt, false otherwise. + * @return the bytes of RSA encryption or decryption + */ + private static byte[] rsaTemplate(final byte[] data, + final byte[] key, + final boolean isPublicKey, + final String transformation, + final boolean isEncrypt) { + if (data == null || data.length == 0 || key == null || key.length == 0) { + return null; + } + try { + Key rsaKey; + if (isPublicKey) { + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key); + rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec); + } else { + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key); + rsaKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); + } + if (rsaKey == null) return null; + Cipher cipher = Cipher.getInstance(transformation); + cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, rsaKey); + int len = data.length; + int maxLen = isEncrypt ? 117 : 128; + int count = len / maxLen; + if (count > 0) { + byte[] ret = new byte[0]; + byte[] buff = new byte[maxLen]; + int index = 0; + for (int i = 0; i < count; i++) { + System.arraycopy(data, index, buff, 0, maxLen); + ret = joins(ret, cipher.doFinal(buff)); + index += maxLen; + } + if (index != len) { + int restLen = len - index; + buff = new byte[restLen]; + System.arraycopy(data, index, buff, 0, restLen); + ret = joins(ret, cipher.doFinal(buff)); + } + return ret; + } else { + return cipher.doFinal(data); + } + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + } + return null; + } + + /////////////////////////////////////////////////////////////////////////// + // other utils methods + /////////////////////////////////////////////////////////////////////////// + + private static byte[] joins(final byte[] prefix, final byte[] suffix) { + byte[] ret = new byte[prefix.length + suffix.length]; + System.arraycopy(prefix, 0, ret, 0, prefix.length); + System.arraycopy(suffix, 0, ret, prefix.length, suffix.length); + return ret; + } + + private static final char HEX_DIGITS[] = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + private static String bytes2HexString(final byte[] bytes) { + if (bytes == null) return ""; + int len = bytes.length; + if (len <= 0) return ""; + char[] ret = new char[len << 1]; + for (int i = 0, j = 0; i < len; i++) { + ret[j++] = HEX_DIGITS[bytes[i] >> 4 & 0x0f]; + ret[j++] = HEX_DIGITS[bytes[i] & 0x0f]; + } + return new String(ret); + } + + private static byte[] hexString2Bytes(String hexString) { + if (isSpace(hexString)) return null; + int len = hexString.length(); + if (len % 2 != 0) { + hexString = "0" + hexString; + len = len + 1; + } + char[] hexBytes = hexString.toUpperCase().toCharArray(); + byte[] ret = new byte[len >> 1]; + for (int i = 0; i < len; i += 2) { + ret[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1])); + } + return ret; + } + + private static int hex2Dec(final char hexChar) { + if (hexChar >= '0' && hexChar <= '9') { + return hexChar - '0'; + } else if (hexChar >= 'A' && hexChar <= 'F') { + return hexChar - 'A' + 10; + } else { + throw new IllegalArgumentException(); + } + } + + private static byte[] base64Encode(final byte[] input) { + return Base64.encode(input, Base64.NO_WRAP); + } + + private static byte[] base64Decode(final byte[] input) { + return Base64.decode(input, Base64.NO_WRAP); + } + + private static boolean isSpace(final String s) { + if (s == null) return true; + for (int i = 0, len = s.length(); i < len; ++i) { + if (!Character.isWhitespace(s.charAt(i))) { + return false; + } + } + return true; + } +} diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/utils/FileUtil.java b/commonlibrary/src/main/java/com/example/commonlibrary/utils/FileUtil.java index 2275043..9ca577a 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/utils/FileUtil.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/utils/FileUtil.java @@ -41,6 +41,9 @@ public static File getDefaultCacheFile(Context context) { } + + + private static String getCacheFilePath(Context context) { String packageName = context.getPackageName(); return "/mnt/sdcard/" + packageName; diff --git a/config.gradle b/config.gradle index d685652..a71d676 100644 --- a/config.gradle +++ b/config.gradle @@ -1,7 +1,7 @@ ext { - isAlone = false;//false:作为Lib组件存在, true:作为application存在 + isAlone = true;//false:作为Lib组件存在, true:作为application存在 android = [ diff --git a/news/src/main/java/com/example/video/api/OtherNewsApi.java b/news/src/main/java/com/example/video/api/OtherNewsApi.java index 3f19920..5564ec3 100644 --- a/news/src/main/java/com/example/video/api/OtherNewsApi.java +++ b/news/src/main/java/com/example/video/api/OtherNewsApi.java @@ -45,6 +45,7 @@ Observable>> getNewsList(@Path("type") String type ,NewsUtil.CACHE_CONTROL}) @GET("photo/api/set/{photoId}.json") Observable getPhotoSetData(@Path("photoId") String photoId); + @Headers(NewsUtil.CACHE_CONTROL) @GET Observable getPhotoListData(@Url String url); diff --git a/video/build.gradle b/video/build.gradle index ec20b9a..a8782ee 100644 --- a/video/build.gradle +++ b/video/build.gradle @@ -5,6 +5,27 @@ if (rootProject.ext.isAlone) { } android { compileSdkVersion rootProject.ext.android.compileSdkVersion + + packagingOptions { + exclude 'META-INF/DEPENDENCIES.txt' + exclude 'META-INF/NOTICE' + exclude 'META-INF/NOTICE.txt' + exclude 'META-INF/LICENSE' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/rxjava.properties' + exclude 'META-INF/rxjava.PROPERTIES' + exclude 'META-INF/RXJAVA.properties' + exclude 'META-INF/RXJAVA.PROPERTIES' + exclude 'META-INF/rxjava' + exclude 'META-INF/RXJAVA' + exclude 'META-INF/rxjava.properties' + exclude 'META-INF/maven/com.squareup.okhttp3/okhttp/pom.xml' + exclude 'META-INF/maven/com.squareup.okhttp3/okhttp/pom.properties' + exclude 'META-INF/maven/com.squareup.okio/okio/pom.xml' + exclude 'META-INF/maven/com.squareup.okio/okio/pom.properties' + exclude 'META-INF/maven/com.google.code.gson/gson/pom.xml' + exclude 'META-INF/maven/com.google.code.gson/gson/pom.properties' + } compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 @@ -82,7 +103,6 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation files('libs/js.jar') } diff --git a/video/src/main/java/com/snew/video/api/VideoApi.java b/video/src/main/java/com/snew/video/api/VideoApi.java index 56d410c..882559b 100644 --- a/video/src/main/java/com/snew/video/api/VideoApi.java +++ b/video/src/main/java/com/snew/video/api/VideoApi.java @@ -1,17 +1,17 @@ package com.snew.video.api; import com.snew.video.bean.HotVideoBean; -import com.snew.video.bean.OtherVideoDetailBean; -import com.snew.video.bean.QQTVVideoDetailBean; import com.snew.video.bean.QQVideoDetailBean; import com.snew.video.bean.VideoDetailBean; import com.snew.video.bean.VideoListBean; +import com.snew.video.interceptor.CacheControlInterceptor; import io.reactivex.Observable; import okhttp3.RequestBody; import okhttp3.ResponseBody; import retrofit2.http.Body; import retrofit2.http.GET; +import retrofit2.http.Headers; import retrofit2.http.POST; import retrofit2.http.Url; @@ -32,6 +32,8 @@ public interface VideoApi { @GET Observable getCookie(@Url String url); + + @Headers(CacheControlInterceptor.CACHE_CONTROL_NET) @GET Observable getContent(@Url String url); @@ -40,6 +42,7 @@ public interface VideoApi { Observable getOtherCookie(@Url String url, @Body RequestBody requestBody); + @Headers(CacheControlInterceptor.CACHE_CONTROL_NET) @GET Observable getQQVideoListBean(@Url String url); @@ -48,23 +51,26 @@ public interface VideoApi { Observable postUrlInfo(@Url String url, @Body RequestBody requestBody); - @POST - // $.post("api.php", {"id": "1006_43dc5ba04ae343ff97111d83b437f2f4","type": "qqmtv","siteuser": '',"md5": sign($('#hdMd5').val()),"hd":"","lg":""}, - Observable postQQTVUrlInfo(@Url String url, @Body RequestBody requestBody); + // @POST + // $.post("api.php", {"id": "1006_43dc5ba04ae343ff97111d83b437f2f4","type": "qqmtv","siteuser": '',"md5": sign($('#hdMd5').val()),"hd":"","lg":""}, + // Observable postQQTVUrlInfo(@Url String url, @Body RequestBody requestBody); + + @Headers(CacheControlInterceptor.CACHE_CONTROL_NET) @GET Observable getVideoListHeaderData(@Url String url); + @Headers(CacheControlInterceptor.CACHE_CONTROL_NET) @GET Observable getHotVideoData(@Url String url); + + @Headers(CacheControlInterceptor.CACHE_CONTROL_NET) @GET Observable searchVideo(@Url String url); - @POST - Observable postBaiYuUrl(@Url String url, @Body RequestBody requestBody); - + @Headers(CacheControlInterceptor.CACHE_CONTROL_NET) @GET Observable getVarietyDetailInfo(@Url String url); } diff --git a/video/src/main/java/com/snew/video/base/VideoApplication.java b/video/src/main/java/com/snew/video/base/VideoApplication.java index b7fa57c..121483e 100644 --- a/video/src/main/java/com/snew/video/base/VideoApplication.java +++ b/video/src/main/java/com/snew/video/base/VideoApplication.java @@ -6,7 +6,7 @@ import com.example.commonlibrary.BaseApplication; import com.example.commonlibrary.bean.news.OtherNewsTypeBean; -import com.example.commonlibrary.bean.news.VideoTabBean; +import com.example.commonlibrary.bean.video.VideoTabBean; import com.example.commonlibrary.module.IAppLife; import com.example.commonlibrary.router.BaseAction; import com.example.commonlibrary.router.Router; @@ -48,6 +48,7 @@ public void onCreate(Application application) { initDB(application); } + private void initDB(Application application) { if (mMainComponent.getRepositoryManager() .getDaoSession().getOtherNewsTypeBeanDao() diff --git a/video/src/main/java/com/snew/video/interceptor/CacheControlInterceptor.java b/video/src/main/java/com/snew/video/interceptor/CacheControlInterceptor.java index 4f29403..cdf98f8 100644 --- a/video/src/main/java/com/snew/video/interceptor/CacheControlInterceptor.java +++ b/video/src/main/java/com/snew/video/interceptor/CacheControlInterceptor.java @@ -18,7 +18,8 @@ public class CacheControlInterceptor implements Interceptor { private static final long CACHE_STALE_SEC = 60 * 60 * 24L; - public static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_SEC; + public static final String CACHE_CONTROL_NOT_NET = "only-if-cached, max-stale=" + CACHE_STALE_SEC; + public static final String CACHE_CONTROL_NET="Cache-Control: public, max-age=3600"; @Override public Response intercept(Chain chain) throws IOException { @@ -32,7 +33,7 @@ public Response intercept(Chain chain) throws IOException { .build(); } else { return response.newBuilder() - .header("Cache-Control", "public, " + CACHE_CONTROL_CACHE) + .header("Cache-Control", "public, " + CACHE_CONTROL_NOT_NET) .removeHeader("Pragma") .build(); } diff --git a/video/src/main/java/com/snew/video/mvp/qq/QQVideoListFragment.java b/video/src/main/java/com/snew/video/mvp/qq/QQVideoListFragment.java index 07036de..34fe116 100644 --- a/video/src/main/java/com/snew/video/mvp/qq/QQVideoListFragment.java +++ b/video/src/main/java/com/snew/video/mvp/qq/QQVideoListFragment.java @@ -4,6 +4,8 @@ import android.view.View; import com.example.commonlibrary.baseadapter.SuperRecyclerView; +import com.example.commonlibrary.baseadapter.decoration.GridSpaceDecoration; +import com.example.commonlibrary.baseadapter.decoration.ListViewDecoration; import com.example.commonlibrary.baseadapter.empty.EmptyLayout; import com.example.commonlibrary.baseadapter.foot.LoadMoreFooterView; import com.example.commonlibrary.baseadapter.foot.OnLoadMoreListener; @@ -11,10 +13,9 @@ import com.example.commonlibrary.baseadapter.manager.WrappedGridLayoutManager; import com.example.commonlibrary.baseadapter.manager.WrappedLinearLayoutManager; import com.example.commonlibrary.bean.BaseBean; -import com.example.commonlibrary.baseadapter.decoration.GridSpaceDecoration; -import com.example.commonlibrary.baseadapter.decoration.ListViewDecoration; import com.example.commonlibrary.customview.swipe.CustomSwipeRefreshLayout; import com.example.commonlibrary.manager.video.ListVideoManager; +import com.example.commonlibrary.rxbus.event.NetStatusEvent; import com.example.commonlibrary.utils.DensityUtil; import com.snew.video.R; import com.snew.video.adapter.QQVideoListAdapter; @@ -32,6 +33,8 @@ import javax.inject.Inject; +import io.reactivex.functions.Consumer; + /** * 项目名称: NewFastFrame * 创建人: 陈锦军 @@ -78,7 +81,7 @@ protected boolean isNeedHeadLayout() { @Override protected boolean isNeedEmptyLayout() { - return false; + return true; } @@ -126,13 +129,23 @@ public void onItemClick(int position, View view) { } else { id = resultsBean.getId(); } - CommonVideoBean commonVideoBean=new CommonVideoBean(); + CommonVideoBean commonVideoBean = new CommonVideoBean(); commonVideoBean.setVideoType(videoType); commonVideoBean.setId(id); commonVideoBean.setTitle(resultsBean.getFields().getTitle()); commonVideoBean.setImage(resultsBean.getFields().getHorizontal_pic_url()); - commonVideoBean.setUrl(VideoUtil.getParseUrl(resultsBean.getId(),videoUrlType)); - QQVideoDetailActivity.start(getActivity(),commonVideoBean); + commonVideoBean.setUrl(VideoUtil.getParseUrl(resultsBean.getId(), videoUrlType)); + QQVideoDetailActivity.start(getActivity(), commonVideoBean); + } + }); + presenter.registerEvent(NetStatusEvent.class, new Consumer() { + @Override + public void accept(NetStatusEvent netStatusEvent) throws Exception { + if (netStatusEvent.isConnected()) { + if (getLayoutStatus() == EmptyLayout.STATUS_NO_NET) { + updateView(); + } + } } }); @@ -261,7 +274,7 @@ public void updateData(BaseBean baseBean) { @Override public void showLoading(String loadingMsg) { - super.showLoading(loadingMsg); + // super.showLoading(loadingMsg); refresh.setRefreshing(true); } @@ -273,7 +286,11 @@ public void hideLoading() { @Override public void showError(String errorMsg, EmptyLayout.OnRetryListener listener) { - super.showError(errorMsg, listener); + if (refresh.isRefreshing()) { + super.showError(errorMsg, listener); + } else { + ((LoadMoreFooterView) display.getLoadMoreFooterView()).setStatus(LoadMoreFooterView.Status.ERROR); + } refresh.setRefreshing(false); } diff --git a/video/src/main/java/com/snew/video/mvp/qq/QQVideoListPresenter.java b/video/src/main/java/com/snew/video/mvp/qq/QQVideoListPresenter.java index 6bf1da5..866e7bb 100644 --- a/video/src/main/java/com/snew/video/mvp/qq/QQVideoListPresenter.java +++ b/video/src/main/java/com/snew/video/mvp/qq/QQVideoListPresenter.java @@ -1,6 +1,7 @@ package com.snew.video.mvp.qq; import com.example.commonlibrary.BaseApplication; +import com.example.commonlibrary.baseadapter.empty.EmptyLayout; import com.example.commonlibrary.bean.BaseBean; import com.example.commonlibrary.mvp.model.DefaultModel; import com.example.commonlibrary.mvp.presenter.RxBasePresenter; @@ -207,6 +208,7 @@ public void onComplete() { public void getHeaderListData(int videoUrlType, int videoType) { + iView.showLoading(null); Observable observable; if (videoUrlType == VideoUtil.VIDEO_URL_TYPE_QQ) { observable = getQQHeaderData(videoType); @@ -230,7 +232,12 @@ public void onNext(QQVideoTabListBean qqVideoTabListBean) { @Override public void onError(Throwable e) { - iView.showError(e.getMessage(), null); + iView.showError(e.getMessage(), new EmptyLayout.OnRetryListener() { + @Override + public void onRetry() { + getHeaderListData(videoUrlType, videoType); + } + }); } @Override diff --git a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java index cfbc83c..40e3eb8 100644 --- a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java +++ b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java @@ -5,6 +5,7 @@ import android.view.View; import android.widget.TextView; +import com.example.commonlibrary.BaseApplication; import com.example.commonlibrary.baseadapter.SuperRecyclerView; import com.example.commonlibrary.baseadapter.decoration.GridSpaceDecoration; import com.example.commonlibrary.baseadapter.decoration.ListViewDecoration; @@ -12,6 +13,8 @@ import com.example.commonlibrary.baseadapter.manager.WrappedGridLayoutManager; import com.example.commonlibrary.baseadapter.manager.WrappedLinearLayoutManager; import com.example.commonlibrary.bean.BaseBean; +import com.example.commonlibrary.bean.video.VideoInfoBean; +import com.example.commonlibrary.bean.video.VideoInfoBeanDao; import com.example.commonlibrary.customview.ToolBarOption; import com.example.commonlibrary.manager.video.DefaultVideoController; import com.example.commonlibrary.manager.video.DefaultVideoPlayer; @@ -32,6 +35,8 @@ import com.snew.video.mvp.actor.ActorDetailInfoActivity; import com.snew.video.util.VideoUtil; +import java.util.List; + import javax.inject.Inject; import androidx.core.app.ActivityOptionsCompat; @@ -252,7 +257,22 @@ public void updateData(BaseBean o) { VideoUpLoadManager.getInstance().uploadVideoBean(data.getUrl(), getUpLoadTitle(), url); } } else { - display.setState(DefaultVideoPlayer.PLAY_STATE_ERROR); + + // 使用缓存播放 + if (o.getExtraInfo() != null && o.getExtraInfo().equals(data.getUrl())) { + List list = BaseApplication.getAppComponent().getDaoSession() + .getVideoInfoBeanDao().queryBuilder().where(VideoInfoBeanDao.Properties + .Name.eq(title.getText().toString().trim())).build().list(); + if (list.size() > 0) { + display.setUp(list.get(0).getPath(), null); + display.start(); + } else { + display.setState(DefaultVideoPlayer.PLAY_STATE_ERROR); + } + } else { + display.setState(DefaultVideoPlayer.PLAY_STATE_ERROR); + } + } } } diff --git a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java index 62c7629..f2de8e8 100644 --- a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java +++ b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java @@ -14,7 +14,6 @@ import com.example.commonlibrary.utils.CommonLogger; import com.snew.video.api.VideoApi; import com.snew.video.bean.NorVideoDetailBean; -import com.snew.video.bean.QQTVVideoDetailBean; import com.snew.video.bean.QQVideoDetailBean; import com.snew.video.bean.TVPlayBean; import com.snew.video.bean.VarietyDetailResult; @@ -53,73 +52,73 @@ public QQVideoDetailPresenter(IView iView, DefaultModel baseModel) { } - public Observable commonParseUrl(String url) { - //http://api.bbbbbb.me/yunjx/?url= - return Observable.just(url).subscribeOn(Schedulers.io()) - .flatMap(new Function>() { - @Override - public Observable apply(String s) throws Exception { - StringBuilder stringBuilder = new StringBuilder("http://api.bbbbbb.me/yunjxs/?url=").append(s); - Document document = Jsoup.connect(stringBuilder.toString()).get(); - String content = document.outerHtml(); - String parseContent = VideoUtil.getMd5Value(content); - StringBuilder body = new StringBuilder(); - body.append("id=").append(s).append("&type=auto&siteuser=&md5=").append(parseContent) - .append("&hd=&lg="); - RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), body.toString()); - return baseModel.getRepositoryManager().getApi(VideoApi.class) - .postQQTVUrlInfo("http://api.bbbbbb.me/yunjxs/api.php", requestBody1) - .flatMap(new Function>() { - @Override - public Observable apply(QQTVVideoDetailBean qqtvVideoDetailBean) throws Exception { - String ext = qqtvVideoDetailBean.getExt(); - if (ext != null && (ext.equals("mp4") || ext.equals("m3u8"))) { - return Observable.just(qqtvVideoDetailBean.getUrl()); - } else if (ext != null && ext.equals("link")) { - String realUrl = qqtvVideoDetailBean.getUrl().substring(qqtvVideoDetailBean.getUrl().indexOf("url=") + 4); - - return commonParseUrl(realUrl); - } - return null; - } - }) - .subscribeOn(Schedulers.io()); - } - }); - } - - - public void getData(String url) { - commonParseUrl(url).observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer() { - @Override - public void onSubscribe(Disposable d) { - addDispose(d); - } - - @Override - public void onNext(String s) { - String decoderUrl = URLDecoder.decode(s); - BaseBean baseBean = new BaseBean(); - baseBean.setType(VideoUtil.BASE_TYPE_VIDEO_DETAIL_URL); - baseBean.setData(decoderUrl); - // 用于标识当前请求的url - baseBean.setExtraInfo(url); - baseBean.setCode(200); - iView.updateData(baseBean); - } - - @Override - public void onError(Throwable e) { - iView.showError(e.getMessage(), null); - } - - @Override - public void onComplete() { - iView.hideLoading(); - } - }); - } +// public Observable commonParseUrl(String url) { +// //http://api.bbbbbb.me/yunjx/?url= +// return Observable.just(url).subscribeOn(Schedulers.io()) +// .flatMap(new Function>() { +// @Override +// public Observable apply(String s) throws Exception { +// StringBuilder stringBuilder = new StringBuilder("http://api.bbbbbb.me/yunjxs/?url=").append(s); +// Document document = Jsoup.connect(stringBuilder.toString()).get(); +// String content = document.outerHtml(); +// String parseContent = VideoUtil.getMd5Value(content); +// StringBuilder body = new StringBuilder(); +// body.append("id=").append(s).append("&type=auto&siteuser=&md5=").append(parseContent) +// .append("&hd=&lg="); +// RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), body.toString()); +// return baseModel.getRepositoryManager().getApi(VideoApi.class) +// .postQQTVUrlInfo("http://api.bbbbbb.me/yunjxs/api.php", requestBody1) +// .flatMap(new Function>() { +// @Override +// public Observable apply(QQTVVideoDetailBean qqtvVideoDetailBean) throws Exception { +// String ext = qqtvVideoDetailBean.getExt(); +// if (ext != null && (ext.equals("mp4") || ext.equals("m3u8"))) { +// return Observable.just(qqtvVideoDetailBean.getUrl()); +// } else if (ext != null && ext.equals("link")) { +// String realUrl = qqtvVideoDetailBean.getUrl().substring(qqtvVideoDetailBean.getUrl().indexOf("url=") + 4); +// +// return commonParseUrl(realUrl); +// } +// return null; +// } +// }) +// .subscribeOn(Schedulers.io()); +// } +// }); +// } + + +// public void getData(String url) { +// commonParseUrl(url).observeOn(AndroidSchedulers.mainThread()) +// .subscribe(new Observer() { +// @Override +// public void onSubscribe(Disposable d) { +// addDispose(d); +// } +// +// @Override +// public void onNext(String s) { +// String decoderUrl = URLDecoder.decode(s); +// BaseBean baseBean = new BaseBean(); +// baseBean.setType(VideoUtil.BASE_TYPE_VIDEO_DETAIL_URL); +// baseBean.setData(decoderUrl); +// // 用于标识当前请求的url +// baseBean.setExtraInfo(url); +// baseBean.setCode(200); +// iView.updateData(baseBean); +// } +// +// @Override +// public void onError(Throwable e) { +// iView.showError(e.getMessage(), null); +// } +// +// @Override +// public void onComplete() { +// iView.hideLoading(); +// } +// }); +// } public void getDetailData(String url, boolean isSwitch) { @@ -142,12 +141,12 @@ public void onSubscribe(Disposable d) { @Override public void onNext(String string) { - CommonLogger.e("最终url" + string); BaseBean baseBean = new BaseBean(); baseBean.setType(VideoUtil.BASE_TYPE_VIDEO_DETAIL_URL); if (string != null) { string = URLDecoder.decode(string); } + CommonLogger.e("最终url" + string); baseBean.setData(string); baseBean.setCode(200); baseBean.setExtraInfo(url); @@ -174,51 +173,67 @@ public void onComplete() { } private Observable getDetailDataForOne(String url) { - RequestBody requestBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), "url=" + url); - return baseModel.getRepositoryManager().getApi(VideoApi.class) - .postUrlInfo("http://api.bbbbbb.me/zy/sigu.php", requestBody).subscribeOn(Schedulers.io()) - .flatMap((Function>) qqVideoDetailBean -> { - if (qqVideoDetailBean.getCode() == 0) { - String tempUrl = null; - if (qqVideoDetailBean.getPlay().equals("url")) { - if (URLUtil.isValidUrl(qqVideoDetailBean.getUrl())) { - tempUrl = qqVideoDetailBean.getUrl(); - } else { - tempUrl = "http://api.bbbbbb.me" + qqVideoDetailBean.getUrl(); - } - Uri uri; - String key; - String type; - uri = Uri.parse(tempUrl); - key = uri.getQueryParameter("url"); - type = uri.getQueryParameter("type"); - CommonLogger.e("url:" + uri.toString()); - if (key != null && (key.contains(".mp4") || key.contains(".m3u8"))) { - return Observable.just(key); - } - String md5 = VideoUtil.getMd5Value(Jsoup.connect(tempUrl).get().outerHtml()); - StringBuilder body = new StringBuilder(); - if (tempUrl.contains("jiexi/")) { - return getDetailDataForThree(url); - } else if (tempUrl.contains("yunjxs") || tempUrl.contains("qqmtv")) { - md5 = VideoUtil.getSignedValue(md5); - body.append("id=").append(key).append("&type=").append(TextUtils.isEmpty(type) ? "auto" : type).append("&siteuser=&md5=").append(md5) - .append("&hd=&lg="); - } else if (tempUrl.contains("anlehe")) { - return getDetailDataForThree(url); + return Observable.just(url).subscribeOn(Schedulers.io()).flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { +// https://api.bbbbbb.me/zy/?url=https://v.qq.com/x/cover/2j5kilwvtepehti.html + StringBuilder stringBuilder=new StringBuilder("https://api.bbbbbb.me/zy/?url="); + stringBuilder.append(s); + Document document=Jsoup.connect(stringBuilder.toString().trim()).get(); +// start : url":" end: ","type + String start="url\":\""; + String end="\",\"type"; + String content = document.outerHtml(); + int startIndex = content.indexOf(start); + String url1 = content.substring(startIndex + start.length(), content.lastIndexOf(end)).trim(); + RequestBody requestBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), "url=" + url1); + return baseModel.getRepositoryManager().getApi(VideoApi.class) + .postUrlInfo("http://api.bbbbbb.me/zy/sigu.php", requestBody).subscribeOn(Schedulers.io()) + .flatMap((Function>) qqVideoDetailBean -> { + if (qqVideoDetailBean.getCode() == 0) { + String tempUrl = null; + if (qqVideoDetailBean.getPlay().equals("url")) { + if (URLUtil.isValidUrl(qqVideoDetailBean.getUrl())) { + tempUrl = qqVideoDetailBean.getUrl(); + } else { + tempUrl = "http://api.bbbbbb.me" + qqVideoDetailBean.getUrl(); + } + Uri uri; + String key; + String type; + uri = Uri.parse(tempUrl); + key = uri.getQueryParameter("url"); + type = uri.getQueryParameter("type"); + CommonLogger.e("url:" + uri.toString()); + if (key != null && (key.contains(".mp4") || key.contains(".m3u8"))) { + return Observable.just(key); + } + + String md5 = VideoUtil.getMd5Value(Jsoup.connect(tempUrl).get().outerHtml()); + StringBuilder body = new StringBuilder(); + if (tempUrl.contains("jiexi/")) { + return getDetailDataForThree(url); + } else if (tempUrl.contains("yunjxs") || tempUrl.contains("qqmtv")) { + md5 = VideoUtil.getSignedValue(md5); + body.append("id=").append(key).append("&type=").append(TextUtils.isEmpty(type) ? "auto" : type).append("&siteuser=&md5=").append(md5) + .append("&hd=&lg="); + } else if (tempUrl.contains("anlehe")) { + return getDetailDataForThree(url); + } + RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), body.toString()); + return baseModel.getRepositoryManager().getApi(VideoApi.class) + .postUrlInfo(tempUrl.substring(0, tempUrl.indexOf("?")) + "api.php", requestBody1) + .map(qqVideoDetailBean1 -> qqVideoDetailBean1.getUrl()).subscribeOn(Schedulers.io()); + } else if (qqVideoDetailBean.getPlay().equals("normal") + || qqVideoDetailBean.getPlay().equals("hls")) { + return Observable.just(qqVideoDetailBean.getUrl()); + } } - RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), body.toString()); - return baseModel.getRepositoryManager().getApi(VideoApi.class) - .postUrlInfo(tempUrl.substring(0, tempUrl.indexOf("?")) + "api.php", requestBody1) - .map(qqVideoDetailBean1 -> qqVideoDetailBean1.getUrl()).subscribeOn(Schedulers.io()); - } else if (qqVideoDetailBean.getPlay().equals("normal") - ||qqVideoDetailBean.getPlay().equals("hls")) { - return Observable.just(qqVideoDetailBean.getUrl()); - } - } - return getDetailDataForThree(url); - }); + return getDetailDataForThree(url); + }); + } + }); } private Observable getDetailDataForTwo(String url) { @@ -476,7 +491,6 @@ private Observable getVarietyDetailInfo(String url, String VarietyDetailResult varietyDetailResult = BaseApplication.getAppComponent().getGson().fromJson(body.substring(0, body.length() - 1) , VarietyDetailResult.class); - if (varietyDetailResult.getJsonvalue() != null && varietyDetailResult.getJsonvalue().getResults() != null && varietyDetailResult.getJsonvalue().getResults().size() > 0) { diff --git a/video/src/main/java/com/snew/video/mvp/video/VideoFragment.java b/video/src/main/java/com/snew/video/mvp/video/VideoFragment.java index f7d5ae0..68a7378 100644 --- a/video/src/main/java/com/snew/video/mvp/video/VideoFragment.java +++ b/video/src/main/java/com/snew/video/mvp/video/VideoFragment.java @@ -1,7 +1,7 @@ package com.snew.video.mvp.video; import com.example.commonlibrary.baseadapter.adapter.ViewPagerAdapter; -import com.example.commonlibrary.bean.news.VideoTabBean; +import com.example.commonlibrary.bean.video.VideoTabBean; import com.example.commonlibrary.customview.ToolBarOption; import com.example.commonlibrary.customview.WrappedViewPager; import com.google.android.material.tabs.TabLayout; diff --git a/video/src/main/module/AndroidManifest.xml b/video/src/main/module/AndroidManifest.xml index 99d32ad..3b5c7a8 100644 --- a/video/src/main/module/AndroidManifest.xml +++ b/video/src/main/module/AndroidManifest.xml @@ -20,17 +20,20 @@ android:theme="@style/CustomTheme"> - + - + + diff --git a/video/src/main/module/java/com/snew/video/VideoActivity.java b/video/src/main/module/java/com/snew/video/VideoActivity.java index b7da872..351cd86 100644 --- a/video/src/main/module/java/com/snew/video/VideoActivity.java +++ b/video/src/main/module/java/com/snew/video/VideoActivity.java @@ -1,7 +1,9 @@ package com.snew.video; +import com.example.commonlibrary.manager.video.ListVideoManager; import com.snew.video.base.VideoBaseActivity; -import com.snew.video.mvp.video.VideoFragment; +import com.snew.video.mvp.qq.QQVideoFragment; +import com.snew.video.util.VideoUtil; /** * 项目名称: NewFastFrame @@ -39,7 +41,7 @@ protected void initView() { @Override protected void initData() { - addOrReplaceFragment(VideoFragment.newInstance(), R.id.fl_activity_video_container); + addOrReplaceFragment(QQVideoFragment.newInstance(VideoUtil.VIDEO_URL_TYPE_QQ), R.id.fl_activity_video_container); } @Override diff --git a/video/src/main/res/layout/fragment_qq_video_list.xml b/video/src/main/res/layout/fragment_qq_video_list.xml index 0a4b314..0e66d3a 100644 --- a/video/src/main/res/layout/fragment_qq_video_list.xml +++ b/video/src/main/res/layout/fragment_qq_video_list.xml @@ -1,19 +1,13 @@ - + android:layout_height="match_parent"> - + android:layout_height="match_parent" /> + - - - - \ No newline at end of file From fb3eea4153c09816859c6e26fd2ce0ca16b9f019 Mon Sep 17 00:00:00 2001 From: lixiaoxiao Date: Thu, 17 Jan 2019 16:01:28 +0800 Subject: [PATCH 2/3] [fix] --- .../dagger/module/GlobalConfigModule.java | 4 +- .../manager/video/DefaultVideoController.java | 5 +- .../manager/video/DefaultVideoPlayer.java | 32 ++- .../net/{ => okhttpconfig}/TrustAllCerts.java | 2 +- .../commonlibrary/skin/SkinManager.java | 4 +- config.gradle | 2 +- .../java/com/snew/video/MainActivity.java | 1 + .../java/com/snew/video/bean/VideoBean.java | 4 + .../dagger/preview/PreViewVideoComponent.java | 18 ++ .../dagger/preview/PreViewVideoModule.java | 35 +++ .../mvp/preview/PreViewVideoFragment.java | 120 +++++++++ .../mvp/preview/PreViewVideoPresenter.java | 90 +++++++ .../snew/video/mvp/qq/QQVideoFragment.java | 35 ++- .../mvp/qq/detail/QQVideoDetailActivity.java | 35 ++- .../mvp/qq/detail/QQVideoDetailPresenter.java | 240 ++++++++---------- video/src/main/module/AndroidManifest.xml | 1 + .../java/com/snew/video/VideoActivity.java | 65 ++++- .../main/module/res/layout/activity_video.xml | 9 +- .../res/layout/activity_preview_video.xml | 17 ++ .../layout/item_fragment_qq_video_list.xml | 1 - .../res/layout/view_activity_video_header.xml | 28 ++ 21 files changed, 545 insertions(+), 203 deletions(-) rename commonlibrary/src/main/java/com/example/commonlibrary/net/{ => okhttpconfig}/TrustAllCerts.java (96%) create mode 100644 video/src/main/java/com/snew/video/dagger/preview/PreViewVideoComponent.java create mode 100644 video/src/main/java/com/snew/video/dagger/preview/PreViewVideoModule.java create mode 100644 video/src/main/java/com/snew/video/mvp/preview/PreViewVideoFragment.java create mode 100644 video/src/main/java/com/snew/video/mvp/preview/PreViewVideoPresenter.java create mode 100644 video/src/main/res/layout/activity_preview_video.xml create mode 100644 video/src/main/res/layout/view_activity_video_header.xml diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/dagger/module/GlobalConfigModule.java b/commonlibrary/src/main/java/com/example/commonlibrary/dagger/module/GlobalConfigModule.java index c0a5454..5b328b1 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/dagger/module/GlobalConfigModule.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/dagger/module/GlobalConfigModule.java @@ -13,7 +13,7 @@ import com.example.commonlibrary.manager.ActivityManager; import com.example.commonlibrary.mvp.model.DefaultModel; import com.example.commonlibrary.net.OkHttpGlobalHandler; -import com.example.commonlibrary.net.TrustAllCerts; +import com.example.commonlibrary.net.okhttpconfig.TrustAllCerts; import com.example.commonlibrary.repository.DefaultRepositoryManager; import com.example.commonlibrary.utils.Constant; import com.example.commonlibrary.utils.FileUtil; @@ -109,7 +109,7 @@ public OkHttpClient.Builder provideOkHttpBuilder(@Nullable final OkHttpGlobalHan OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS); // 自定义签名证书 - // builder.sslSocketFactory(SSLConfig.getSSLSocketFactory(BaseApplication.getInstance()), (X509TrustManager) Objects.requireNonNull(SSLConfig.getTrustManager(BaseApplication.getInstance()))); +// builder.sslSocketFactory(SSLConfig.getSSLSocketFactory(BaseApplication.getInstance()), (X509TrustManager) Objects.requireNonNull(SSLConfig.getTrustManager(BaseApplication.getInstance()))); builder.sslSocketFactory(TrustAllCerts.createSSLSocketFactory()); builder.hostnameVerifier(new TrustAllCerts.TrustAllHostnameVerifier()); if (tokenInterceptor != null) { diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java index edcd509..4f1e97c 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoController.java @@ -512,7 +512,6 @@ public void onClick(View v) { } else if (id == R.id.ll_view_video_control_restart) { finishContainer.setVisibility(GONE); mIVideoPlayer.release(); - mIVideoPlayer.setState(DefaultVideoPlayer.PLAY_STATE_PREPARING); mIVideoPlayer.start(); } else if (id == R.id.ll_view_video_control_share) { ToastUtils.showShortToast("分享功能"); @@ -520,8 +519,8 @@ public void onClick(View v) { clarityContainer.setVisibility(GONE); } else if (id == R.id.tv_view_video_control_error_retry) { if (AppUtil.isNetworkAvailable()) { - mIVideoPlayer.reset(); - mIVideoPlayer.prepareAsync(); + mIVideoPlayer.release(); + mIVideoPlayer.start(); } else { ToastUtils.showShortToast("网络连接失败,请检查网络配置"); } diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java index c25e088..2ec36b6 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/manager/video/DefaultVideoPlayer.java @@ -140,6 +140,7 @@ public void setState(int state) { @Override public void start() { + CommonLogger.e("start"); ListVideoManager.getInstance().setCurrentPlayer(this); if (mState == PLAY_STATE_IDLE || mState == PLAY_STATE_PREPARING) { initMediaPlayer(); @@ -153,7 +154,7 @@ public void start() { innerStart(mMediaPlayer.getCurrentPosition()); } else if (getCurrentState() == PLAY_STATE_ERROR || getCurrentState() == PLAY_STATE_FINISH) { reset(); - prepareAsync(); + start(); } else if (getCurrentState() == PLAY_STATE_PLAYING || getCurrentState() == PLAY_STATE_BUFFERING_PLAYING) { } @@ -353,6 +354,10 @@ public void reset() { public void release() { reset(); container.removeView(defaultTextureView); + if (mMediaPlayer != null) { + mMediaPlayer.release(); + mMediaPlayer = null; + } } @Override @@ -391,6 +396,7 @@ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, @Override public void prepareAsync() { + CommonLogger.e("prepareAsync"); if (mMediaPlayer == null || url == null) return; container.setKeepScreenOn(true); @@ -398,15 +404,16 @@ public void prepareAsync() { mState = PLAY_STATE_PREPARING; mVideoController.onPlayStateChanged(mState); if (AppUtil.isNetworkAvailable()) { - String realUrl; - if (url.startsWith("http")) { - realUrl = BaseApplication.getVideoProxy().getProxyUrl(url); - CommonLogger.e("proxyUrl:" + realUrl); - BaseApplication.getVideoProxy().registerCacheListener(this, url); - }else { - realUrl=url; - } - mMediaPlayer.setDataSource(getContext(), Uri.parse(realUrl), headers); + // String realUrl; + // if (url.startsWith("http")) { + // realUrl = BaseApplication.getVideoProxy().getProxyUrl(url); + // CommonLogger.e("proxyUrl:" + realUrl); + // BaseApplication.getVideoProxy().registerCacheListener(this, url); + // } else { + // realUrl = url; + // mBufferedPercent = 100; + // } + mMediaPlayer.setDataSource(getContext(), Uri.parse(url), headers); mMediaPlayer.prepareAsync(); } else { mState = PLAY_STATE_ERROR; @@ -443,6 +450,7 @@ private void innerStart(long position) { @Override public void onPrepared(IMediaPlayer iMediaPlayer) { + CommonLogger.e("onPrepared"); mState = PLAY_STATE_PREPARED; mVideoController.onPlayStateChanged(mState); long position = 0; @@ -505,7 +513,7 @@ public boolean onError(IMediaPlayer iMediaPlayer, int what, int extra) { // 1extra -2147483648 if ((what == 1 && extra == -2147483648) && !url.contains(".mp4") && !url.contains(".m3u8") && switchNum < MAX_SWITCH_NUM) { switchNum++; - // switchMediaPlayer(false); + switchMediaPlayer(false); } mState = PLAY_STATE_ERROR; mVideoController.onPlayStateChanged(mState); @@ -526,7 +534,7 @@ private void switchMediaPlayer(boolean isCheckAndroid) { @Override public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int percent) { - // mBufferedPercent = percent; + mBufferedPercent = percent; } @Override diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/net/TrustAllCerts.java b/commonlibrary/src/main/java/com/example/commonlibrary/net/okhttpconfig/TrustAllCerts.java similarity index 96% rename from commonlibrary/src/main/java/com/example/commonlibrary/net/TrustAllCerts.java rename to commonlibrary/src/main/java/com/example/commonlibrary/net/okhttpconfig/TrustAllCerts.java index 8bbe7d1..0d75cd7 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/net/TrustAllCerts.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/net/okhttpconfig/TrustAllCerts.java @@ -1,4 +1,4 @@ -package com.example.commonlibrary.net; +package com.example.commonlibrary.net.okhttpconfig; import java.security.SecureRandom; import java.security.cert.CertificateException; diff --git a/commonlibrary/src/main/java/com/example/commonlibrary/skin/SkinManager.java b/commonlibrary/src/main/java/com/example/commonlibrary/skin/SkinManager.java index 5dfda92..eb15017 100644 --- a/commonlibrary/src/main/java/com/example/commonlibrary/skin/SkinManager.java +++ b/commonlibrary/src/main/java/com/example/commonlibrary/skin/SkinManager.java @@ -15,7 +15,6 @@ import com.example.commonlibrary.net.download.DownloadListener; import com.example.commonlibrary.rxbus.RxBusManager; import com.example.commonlibrary.rxbus.event.SkinUpdateEvent; -import com.example.commonlibrary.utils.CommonLogger; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -84,7 +83,7 @@ public void loadSkinResource(String path, final DownloadListener listener) { public void updateSkin(String path,SkinUpdateListener skinUpdateListener) { try { - CommonLogger.e("path:" +path); + PackageInfo packageInfo = context.getPackageManager().getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES); packageName = packageInfo.packageName; isLocal = false; @@ -158,7 +157,6 @@ public Drawable getDrawable(int resId) { public ColorStateList getColorStateList(int resId) { if (isLocal) { - CommonLogger.e("放回本地"); return ContextCompat.getColorStateList(context, resId); } int id = resources.getIdentifier(context.getResources().getResourceEntryName(resId), "color", packageName); diff --git a/config.gradle b/config.gradle index a71d676..d685652 100644 --- a/config.gradle +++ b/config.gradle @@ -1,7 +1,7 @@ ext { - isAlone = true;//false:作为Lib组件存在, true:作为application存在 + isAlone = false;//false:作为Lib组件存在, true:作为application存在 android = [ diff --git a/video/src/main/java/com/snew/video/MainActivity.java b/video/src/main/java/com/snew/video/MainActivity.java index afb594b..cc7de0a 100644 --- a/video/src/main/java/com/snew/video/MainActivity.java +++ b/video/src/main/java/com/snew/video/MainActivity.java @@ -45,6 +45,7 @@ protected boolean needStatusPadding() { protected void initData() { addOrReplaceFragment(QQVideoFragment.newInstance(VideoUtil.VIDEO_URL_TYPE_QQ), R.id.fl_activity_video_container); // addOrReplaceFragment(UpdateVideoFragment.newInstance(), R.id.fl_activity_video_container); + } @Override diff --git a/video/src/main/java/com/snew/video/bean/VideoBean.java b/video/src/main/java/com/snew/video/bean/VideoBean.java index d748670..8f4c119 100644 --- a/video/src/main/java/com/snew/video/bean/VideoBean.java +++ b/video/src/main/java/com/snew/video/bean/VideoBean.java @@ -38,6 +38,10 @@ public VideoBean(String title, String url) { this(title, 0, null, url); } + public VideoBean() { + + } + @Override public boolean equals(@Nullable Object obj) { diff --git a/video/src/main/java/com/snew/video/dagger/preview/PreViewVideoComponent.java b/video/src/main/java/com/snew/video/dagger/preview/PreViewVideoComponent.java new file mode 100644 index 0000000..bc66175 --- /dev/null +++ b/video/src/main/java/com/snew/video/dagger/preview/PreViewVideoComponent.java @@ -0,0 +1,18 @@ +package com.snew.video.dagger.preview; + +import com.example.commonlibrary.dagger.scope.PerFragment; +import com.snew.video.dagger.VideoComponent; +import com.snew.video.mvp.preview.PreViewVideoFragment; + +import dagger.Component; + +/** + * 项目名称: NewFastFrame + * 创建人: 陈锦军 + * 创建时间: 2019/1/9 16:17 + */ +@PerFragment +@Component(dependencies = VideoComponent.class, modules = PreViewVideoModule.class) +public interface PreViewVideoComponent { + public void inject(PreViewVideoFragment preViewVideoActivity); +} diff --git a/video/src/main/java/com/snew/video/dagger/preview/PreViewVideoModule.java b/video/src/main/java/com/snew/video/dagger/preview/PreViewVideoModule.java new file mode 100644 index 0000000..b8e0351 --- /dev/null +++ b/video/src/main/java/com/snew/video/dagger/preview/PreViewVideoModule.java @@ -0,0 +1,35 @@ +package com.snew.video.dagger.preview; + +import com.example.commonlibrary.mvp.model.DefaultModel; +import com.snew.video.adapter.QQVideoListAdapter; +import com.snew.video.mvp.preview.PreViewVideoFragment; +import com.snew.video.mvp.preview.PreViewVideoPresenter; + +import dagger.Module; +import dagger.Provides; + +/** + * 项目名称: NewFastFrame + * 创建人: 陈锦军 + * 创建时间: 2019/1/9 16:17 + */ +@Module +public class PreViewVideoModule { + private PreViewVideoFragment mPreViewVideoActivity; + + public PreViewVideoModule(PreViewVideoFragment preViewVideoActivity) { + mPreViewVideoActivity = preViewVideoActivity; + } + + + @Provides + public PreViewVideoPresenter providePresenter(DefaultModel defaultModel) { + return new PreViewVideoPresenter(mPreViewVideoActivity, defaultModel); + } + + + @Provides + public QQVideoListAdapter provideAdapter(){ + return new QQVideoListAdapter(); + } +} diff --git a/video/src/main/java/com/snew/video/mvp/preview/PreViewVideoFragment.java b/video/src/main/java/com/snew/video/mvp/preview/PreViewVideoFragment.java new file mode 100644 index 0000000..5511d69 --- /dev/null +++ b/video/src/main/java/com/snew/video/mvp/preview/PreViewVideoFragment.java @@ -0,0 +1,120 @@ +package com.snew.video.mvp.preview; + +import android.view.View; + +import com.example.commonlibrary.baseadapter.SuperRecyclerView; +import com.example.commonlibrary.baseadapter.decoration.GridSpaceDecoration; +import com.example.commonlibrary.baseadapter.listener.OnSimpleItemClickListener; +import com.example.commonlibrary.baseadapter.manager.WrappedGridLayoutManager; +import com.example.commonlibrary.bean.BaseBean; +import com.example.commonlibrary.customview.swipe.CustomSwipeRefreshLayout; +import com.example.commonlibrary.utils.CommonLogger; +import com.example.commonlibrary.utils.DensityUtil; +import com.example.commonlibrary.utils.ToastUtils; +import com.snew.video.R; +import com.snew.video.adapter.QQVideoListAdapter; +import com.snew.video.base.VideoBaseFragment; +import com.snew.video.bean.CommonVideoBean; +import com.snew.video.bean.QQVideoListBean; +import com.snew.video.dagger.preview.DaggerPreViewVideoComponent; +import com.snew.video.dagger.preview.PreViewVideoModule; +import com.snew.video.mvp.qq.detail.QQVideoDetailActivity; +import com.snew.video.util.VideoUtil; + +import java.util.List; + +import javax.inject.Inject; + +/** + * 项目名称: NewFastFrame + * 创建人: 陈锦军 + * 创建时间: 2019/1/9 16:13 + */ +public class PreViewVideoFragment extends VideoBaseFragment implements CustomSwipeRefreshLayout.OnRefreshListener { + private CustomSwipeRefreshLayout refresh; + private SuperRecyclerView display; + + @Inject + QQVideoListAdapter mVideoAdapter; + + public static PreViewVideoFragment newInstance() { + return new PreViewVideoFragment(); + } + + @Override + protected boolean isNeedHeadLayout() { + return false; + } + + @Override + protected boolean isNeedEmptyLayout() { + return false; + } + + + @Override + protected boolean needStatusPadding() { + return false; + } + + @Override + protected int getContentLayout() { + return R.layout.activity_preview_video; + } + + @Override + protected void initView() { + refresh = findViewById(R.id.refresh_activity_preview_video_refresh); + display = findViewById(R.id.srcv_activity_preview_video_display); + refresh.setOnRefreshListener(this); + } + + @Override + protected void initData() { + DaggerPreViewVideoComponent.builder().preViewVideoModule(new PreViewVideoModule(this)) + .videoComponent(getComponent()).build().inject(this); + display.setLayoutManager(new WrappedGridLayoutManager(getContext(), 3)); + display.addItemDecoration(new GridSpaceDecoration(3, DensityUtil.toDp(3), DensityUtil.toDp(15), true)); + display.setAdapter(mVideoAdapter); + mVideoAdapter.setOnItemClickListener(new OnSimpleItemClickListener() { + @Override + public void onItemClick(int position, View view) { + CommonVideoBean commonVideoBean = new CommonVideoBean(); + QQVideoListBean.JsonvalueBean.ResultsBean videoBean = mVideoAdapter.getData(position); + commonVideoBean.setUrl(videoBean.getId()); + commonVideoBean.setImage(videoBean.getFields().getVertical_pic_url()); + commonVideoBean.setVideoType(VideoUtil.VIDEO_TYPE_QQ_CAMERA); + commonVideoBean.setTitle(videoBean.getFields().getTitle()); + QQVideoDetailActivity.start(getActivity(), commonVideoBean); + } + }); + } + + @Override + protected void updateView() { + presenter.getPreVideoData(); + } + + @Override + public void updateData(BaseBean baseBean) { + if (baseBean.getCode() == 200) { + mVideoAdapter.refreshData((List) baseBean.getData()); + } else { + ToastUtils.showShortToast(baseBean.getDesc()); + CommonLogger.e(baseBean.getDesc()); + refresh.setRefreshing(false); + } + } + + + @Override + public void hideLoading() { + super.hideLoading(); + refresh.setRefreshing(false); + } + + @Override + public void onRefresh() { + presenter.getPreVideoData(); + } +} diff --git a/video/src/main/java/com/snew/video/mvp/preview/PreViewVideoPresenter.java b/video/src/main/java/com/snew/video/mvp/preview/PreViewVideoPresenter.java new file mode 100644 index 0000000..330a5b8 --- /dev/null +++ b/video/src/main/java/com/snew/video/mvp/preview/PreViewVideoPresenter.java @@ -0,0 +1,90 @@ +package com.snew.video.mvp.preview; + +import com.example.commonlibrary.bean.BaseBean; +import com.example.commonlibrary.mvp.model.DefaultModel; +import com.example.commonlibrary.mvp.presenter.RxBasePresenter; +import com.example.commonlibrary.mvp.view.IView; +import com.snew.video.bean.QQVideoListBean; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Observable; +import io.reactivex.ObservableSource; +import io.reactivex.Observer; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + + +/** + * 项目名称: NewFastFrame + * 创建人: 陈锦军 + * 创建时间: 2019/1/9 16:13 + */ +public class PreViewVideoPresenter extends RxBasePresenter, DefaultModel> { + public PreViewVideoPresenter(IView iView, DefaultModel baseModel) { + super(iView, baseModel); + } + + public void getPreVideoData() { + Observable.just("http://v.sigu.me/first.php?page=1") + .subscribeOn(Schedulers.io()) + .flatMap((Function>>) s -> { + Document document = Jsoup.connect(s).get(); + Element element = document.select(".tv-list.clearfix").first(); + List list = new ArrayList<>(); + if (element.children().size() > 0) { + for (Element item : + element.children()) { + Element tag = item.getElementsByTag("img").first(); + if (tag != null) { + QQVideoListBean.JsonvalueBean.ResultsBean videoBean = new QQVideoListBean.JsonvalueBean.ResultsBean(); + QQVideoListBean.JsonvalueBean.ResultsBean.FieldsBean fieldsBean=new QQVideoListBean.JsonvalueBean.ResultsBean.FieldsBean(); + fieldsBean.setVertical_pic_url(tag.attr("data-src").trim()); + Element a = item.getElementsByTag("a").first(); + if (a != null) { + videoBean.setId("http://v.sigu.me/" + a.attr("href").trim()); + fieldsBean.setTitle(a.attr("title")); + videoBean.setFields(fieldsBean); + list.add(videoBean); + } + } + } + } + return Observable.just(list); + }).observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer>() { + @Override + public void onSubscribe(Disposable d) { + addDispose(d); + } + + @Override + public void onNext(List videoBean) { + BaseBean baseBean = new BaseBean(); + baseBean.setCode(200); + baseBean.setData(videoBean); + iView.updateData(baseBean); + } + + @Override + public void onError(Throwable e) { + BaseBean baseBean = new BaseBean(); + baseBean.setCode(-1); + baseBean.setDesc(e.getMessage()); + iView.updateData(baseBean); + } + + @Override + public void onComplete() { + iView.hideLoading(); + } + }); + } +} diff --git a/video/src/main/java/com/snew/video/mvp/qq/QQVideoFragment.java b/video/src/main/java/com/snew/video/mvp/qq/QQVideoFragment.java index ef45c01..4fe6426 100644 --- a/video/src/main/java/com/snew/video/mvp/qq/QQVideoFragment.java +++ b/video/src/main/java/com/snew/video/mvp/qq/QQVideoFragment.java @@ -1,16 +1,13 @@ package com.snew.video.mvp.qq; import android.os.Bundle; -import android.view.View; import com.example.commonlibrary.baseadapter.adapter.ViewPagerAdapter; -import com.example.commonlibrary.customview.ToolBarOption; import com.example.commonlibrary.customview.WrappedViewPager; import com.google.android.material.tabs.TabLayout; import com.snew.video.R; import com.snew.video.base.VideoBaseFragment; import com.snew.video.bean.QQVideoTabBean; -import com.snew.video.mvp.search.SearchVideoActivity; import com.snew.video.util.VideoUtil; import java.util.ArrayList; @@ -39,7 +36,7 @@ public static QQVideoFragment newInstance(int videoUrlType) { @Override protected boolean isNeedHeadLayout() { - return true; + return false; } @Override @@ -47,6 +44,11 @@ protected boolean isNeedEmptyLayout() { return false; } + @Override + protected boolean needStatusPadding() { + return false; + } + @Override protected int getContentLayout() { return R.layout.fragment_qq_video; @@ -65,21 +67,16 @@ protected void initView() { protected void initData() { type = getArguments().getInt(VideoUtil.VIDEO_URL_TYPE, VideoUtil.VIDEO_URL_TYPE_QQ); init(); - ToolBarOption toolBarOption = new ToolBarOption(); - if (type == VideoUtil.VIDEO_URL_TYPE_QQ) { - toolBarOption.setTitle("腾讯视频"); - } else { - toolBarOption.setTitle("天天更新"); - } - toolBarOption.setNeedNavigation(false); - toolBarOption.setRightResId(R.drawable.ic_news_search); - toolBarOption.setRightListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - SearchVideoActivity.start(getActivity()); - } - }); - setToolBar(toolBarOption); + // ToolBarOption toolBarOption = new ToolBarOption(); + // if (type == VideoUtil.VIDEO_URL_TYPE_QQ) { + // toolBarOption.setTitle("腾讯视频"); + // } else { + // toolBarOption.setTitle("天天更新"); + // } + // toolBarOption.setNeedNavigation(false); + // toolBarOption.setRightResId(R.drawable.ic_news_search); + // toolBarOption.setRightListener(v -> SearchVideoActivity.start(getActivity())); + // setToolBar(toolBarOption); } private void init() { diff --git a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java index 40e3eb8..db0f23c 100644 --- a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java +++ b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailActivity.java @@ -5,7 +5,6 @@ import android.view.View; import android.widget.TextView; -import com.example.commonlibrary.BaseApplication; import com.example.commonlibrary.baseadapter.SuperRecyclerView; import com.example.commonlibrary.baseadapter.decoration.GridSpaceDecoration; import com.example.commonlibrary.baseadapter.decoration.ListViewDecoration; @@ -13,8 +12,6 @@ import com.example.commonlibrary.baseadapter.manager.WrappedGridLayoutManager; import com.example.commonlibrary.baseadapter.manager.WrappedLinearLayoutManager; import com.example.commonlibrary.bean.BaseBean; -import com.example.commonlibrary.bean.video.VideoInfoBean; -import com.example.commonlibrary.bean.video.VideoInfoBeanDao; import com.example.commonlibrary.customview.ToolBarOption; import com.example.commonlibrary.manager.video.DefaultVideoController; import com.example.commonlibrary.manager.video.DefaultVideoPlayer; @@ -35,8 +32,6 @@ import com.snew.video.mvp.actor.ActorDetailInfoActivity; import com.snew.video.util.VideoUtil; -import java.util.List; - import javax.inject.Inject; import androidx.core.app.ActivityOptionsCompat; @@ -211,7 +206,9 @@ private void deal() { if (data.getUrl() != null) { presenter.getDetailData(data.getUrl(), ((DefaultVideoController) display.getController()).isSwitchUrl()); } - presenter.getDetailInfo(data.getId()); + if (data.getId() != null) { + presenter.getDetailInfo(data.getId()); + } } @@ -259,19 +256,19 @@ public void updateData(BaseBean o) { } else { // 使用缓存播放 - if (o.getExtraInfo() != null && o.getExtraInfo().equals(data.getUrl())) { - List list = BaseApplication.getAppComponent().getDaoSession() - .getVideoInfoBeanDao().queryBuilder().where(VideoInfoBeanDao.Properties - .Name.eq(title.getText().toString().trim())).build().list(); - if (list.size() > 0) { - display.setUp(list.get(0).getPath(), null); - display.start(); - } else { - display.setState(DefaultVideoPlayer.PLAY_STATE_ERROR); - } - } else { - display.setState(DefaultVideoPlayer.PLAY_STATE_ERROR); - } +// if (o.getExtraInfo() != null && o.getExtraInfo().equals(data.getUrl())) { +// List list = BaseApplication.getAppComponent().getDaoSession() +// .getVideoInfoBeanDao().queryBuilder().where(VideoInfoBeanDao.Properties +// .Name.eq(data.getTitle())).build().list(); +// if (list.size() > 0) { +// display.setUp(list.get(0).getPath(), null); +// display.start(); +// } else { +// display.setState(DefaultVideoPlayer.PLAY_STATE_ERROR); +// } +// } else { +// display.setState(DefaultVideoPlayer.PLAY_STATE_ERROR); +// } } } diff --git a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java index f2de8e8..dc851ea 100644 --- a/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java +++ b/video/src/main/java/com/snew/video/mvp/qq/detail/QQVideoDetailPresenter.java @@ -6,8 +6,6 @@ import com.example.commonlibrary.BaseApplication; import com.example.commonlibrary.bean.BaseBean; -import com.example.commonlibrary.manager.video.ListVideoManager; -import com.example.commonlibrary.manager.video.VideoController; import com.example.commonlibrary.mvp.model.DefaultModel; import com.example.commonlibrary.mvp.presenter.RxBasePresenter; import com.example.commonlibrary.mvp.view.IView; @@ -52,85 +50,85 @@ public QQVideoDetailPresenter(IView iView, DefaultModel baseModel) { } -// public Observable commonParseUrl(String url) { -// //http://api.bbbbbb.me/yunjx/?url= -// return Observable.just(url).subscribeOn(Schedulers.io()) -// .flatMap(new Function>() { -// @Override -// public Observable apply(String s) throws Exception { -// StringBuilder stringBuilder = new StringBuilder("http://api.bbbbbb.me/yunjxs/?url=").append(s); -// Document document = Jsoup.connect(stringBuilder.toString()).get(); -// String content = document.outerHtml(); -// String parseContent = VideoUtil.getMd5Value(content); -// StringBuilder body = new StringBuilder(); -// body.append("id=").append(s).append("&type=auto&siteuser=&md5=").append(parseContent) -// .append("&hd=&lg="); -// RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), body.toString()); -// return baseModel.getRepositoryManager().getApi(VideoApi.class) -// .postQQTVUrlInfo("http://api.bbbbbb.me/yunjxs/api.php", requestBody1) -// .flatMap(new Function>() { -// @Override -// public Observable apply(QQTVVideoDetailBean qqtvVideoDetailBean) throws Exception { -// String ext = qqtvVideoDetailBean.getExt(); -// if (ext != null && (ext.equals("mp4") || ext.equals("m3u8"))) { -// return Observable.just(qqtvVideoDetailBean.getUrl()); -// } else if (ext != null && ext.equals("link")) { -// String realUrl = qqtvVideoDetailBean.getUrl().substring(qqtvVideoDetailBean.getUrl().indexOf("url=") + 4); -// -// return commonParseUrl(realUrl); -// } -// return null; -// } -// }) -// .subscribeOn(Schedulers.io()); -// } -// }); -// } - - -// public void getData(String url) { -// commonParseUrl(url).observeOn(AndroidSchedulers.mainThread()) -// .subscribe(new Observer() { -// @Override -// public void onSubscribe(Disposable d) { -// addDispose(d); -// } -// -// @Override -// public void onNext(String s) { -// String decoderUrl = URLDecoder.decode(s); -// BaseBean baseBean = new BaseBean(); -// baseBean.setType(VideoUtil.BASE_TYPE_VIDEO_DETAIL_URL); -// baseBean.setData(decoderUrl); -// // 用于标识当前请求的url -// baseBean.setExtraInfo(url); -// baseBean.setCode(200); -// iView.updateData(baseBean); -// } -// -// @Override -// public void onError(Throwable e) { -// iView.showError(e.getMessage(), null); -// } -// -// @Override -// public void onComplete() { -// iView.hideLoading(); -// } -// }); -// } + // public Observable commonParseUrl(String url) { + // //http://api.bbbbbb.me/yunjx/?url= + // return Observable.just(url).subscribeOn(Schedulers.io()) + // .flatMap(new Function>() { + // @Override + // public Observable apply(String s) throws Exception { + // StringBuilder stringBuilder = new StringBuilder("http://api.bbbbbb.me/yunjxs/?url=").append(s); + // Document document = Jsoup.connect(stringBuilder.toString()).get(); + // String content = document.outerHtml(); + // String parseContent = VideoUtil.getMd5Value(content); + // StringBuilder body = new StringBuilder(); + // body.append("id=").append(s).append("&type=auto&siteuser=&md5=").append(parseContent) + // .append("&hd=&lg="); + // RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), body.toString()); + // return baseModel.getRepositoryManager().getApi(VideoApi.class) + // .postQQTVUrlInfo("http://api.bbbbbb.me/yunjxs/api.php", requestBody1) + // .flatMap(new Function>() { + // @Override + // public Observable apply(QQTVVideoDetailBean qqtvVideoDetailBean) throws Exception { + // String ext = qqtvVideoDetailBean.getExt(); + // if (ext != null && (ext.equals("mp4") || ext.equals("m3u8"))) { + // return Observable.just(qqtvVideoDetailBean.getUrl()); + // } else if (ext != null && ext.equals("link")) { + // String realUrl = qqtvVideoDetailBean.getUrl().substring(qqtvVideoDetailBean.getUrl().indexOf("url=") + 4); + // + // return commonParseUrl(realUrl); + // } + // return null; + // } + // }) + // .subscribeOn(Schedulers.io()); + // } + // }); + // } + + + // public void getData(String url) { + // commonParseUrl(url).observeOn(AndroidSchedulers.mainThread()) + // .subscribe(new Observer() { + // @Override + // public void onSubscribe(Disposable d) { + // addDispose(d); + // } + // + // @Override + // public void onNext(String s) { + // String decoderUrl = URLDecoder.decode(s); + // BaseBean baseBean = new BaseBean(); + // baseBean.setType(VideoUtil.BASE_TYPE_VIDEO_DETAIL_URL); + // baseBean.setData(decoderUrl); + // // 用于标识当前请求的url + // baseBean.setExtraInfo(url); + // baseBean.setCode(200); + // iView.updateData(baseBean); + // } + // + // @Override + // public void onError(Throwable e) { + // iView.showError(e.getMessage(), null); + // } + // + // @Override + // public void onComplete() { + // iView.hideLoading(); + // } + // }); + // } public void getDetailData(String url, boolean isSwitch) { - if (url.startsWith("http://m.bt361.cn")) { + if (url.startsWith("http://v.sigu.me")) { getUpdateDetailData(url); return; } Observable observable; if (isSwitch) { - observable = getDetailDataForTwo(url); - } else { observable = getDetailDataForOne(url); + } else { + observable = getDetailDataForThree(url); } observable.observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @@ -177,18 +175,18 @@ private Observable getDetailDataForOne(String url) { return Observable.just(url).subscribeOn(Schedulers.io()).flatMap(new Function>() { @Override public ObservableSource apply(String s) throws Exception { -// https://api.bbbbbb.me/zy/?url=https://v.qq.com/x/cover/2j5kilwvtepehti.html - StringBuilder stringBuilder=new StringBuilder("https://api.bbbbbb.me/zy/?url="); + // https://api.bbbbbb.me/zy/?url=https://v.qq.com/x/cover/2j5kilwvtepehti.html + StringBuilder stringBuilder = new StringBuilder("https://api.bbbbbb.me/zy/?url="); stringBuilder.append(s); - Document document=Jsoup.connect(stringBuilder.toString().trim()).get(); -// start : url":" end: ","type - String start="url\":\""; - String end="\",\"type"; + Document document = Jsoup.connect(stringBuilder.toString().trim()).get(); + // start : url":" end: ","type + String start = "url\":\""; + String end = "\",\"type"; String content = document.outerHtml(); int startIndex = content.indexOf(start); String url1 = content.substring(startIndex + start.length(), content.lastIndexOf(end)).trim(); RequestBody requestBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), "url=" + url1); - return baseModel.getRepositoryManager().getApi(VideoApi.class) + return baseModel.getRepositoryManager().getApi(VideoApi.class) .postUrlInfo("http://api.bbbbbb.me/zy/sigu.php", requestBody).subscribeOn(Schedulers.io()) .flatMap((Function>) qqVideoDetailBean -> { if (qqVideoDetailBean.getCode() == 0) { @@ -236,75 +234,48 @@ public ObservableSource apply(String s) throws Exception { }); } - private Observable getDetailDataForTwo(String url) { - return Observable.just(url).subscribeOn(Schedulers.io()) - .flatMap(new Function>() { - @Override - public ObservableSource apply(String s) throws Exception { - StringBuilder stringBuilder = new StringBuilder("http://all.baiyug.cn:2021/QQQ/index.php").append("?url=") - .append(s); - Document document = Jsoup.connect(stringBuilder.toString()).header("Referer", "http://app.baiyug.cn").get(); - String content = document.outerHtml(); - String start = "url:"; - int startIndex = content.indexOf(start); - String end = "pic: pic"; - String url1 = content.substring(startIndex + start.length(), content.lastIndexOf(end)).trim(); - String realUrl = url1.substring(1, url1.length() - 2); - if (URLUtil.isValidUrl(realUrl)) { - return Observable.just(realUrl); - } else { - return getDetailDataForThree(url); - } - } - }); - } private void getUpdateDetailData(String url) { Observable.just(url).subscribeOn(Schedulers.io()) .map(s -> { Document document = Jsoup.connect(s).get(); - Elements elements = document.select(".swiper-slide"); - // http://m.bt361.cn/vod/detail/id/45468/ - List list = new ArrayList<>(); - if (elements.size() > 0) { - for (int i = 0; i < elements.size(); i++) { - Element item = elements.get(i); - - String link = item.getElementsByTag("a").first().attr("href"); - // http://m.tbb361.com/index.php/vod/play/id/60010/sid/2/nid/1/ - String realLink = "http://m.bt361.cn" + link; - Document document1 = Jsoup.connect(realLink).get(); - String content = document1.outerHtml(); - String start = "\"url\":\""; - // ","link_next - String end = "\",\"url_next"; - String url1 = content.substring(content.indexOf(start) + start.length(), content.indexOf(end)); - String decoderUrl = URLDecoder.decode(url1); - VideoController.Clarity clarity = new VideoController.Clarity(item.text(), null, decoderUrl); - list.add(clarity); - } - } - return list; + String content = document.outerHtml().trim(); + String start = "\"dangqian\" value=\""; + String end = "\" style="; + int startIndex = content.indexOf(start); + int endIndex = content.lastIndexOf(end); + String url1 = content.substring(startIndex + start.length(), endIndex); + CommonLogger.e("url::::" + url1); + return url1; }).observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer>() { + .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { addDispose(d); } @Override - public void onNext(List clarities) { - if (clarities != null && clarities.size() > 0) { - ListVideoManager.getInstance().getCurrentPlayer().setClarity(clarities); - ListVideoManager.getInstance().updateUrl(clarities.get(0).getVideoUrl()); - } else { - ListVideoManager.getInstance().error(); + public void onNext(String string) { + BaseBean baseBean = new BaseBean(); + baseBean.setType(VideoUtil.BASE_TYPE_VIDEO_DETAIL_URL); + if (string != null) { + string = URLDecoder.decode(string); } + CommonLogger.e("最终url" + string); + baseBean.setData(string); + baseBean.setCode(200); + baseBean.setExtraInfo(url); + iView.updateData(baseBean); } @Override public void onError(Throwable e) { iView.showError(e.getMessage(), null); + BaseBean baseBean = new BaseBean(); + baseBean.setType(VideoUtil.BASE_TYPE_VIDEO_DETAIL_URL); + baseBean.setCode(-1); + baseBean.setExtraInfo(url); + iView.updateData(baseBean); } @Override @@ -317,6 +288,7 @@ public void onComplete() { public Observable getDetailDataForThree(String url) { // http://app.baiyug.cn:2019/vip/search/qq.php?url=https://v.qq.com/x/cover/og0eputlxwet1cn.html + CommonLogger.e("url:" + url); return Observable.just(url).subscribeOn(Schedulers.io()) .flatMap((Function>) s -> { StringBuilder stringBuilder = new StringBuilder("http://app.baiyug.cn:2019/vip/search/qq.php").append("?url=") @@ -325,6 +297,7 @@ public Observable getDetailDataForThree(String url) { try { document = Jsoup.connect(stringBuilder.toString()).header("Referer", "http://app.baiyug.cn").get(); String src = document.getElementsByTag("iframe").first().attr("src"); + CommonLogger.e("content:" + document.outerHtml()); String str; if (URLUtil.isValidUrl(src)) { Uri uri = Uri.parse(src); @@ -339,7 +312,7 @@ public Observable getDetailDataForThree(String url) { } } catch (IOException e) { e.printStackTrace(); - return getDetailDataForFour(url); + return getDetailDataForOne(url); } }); } @@ -351,10 +324,10 @@ public Observable getDetailDataForFour(String url) { StringBuilder stringBuilder = new StringBuilder("http://all.baiyug.cn:2021/QQ/index.php").append("?url=") .append(s); Document document = Jsoup.connect(stringBuilder.toString()).header("Referer", "http://app.baiyug.cn").get(); - String content = document.outerHtml(); + String content = document.outerHtml().replace("amp;", "").trim(); String start = "url:"; int startIndex = content.indexOf(start); - String end = "pic: pic"; + String end = "pic:"; String url1 = content.substring(startIndex + start.length(), content.lastIndexOf(end)).trim(); String realUrl = url1.substring(1, url1.length() - 2); if (URLUtil.isValidUrl(realUrl)) { @@ -365,6 +338,7 @@ public Observable getDetailDataForFour(String url) { }); } + public void getDetailInfo(String id) { String url = VideoUtil.getVideoDetailUrl(id); Observable observable; diff --git a/video/src/main/module/AndroidManifest.xml b/video/src/main/module/AndroidManifest.xml index 3b5c7a8..a883ade 100644 --- a/video/src/main/module/AndroidManifest.xml +++ b/video/src/main/module/AndroidManifest.xml @@ -34,6 +34,7 @@ android:launchMode="singleTask" /> + diff --git a/video/src/main/module/java/com/snew/video/VideoActivity.java b/video/src/main/module/java/com/snew/video/VideoActivity.java index 351cd86..72a7b00 100644 --- a/video/src/main/module/java/com/snew/video/VideoActivity.java +++ b/video/src/main/module/java/com/snew/video/VideoActivity.java @@ -1,21 +1,38 @@ package com.snew.video; +import android.view.View; + +import com.example.commonlibrary.baseadapter.adapter.ViewPagerAdapter; +import com.example.commonlibrary.customview.ToolBarOption; +import com.example.commonlibrary.customview.ViewPagerIndicator; +import com.example.commonlibrary.customview.WrappedViewPager; import com.example.commonlibrary.manager.video.ListVideoManager; +import com.example.commonlibrary.utils.ToastUtils; import com.snew.video.base.VideoBaseActivity; +import com.snew.video.mvp.preview.PreViewVideoFragment; import com.snew.video.mvp.qq.QQVideoFragment; +import com.snew.video.mvp.search.SearchVideoActivity; import com.snew.video.util.VideoUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import androidx.fragment.app.Fragment; + /** * 项目名称: NewFastFrame * 创建人: 陈锦军 * 创建时间: 2018/12/10 11:12 */ -public class VideoActivity extends VideoBaseActivity { +public class VideoActivity extends VideoBaseActivity implements View.OnClickListener { + private WrappedViewPager display; + private ViewPagerIndicator viewPagerIndicator; @Override protected boolean isNeedHeadLayout() { - return false; + return true; } @Override @@ -36,12 +53,35 @@ protected int getContentLayout() { @Override protected void initView() { - + display = findViewById(R.id.wvp_activity_video_display); } @Override protected void initData() { - addOrReplaceFragment(QQVideoFragment.newInstance(VideoUtil.VIDEO_URL_TYPE_QQ), R.id.fl_activity_video_container); + ToolBarOption toolBarOption = new ToolBarOption(); + toolBarOption.setCustomView(getCustomView()); + toolBarOption.setNeedNavigation(false); + setToolBar(toolBarOption); + ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); + List list = new ArrayList<>(); + list.add(QQVideoFragment.newInstance(VideoUtil.VIDEO_URL_TYPE_QQ)); + list.add(PreViewVideoFragment.newInstance()); + viewPagerAdapter.setTitleAndFragments(Arrays.asList("腾讯", "最新"), list); + display.setAdapter(viewPagerAdapter); + viewPagerIndicator.setViewPager(display, 0); + } + + + @Override + protected boolean needSlide() { + return false; + } + + private View getCustomView() { + View view = getLayoutInflater().inflate(R.layout.view_activity_video_header, null, false); + viewPagerIndicator = view.findViewById(R.id.vpi_view_activity_video_header_view_indicator); + view.findViewById(R.id.iv_view_activity_video_header_view_search).setOnClickListener(this); + return view; } @Override @@ -50,10 +90,27 @@ public void updateData(Object o) { } + private long mExitTime; + @Override public void onBackPressed() { if (!ListVideoManager.getInstance().onBackPressed()) { super.onBackPressed(); + } else if (System.currentTimeMillis() - mExitTime > 2000) { + ToastUtils.showShortToast("再按一次退出程序"); + mExitTime = System.currentTimeMillis(); + } else { + super.onBackPressed(); + } + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.iv_view_activity_video_header_view_search) { + SearchVideoActivity.start(this); } } + + } diff --git a/video/src/main/module/res/layout/activity_video.xml b/video/src/main/module/res/layout/activity_video.xml index 731d099..001b272 100644 --- a/video/src/main/module/res/layout/activity_video.xml +++ b/video/src/main/module/res/layout/activity_video.xml @@ -2,13 +2,12 @@ - + \ No newline at end of file diff --git a/video/src/main/res/layout/activity_preview_video.xml b/video/src/main/res/layout/activity_preview_video.xml new file mode 100644 index 0000000..dc31346 --- /dev/null +++ b/video/src/main/res/layout/activity_preview_video.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/video/src/main/res/layout/item_fragment_qq_video_list.xml b/video/src/main/res/layout/item_fragment_qq_video_list.xml index de670cd..2ec071d 100644 --- a/video/src/main/res/layout/item_fragment_qq_video_list.xml +++ b/video/src/main/res/layout/item_fragment_qq_video_list.xml @@ -25,7 +25,6 @@ android:layout_alignParentBottom="true" android:background="@drawable/ic_video_list_score_bg" android:gravity="end|bottom" - android:text="9.6" android:textColor="@color/orange_500" android:textSize="12sp" /> diff --git a/video/src/main/res/layout/view_activity_video_header.xml b/video/src/main/res/layout/view_activity_video_header.xml new file mode 100644 index 0000000..fd79367 --- /dev/null +++ b/video/src/main/res/layout/view_activity_video_header.xml @@ -0,0 +1,28 @@ + + + + + + + + \ No newline at end of file From cdcef460d99d4577855075d51a626678a7f9537e Mon Sep 17 00:00:00 2001 From: lixiaoxiao Date: Mon, 25 Feb 2019 10:15:06 +0800 Subject: [PATCH 3/3] =?UTF-8?q?[fix]=E9=80=82=E9=85=8D=E5=85=A8=E9=9D=A2?= =?UTF-8?q?=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 5 ++++- chat/src/main/res/layout/activity_login.xml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 739eded..885cc88 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,7 +28,10 @@ - + \ No newline at end of file diff --git a/chat/src/main/res/layout/activity_login.xml b/chat/src/main/res/layout/activity_login.xml index 2099558..976e4b0 100644 --- a/chat/src/main/res/layout/activity_login.xml +++ b/chat/src/main/res/layout/activity_login.xml @@ -1,6 +1,6 @@ + android:layout_height="match_parent">