Commit 3be7468f by konghaorui

删除 Platform 模块业务功能代码、删减重复功能类

parent a9c69d4b
...@@ -23,7 +23,6 @@ interface DemoService { ...@@ -23,7 +23,6 @@ interface DemoService {
@GET("home/index") @GET("home/index")
fun getHomeData(): Observable<JsonObject> fun getHomeData(): Observable<JsonObject>
@GET("home/index") @GET("home/index")
fun getHome1Data(): Observable<JsonObject> fun getHome1Data(): Observable<JsonObject>
......
apply plugin: 'maven'
def mavenRepositoryUrl
if (isReleaseBuild()) {
println 'RELEASE BUILD'
mavenRepositoryUrl = "http://nexus.yidianling.com/repository/AndroidReleases/"
} else {
println 'SNAPSHOTS BUILD'
mavenRepositoryUrl = "http://nexus.yidianling.com/repository/AndroidSnapshots/"
}
def getRepositoryUsername() {
return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "admin"
}
def getRepositoryPassword() {
return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "fjoi#1+#@"
}
def isReleaseBuild() {
return IS_PUBLISH.toBoolean();
}
afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
pom.artifactId = project.getName().replace('_', "-")
pom.groupId = "com.ydl"
pom.version = isReleaseBuild() ? VERSION_NAME : VERSION_NAME + "-SNAPSHOT"
repository(url: mavenRepositoryUrl) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
}
}
}
uploadArchives.doFirst {
// log
println String.format(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n>>>>> [%s] 正在将[%s]版本的[%s]包上传到Maven的[%s]仓库 >>>>>\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
, project.getName()
, VERSION_NAME
, "aar"
, IS_PUBLISH.toBoolean() ? "release" : "snapshot"
)
}
}
\ No newline at end of file
...@@ -2,6 +2,7 @@ apply plugin: 'com.android.library' ...@@ -2,6 +2,7 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply from: "../maven_push.gradle"
android { android {
compileSdkVersion 28 compileSdkVersion 28
...@@ -50,3 +51,4 @@ dependencies { ...@@ -50,3 +51,4 @@ dependencies {
api rootProject.ext.dependencies["gson"] api rootProject.ext.dependencies["gson"]
} }
IS_PUBLISH=false
VERSION_NAME=1.0.0
\ No newline at end of file
...@@ -17,46 +17,6 @@ apply plugin: 'kotlin-android' ...@@ -17,46 +17,6 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
Properties properties = new Properties()
properties.load(project.rootProject.file('api.properties').newDataInputStream())
String pack = properties.getProperty("pack", "test")
String serverurl = properties.getProperty("serverurl." + pack)
String actionurl = properties.getProperty("actionurl." + pack)
String h5url = properties.getProperty("h5url." + pack)
String mh5url = properties.getProperty("mh5url." + pack)
String ydlh5url = properties.getProperty("ydlh5url." + pack)
String weburl = properties.getProperty("weburl." + pack)
String javaurl = properties.getProperty("javaurl." + pack)
String javatempurl = properties.getProperty("javatempurl." + pack)
String javaapi = properties.getProperty("javaapi." + pack)
String javacouponurl = properties.getProperty("javacouponurl." + pack)
//测试环境所有url
String testServerurl = properties.getProperty("serverurl.test")
String testActionurl = properties.getProperty("actionurl.test")
String testH5url = properties.getProperty("h5url.test")
String testydlh5url = properties.getProperty("ydlh5url.test")
String testweburl = properties.getProperty("weburl.test")
String testJavaurl = properties.getProperty("javaurl.test")
String testJavatempurl = properties.getProperty("javatempurl.test")
String testJavaapi = properties.getProperty("javaapi.test")
String testJavacouponurl = properties.getProperty("javacouponurl.test")
//预发布环境所有url
String preServerurl = properties.getProperty("serverurl.pre")
String preH5url = properties.getProperty("h5url.pre")
//线上环境所有url
String releaseServerurl = properties.getProperty("serverurl.prod")
String releaseActionurl = properties.getProperty("actionurl.prod")
String releaseH5url = properties.getProperty("h5url.prod")
String releaseydlh5url = properties.getProperty("ydlh5url.prod")
String releaseWEBurl = properties.getProperty("weburl.prod")
String releaseJavaurl = properties.getProperty("javaurl.prod")
String releaseJavatempurl = properties.getProperty("javatempurl.prod")
String releaseJavaapi = properties.getProperty("javaapi.prod")
String releaseJavacouponurl = properties.getProperty("javacouponurl.prod")
kapt { kapt {
arguments { arguments {
arg("AROUTER_MODULE_NAME", project.getName()) arg("AROUTER_MODULE_NAME", project.getName())
...@@ -74,44 +34,6 @@ android { ...@@ -74,44 +34,6 @@ android {
multiDexEnabled true multiDexEnabled true
buildConfigField "String", "SERVER_JAVA_API_URL", "\"$javaapi\""
buildConfigField "String", "SERVER_JAVA_URL", "\"$javaurl\""
buildConfigField "String", "SERVER_COUPON_JAVA_URL", "\"$javacouponurl\""
buildConfigField "String", "SERVER_TEMP_JAVA_URL", "\"$javatempurl\""
buildConfigField "String", "SERVER_URL", "\"$serverurl\""
buildConfigField "String", "ACTION_URL", "\"$actionurl\""
buildConfigField "String", "H5_URL", "\"$h5url\""
buildConfigField "String", "MH5_URL", "\"$mh5url\""
buildConfigField "String", "YDL_H5_URL", "\"$ydlh5url\""
buildConfigField "String", "WEB_URL", "\"$weburl\""
buildConfigField "String", "pack", "\"$pack\""
//测试url
buildConfigField "String", "TEST_SERVER_URL", "\"$testServerurl\""
buildConfigField "String", "TEST_ACTION_URL", "\"$testActionurl\""
buildConfigField "String", "TEST_H5_URL", "\"$testH5url\""
buildConfigField "String", "TEST_YDL_H5_URL", "\"$testydlh5url\""
buildConfigField "String", "TEST_WEB_URL", "\"$testweburl\""
buildConfigField "String", "TEST_SERVER_JAVA_URL", "\"$testJavaurl\""
buildConfigField "String", "TEST_SERVER_TEMP_JAVA_URL", "\"$testJavatempurl\""
buildConfigField "String", "TEST_SERVER_JAVA_API_URL", "\"$testJavaapi\""
buildConfigField "String", "TEST_SERVER_COUPON_JAVA_URL", "\"$testJavacouponurl\""
//预发布url
buildConfigField "String", "PRE_SERVER_URL", "\"$preServerurl\""
buildConfigField "String", "PRE_H5_URL", "\"$preH5url\""
//线上url
buildConfigField "String", "RELEASE_SERVER_URL", "\"$releaseServerurl\""
buildConfigField "String", "RELEASE_ACTION_URL", "\"$releaseActionurl\""
buildConfigField "String", "RELEASE_YDL_H5_URL", "\"$releaseydlh5url\""
buildConfigField "String", "RELEASE_H5_URL", "\"$releaseH5url\""
buildConfigField "String", "RELEASE_WEB_URL", "\"$releaseWEBurl\""
buildConfigField "String", "RELEASE_SERVER_JAVA_URL", "\"$releaseJavaurl\""
buildConfigField "String", "RELEASE_SERVER_TEMP_JAVA_URL", "\"$releaseJavatempurl\""
buildConfigField "String", "RELEASE_SERVER_JAVA_API_URL", "\"$releaseJavaapi\""
buildConfigField "String", "RELEASE_SERVER_COUPON_JAVA_URL", "\"$releaseJavacouponurl\""
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
flavorDimensions "versionCode" flavorDimensions "versionCode"
......
...@@ -24,14 +24,14 @@ ...@@ -24,14 +24,14 @@
android:theme="@style/Transparent" /> android:theme="@style/Transparent" />
<activity <activity
android:name=".custom.imagepicker.ImagePickerActivity" android:name="com.yidianling.ydlcommon.custom.actions.imagepicker.ImagePickerActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<service android:name=".custom.player.service.HMusicPlayService" <service android:name="com.yidianling.ydlcommon.custom.actions.player.service.HMusicPlayService"
android:enabled="true"/> android:enabled="true"/>
<receiver android:name=".custom.player.notifycation.MusicPlayerReceiver" <receiver android:name="com.yidianling.ydlcommon.custom.actions.player.notifycation.MusicPlayerReceiver"
android:enabled="true" android:enabled="true"
android:exported="false"> android:exported="false">
<intent-filter> <intent-filter>
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<!--监听系统下载完成的广播--> <!--监听系统下载完成的广播-->
<receiver android:name=".custom.receiver.DownloadReceiver"> <receiver android:name=".custom.utils.receiver.DownloadReceiver">
<intent-filter> <intent-filter>
<action android:name="DownloadManager.ACTION_DOWNLOAD_COMPLETE"/> <action android:name="DownloadManager.ACTION_DOWNLOAD_COMPLETE"/>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" /> <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
......
...@@ -6,6 +6,7 @@ import android.os.Bundle ...@@ -6,6 +6,7 @@ import android.os.Bundle
import android.support.annotation.LayoutRes import android.support.annotation.LayoutRes
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.util.Log import android.util.Log
import android.view.View
import com.trello.rxlifecycle2.android.ActivityEvent import com.trello.rxlifecycle2.android.ActivityEvent
import com.yidianling.ydlcommon.core.base.lifecycle.IActivityLifecycleable import com.yidianling.ydlcommon.core.base.lifecycle.IActivityLifecycleable
import com.yidianling.ydlcommon.core.bean.StatusBarOptions import com.yidianling.ydlcommon.core.bean.StatusBarOptions
...@@ -27,6 +28,7 @@ abstract class BaseActivity : AppCompatActivity(),IActivityLifecycleable { ...@@ -27,6 +28,7 @@ abstract class BaseActivity : AppCompatActivity(),IActivityLifecycleable {
private val mLifecycleSubject = BehaviorSubject.create<ActivityEvent>() private val mLifecycleSubject = BehaviorSubject.create<ActivityEvent>()
var mContext: Activity by Delegates.notNull() var mContext: Activity by Delegates.notNull()
var statusBarOption: StatusBarOptions? = null var statusBarOption: StatusBarOptions? = null
var statusView: View? = null
override fun provideLifecycleSubject(): Subject<ActivityEvent> { override fun provideLifecycleSubject(): Subject<ActivityEvent> {
return mLifecycleSubject; return mLifecycleSubject;
...@@ -54,7 +56,13 @@ abstract class BaseActivity : AppCompatActivity(),IActivityLifecycleable { ...@@ -54,7 +56,13 @@ abstract class BaseActivity : AppCompatActivity(),IActivityLifecycleable {
override fun setContentView(@LayoutRes layoutResID: Int) { override fun setContentView(@LayoutRes layoutResID: Int) {
if (statusBarOption!=null && statusBarOption?.isAddStatusView!!) { if (statusBarOption!=null && statusBarOption?.isAddStatusView!!) {
super.setContentView(StatusBarUtils.initStatusBarView(this,layoutResID,statusBarOption!!)) val returnViews = StatusBarUtils.initStatusBarView(this, layoutResID, statusBarOption!!)
if(returnViews.size > 1){
statusView = returnViews[1];
}
super.setContentView(returnViews[0])
AndroidSystemHelper.fixAndroidBug5497Workaround(this) AndroidSystemHelper.fixAndroidBug5497Workaround(this)
} else { } else {
super.setContentView(layoutResID) super.setContentView(layoutResID)
...@@ -82,4 +90,10 @@ abstract class BaseActivity : AppCompatActivity(),IActivityLifecycleable { ...@@ -82,4 +90,10 @@ abstract class BaseActivity : AppCompatActivity(),IActivityLifecycleable {
open fun initStatusViewOptions(isAddStatusView:Boolean,statusBarDarkMode:Boolean,statusColor:String){ open fun initStatusViewOptions(isAddStatusView:Boolean,statusBarDarkMode:Boolean,statusColor:String){
statusBarOption = StatusBarOptions(isAddStatusView,statusBarDarkMode,statusColor) statusBarOption = StatusBarOptions(isAddStatusView,statusBarDarkMode,statusColor)
} }
open fun initStatusViewOptions(){
statusBarOption = StatusBarOptions()
}
} }
\ No newline at end of file
...@@ -56,7 +56,10 @@ abstract class BaseFragment : Fragment() ,IFragmentLifecycleable{ ...@@ -56,7 +56,10 @@ abstract class BaseFragment : Fragment() ,IFragmentLifecycleable{
layoutResId != 0 -> { layoutResId != 0 -> {
val childView = inflater.inflate(layoutResId, container, false) val childView = inflater.inflate(layoutResId, container, false)
if (statusBarOption!=null && statusBarOption?.isAddStatusView!!){ if (statusBarOption!=null && statusBarOption?.isAddStatusView!!){
return StatusBarUtils.initStatusBarView(activity!!,childView,statusBarOption!!)
val returnViews = StatusBarUtils.initStatusBarView(activity!!, childView, statusBarOption!!)
return returnViews[0]
}else{ }else{
return childView; return childView;
} }
......
...@@ -8,8 +8,8 @@ import com.ydl.ydlnet.builder.config.OkHttpConfig ...@@ -8,8 +8,8 @@ import com.ydl.ydlnet.builder.config.OkHttpConfig
import com.yidianling.common.tools.RxAppTool import com.yidianling.common.tools.RxAppTool
import com.yidianling.common.tools.RxDeviceTool import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.ydlcommon.BuildConfig import com.yidianling.ydlcommon.BuildConfig
import com.yidianling.ydlcommon.custom.constant.YdlConstants import com.yidianling.ydlcommon.custom.constant.YDLConstants
import com.yidianling.ydlcommon.custom.data.YdlDataManager import com.yidianling.ydlcommon.custom.data.PlatformDataManager
import com.yidianling.ydlcommon.custom.http.EncryptUtils import com.yidianling.ydlcommon.custom.http.EncryptUtils
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager
import com.yidianling.ydlcommon.custom.utils.YDLCacheUtils import com.yidianling.ydlcommon.custom.utils.YDLCacheUtils
...@@ -97,11 +97,11 @@ class HttpConfig { ...@@ -97,11 +97,11 @@ class HttpConfig {
val name = body.name(i) val name = body.name(i)
val value = body.value(i) val value = body.value(i)
// 去除假参数和值为空的参数 // 去除假参数和值为空的参数
if (YdlConstants.HOLDER_PARAM != name && !TextUtils.isEmpty(value)) { if (YDLConstants.HOLDER_PARAM != name && !TextUtils.isEmpty(value)) {
bodyBuild.addEncoded(name, value) bodyBuild.addEncoded(name, value)
} }
} }
bodyBuild.addEncoded(FFROM, YdlDataManager.getRam().getChannelName()) bodyBuild.addEncoded(FFROM, PlatformDataManager.getRam().getChannelName())
.addEncoded(IS_FROM_APP, "1") .addEncoded(IS_FROM_APP, "1")
.addEncoded( .addEncoded(
OS_BUILD, OS_BUILD,
...@@ -182,7 +182,7 @@ class HttpConfig { ...@@ -182,7 +182,7 @@ class HttpConfig {
.newBuilder() .newBuilder()
.header(AUTHORIZATION_NAME, head) .header(AUTHORIZATION_NAME, head)
.addHeader("Connection", "close") .addHeader("Connection", "close")
.addHeader(FFROM, YdlDataManager.getRam().getChannelName()) .addHeader(FFROM, PlatformDataManager.getRam().getChannelName())
.addHeader(IS_FROM_APP, "1") .addHeader(IS_FROM_APP, "1")
.addHeader(VERSION, RxDeviceTool.getAppVersionName(BaseApplication.getApp())) .addHeader(VERSION, RxDeviceTool.getAppVersionName(BaseApplication.getApp()))
.addHeader( .addHeader(
......
...@@ -16,8 +16,8 @@ import android.view.View ...@@ -16,8 +16,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.widget.LinearLayout import android.widget.LinearLayout
import com.yidianling.ydlcommon.core.bean.StatusBarOptions
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.core.bean.StatusBarOptions
/** /**
...@@ -864,7 +864,7 @@ class StatusBarUtils { ...@@ -864,7 +864,7 @@ class StatusBarUtils {
fun initStatusBarView( fun initStatusBarView(
context: Activity, @LayoutRes layoutResID: Int, context: Activity, @LayoutRes layoutResID: Int,
statusBarOptions: StatusBarOptions statusBarOptions: StatusBarOptions
): View { ): Array<View> {
val child = View.inflate(context, layoutResID, null) val child = View.inflate(context, layoutResID, null)
return initStatusBarView(context,child,statusBarOptions) return initStatusBarView(context,child,statusBarOptions)
} }
...@@ -872,23 +872,34 @@ class StatusBarUtils { ...@@ -872,23 +872,34 @@ class StatusBarUtils {
fun initStatusBarView( fun initStatusBarView(
context: Activity,child:View, context: Activity,child:View,
statusBarOptions: StatusBarOptions statusBarOptions: StatusBarOptions
): View { ): Array<View> {
var returnView = arrayOf<View>()
val containerView = View.inflate(context, R.layout.layout_root, null) as ViewGroup val containerView = View.inflate(context, R.layout.layout_root, null) as ViewGroup
val rootView = containerView.findViewById<LinearLayout>(R.id.ll_root); val rootView = containerView.findViewById<LinearLayout>(R.id.ll_root);
initStatus(context,rootView,statusBarOptions); val statusView = initStatus(context, rootView, statusBarOptions);
val params = val params =
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
rootView.addView(child, params) rootView.addView(child, params)
return containerView returnView[0] = containerView
if (statusView != null){
returnView[1] = statusView
}
return returnView
} }
fun initStatus( fun initStatus(
context: Activity, context: Activity,
rootView: View, rootView: View,
statusBarOptions: StatusBarOptions) { statusBarOptions: StatusBarOptions):View? {
var statusView:View ?=null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
var statusView = rootView.findViewById<View>(R.id.view_status_place_holder) statusView = rootView.findViewById<View>(R.id.view_status_place_holder)
statusView?.setBackgroundColor(Color.parseColor(statusBarOptions.statusColor)) statusView?.setBackgroundColor(Color.parseColor(statusBarOptions.statusColor))
val statusBarHeight = StatusBarUtils.getStatusBarHeight(context) val statusBarHeight = StatusBarUtils.getStatusBarHeight(context)
val layoutParams = statusView?.getLayoutParams() as LinearLayout.LayoutParams val layoutParams = statusView?.getLayoutParams() as LinearLayout.LayoutParams
...@@ -899,6 +910,7 @@ class StatusBarUtils { ...@@ -899,6 +910,7 @@ class StatusBarUtils {
if (statusBarOptions.statusBarDarkMode) { if (statusBarOptions.statusBarDarkMode) {
statusBarLightMode(context) statusBarLightMode(context)
} }
return statusView
} }
} }
......
...@@ -2,7 +2,7 @@ package com.yidianling.ydlcommon.custom; ...@@ -2,7 +2,7 @@ package com.yidianling.ydlcommon.custom;
import com.yidianling.ydlcommon.core.base.BaseApplication; import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.RxAppTool; import com.yidianling.common.tools.RxAppTool;
import com.yidianling.ydlcommon.custom.data.YdlDataManager; import com.yidianling.ydlcommon.custom.data.PlatformDataManager;
import com.yidianling.ydlcommon.custom.http.EncryptUtils; import com.yidianling.ydlcommon.custom.http.EncryptUtils;
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager; import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager;
import com.yidianling.ydlcommon.custom.router.YdlUserInfo; import com.yidianling.ydlcommon.custom.router.YdlUserInfo;
...@@ -117,7 +117,7 @@ public class TemporaryUtils { ...@@ -117,7 +117,7 @@ public class TemporaryUtils {
} }
mTree.put("v", RxAppTool.getAppVersionName(BaseApplication.Companion.getApp())); mTree.put("v", RxAppTool.getAppVersionName(BaseApplication.Companion.getApp()));
mTree.put("isFromApp", "1");//1表示用户版调用接口 mTree.put("isFromApp", "1");//1表示用户版调用接口
mTree.put("ffrom", YdlDataManager.INSTANCE.getRam().getChannelName()); mTree.put("ffrom", PlatformDataManager.INSTANCE.getRam().getChannelName());
mTree.put("ts", time); mTree.put("ts", time);
Set<String> keySet = mTree.descendingKeySet(); Set<String> keySet = mTree.descendingKeySet();
......
...@@ -10,7 +10,7 @@ import com.yidianling.common.tools.RxDeviceTool; ...@@ -10,7 +10,7 @@ import com.yidianling.common.tools.RxDeviceTool;
import com.yidianling.ydlcommon.BuildConfig; import com.yidianling.ydlcommon.BuildConfig;
import com.yidianling.ydlcommon.custom.router.YdlCommonOut; import com.yidianling.ydlcommon.custom.router.YdlCommonOut;
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager; import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager;
import com.yidianling.ydlcommon.custom.tool.JPushUtils; import com.yidianling.ydlcommon.custom.utils.JPushUtils;
//埋点工具类 //埋点工具类
public class YdlBuryPointUtil { public class YdlBuryPointUtil {
......
package com.yidianling.ydlcommon.custom.imagepicker package com.yidianling.ydlcommon.custom.actions.imagepicker
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import com.lzy.imagepicker.ImagePicker import com.lzy.imagepicker.ImagePicker
import com.lzy.imagepicker.bean.ImageItem import com.lzy.imagepicker.bean.ImageItem
import com.lzy.imagepicker.ui.ImageGridActivity import com.lzy.imagepicker.ui.ImageGridActivity
import com.yidianling.ydlcommon.custom.base.BaseActivity import com.yidianling.ydlcommon.core.base.BaseActivity
import com.yidianling.ydlcommon.custom.remind.ToastHelper import com.yidianling.ydlcommon.custom.utils.remind.ToastHelper
/** /**
......
package com.yidianling.ydlcommon.custom.imagepicker package com.yidianling.ydlcommon.custom.actions.imagepicker
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
...@@ -6,8 +6,8 @@ import android.support.v7.app.AppCompatActivity ...@@ -6,8 +6,8 @@ import android.support.v7.app.AppCompatActivity
import com.lzy.imagepicker.ImagePicker import com.lzy.imagepicker.ImagePicker
import com.lzy.imagepicker.bean.ImageItem import com.lzy.imagepicker.bean.ImageItem
import com.lzy.imagepicker.ui.ImageGridActivity import com.lzy.imagepicker.ui.ImageGridActivity
import com.yidianling.ydlcommon.custom.base.BaseFragment import com.yidianling.ydlcommon.core.base.BaseFragment
import com.yidianling.ydlcommon.custom.remind.ToastHelper import com.yidianling.ydlcommon.custom.utils.remind.ToastHelper
/** /**
* author : Zhangwenchao * author : Zhangwenchao
...@@ -47,7 +47,6 @@ internal class ImagePickerFragment: BaseFragment() { ...@@ -47,7 +47,6 @@ internal class ImagePickerFragment: BaseFragment() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
openCamera = arguments.getBoolean(OPEN_CAMERA, false) openCamera = arguments.getBoolean(OPEN_CAMERA, false)
val intent = Intent(activity, ImageGridActivity::class.java) val intent = Intent(activity, ImageGridActivity::class.java)
// intent.putExtra(ImageGridActivity.EXTRAS_TAKE_PICKERS, openCamera)
startActivityForResult(intent, startActivityForResult(intent,
REQUEST_CODE REQUEST_CODE
) )
...@@ -57,7 +56,6 @@ internal class ImagePickerFragment: BaseFragment() { ...@@ -57,7 +56,6 @@ internal class ImagePickerFragment: BaseFragment() {
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (resultCode == ImagePicker.RESULT_CODE_ITEMS) { if (resultCode == ImagePicker.RESULT_CODE_ITEMS) {
......
package com.yidianling.ydlcommon.custom.imagepicker package com.yidianling.ydlcommon.custom.actions.imagepicker
import com.lzy.imagepicker.bean.ImageItem import com.lzy.imagepicker.bean.ImageItem
......
package com.yidianling.ydlcommon.custom.imagepicker; package com.yidianling.ydlcommon.custom.actions.imagepicker;
import android.app.Activity; import android.app.Activity;
import android.net.Uri; import android.net.Uri;
......
package com.yidianling.ydlcommon.custom.imagepicker package com.yidianling.ydlcommon.custom.actions.imagepicker
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
......
package com.yidianling.ydlcommon.custom.player package com.yidianling.ydlcommon.custom.actions.player
/** /**
* 配置文件 * 配置文件
......
package com.yidianling.ydlcommon.custom.player package com.yidianling.ydlcommon.custom.actions.player
/** /**
* 音乐详情 * 音乐详情
......
package com.yidianling.ydlcommon.custom.player package com.yidianling.ydlcommon.custom.actions.player
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.os.Bundle import android.os.Bundle
import com.yidianling.ydlcommon.custom.player.player.NotifyClickListener import com.yidianling.ydlcommon.custom.actions.player.player.NotifyClickListener
import com.yidianling.ydlcommon.custom.player.service.HMusicPlayService import com.yidianling.ydlcommon.custom.actions.player.service.HMusicPlayService
/** /**
* 音频播放器辅助类 * 音频播放器辅助类
......
package com.yidianling.ydlcommon.custom.player package com.yidianling.ydlcommon.custom.actions.player
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
......
package com.yidianling.ydlcommon.custom.player package com.yidianling.ydlcommon.custom.actions.player
import android.content.ComponentName import android.content.ComponentName
import android.content.ServiceConnection import android.content.ServiceConnection
import android.os.IBinder import android.os.IBinder
import android.text.TextUtils import android.text.TextUtils
import com.yidianling.ydlcommon.core.base.BaseApplication import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.ydlcommon.custom.player.player.PlayStatusListener import com.yidianling.ydlcommon.custom.actions.player.player.PlayStatusListener
import com.yidianling.ydlcommon.custom.player.service.HMusicPlayService import com.yidianling.ydlcommon.custom.actions.player.service.HMusicPlayService
import com.yidianling.ydlcommon.custom.utils.AppUtils import com.yidianling.ydlcommon.custom.utils.AppUtils
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
......
package com.yidianling.ydlcommon.custom.player.notifycation package com.yidianling.ydlcommon.custom.actions.player.notifycation
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import com.yidianling.ydlcommon.custom.player.MusicPlayerHelper import com.yidianling.ydlcommon.custom.actions.player.MusicPlayerHelper
import com.yidianling.ydlcommon.custom.player.service.HMusicPlayService import com.yidianling.ydlcommon.custom.actions.player.service.HMusicPlayService
import android.os.Build import android.os.Build
import java.lang.reflect.Method import java.lang.reflect.Method
......
package com.yidianling.ydlcommon.custom.player.notifycation package com.yidianling.ydlcommon.custom.actions.player.notifycation
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Notification import android.app.Notification
......
package com.yidianling.ydlcommon.custom.player.player package com.yidianling.ydlcommon.custom.actions.player.player
import com.yidianling.ydlcommon.custom.player.MusicInfoBean import com.yidianling.ydlcommon.custom.actions.player.MusicInfoBean
/** /**
......
package com.yidianling.ydlcommon.custom.player.player package com.yidianling.ydlcommon.custom.actions.player.player
/** /**
* 通知栏操作监听器 * 通知栏操作监听器
......
package com.yidianling.ydlcommon.custom.player.player package com.yidianling.ydlcommon.custom.actions.player.player
/** /**
* 播放状态回调 * 播放状态回调
......
package com.yidianling.ydlcommon.custom.player.service package com.yidianling.ydlcommon.custom.actions.player.service
import android.app.Notification import android.app.Notification
import android.app.NotificationManager import android.app.NotificationManager
...@@ -28,12 +28,12 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory ...@@ -28,12 +28,12 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util import com.google.android.exoplayer2.util.Util
import com.yidianling.common.tools.LogUtil import com.yidianling.common.tools.LogUtil
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.player.MusicInfoBean import com.yidianling.ydlcommon.custom.actions.player.MusicInfoBean
import com.yidianling.ydlcommon.custom.player.YDLMusicHelper import com.yidianling.ydlcommon.custom.actions.player.YDLMusicHelper
import com.yidianling.ydlcommon.custom.player.notifycation.NotificationHelper import com.yidianling.ydlcommon.custom.actions.player.notifycation.NotificationHelper
import com.yidianling.ydlcommon.custom.player.player.PlayStatusListener import com.yidianling.ydlcommon.custom.actions.player.player.PlayStatusListener
import com.yidianling.ydlcommon.custom.player.util.LogH import com.yidianling.ydlcommon.custom.actions.player.util.LogH
import com.yidianling.ydlcommon.custom.player.util.UtilH import com.yidianling.ydlcommon.custom.actions.player.util.UtilH
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
......
package com.yidianling.ydlcommon.custom.player.util package com.yidianling.ydlcommon.custom.actions.player.util
import android.util.Log import android.util.Log
......
package com.yidianling.ydlcommon.custom.player.util package com.yidianling.ydlcommon.custom.actions.player.util
import android.content.Context import android.content.Context
import android.text.TextUtils import android.text.TextUtils
import com.yidianling.ydlcommon.custom.player.Config import com.yidianling.ydlcommon.custom.actions.player.Config
/** /**
* 工具类 * 工具类
......
package com.yidianling.ydlcommon.custom.player.view package com.yidianling.ydlcommon.custom.actions.player.view
import android.app.Activity import android.app.Activity
import android.os.Handler import android.os.Handler
...@@ -7,12 +7,12 @@ import android.widget.RelativeLayout ...@@ -7,12 +7,12 @@ import android.widget.RelativeLayout
import android.widget.SeekBar import android.widget.SeekBar
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.player.MusicInfoBean import com.yidianling.ydlcommon.custom.actions.player.MusicInfoBean
import com.yidianling.ydlcommon.custom.player.YDLMusicHelper import com.yidianling.ydlcommon.custom.actions.player.YDLMusicHelper
import com.yidianling.ydlcommon.custom.player.YDLMusicPlayer import com.yidianling.ydlcommon.custom.actions.player.YDLMusicPlayer
import com.yidianling.ydlcommon.custom.player.player.HPlayStatusListener import com.yidianling.ydlcommon.custom.actions.player.player.HPlayStatusListener
import com.yidianling.ydlcommon.custom.player.player.PlayStatusListener import com.yidianling.ydlcommon.custom.actions.player.player.PlayStatusListener
import com.yidianling.ydlcommon.custom.player.service.HMusicPlayService import com.yidianling.ydlcommon.custom.actions.player.service.HMusicPlayService
import kotlinx.android.synthetic.main.play_music_view.view.* import kotlinx.android.synthetic.main.play_music_view.view.*
/** /**
......
package com.yidianling.ydlcommon.custom.share package com.yidianling.ydlcommon.custom.actions.share
import android.app.Activity import android.app.Activity
import android.text.TextUtils import android.text.TextUtils
...@@ -10,8 +10,8 @@ import com.umeng.socialize.media.UMWeb ...@@ -10,8 +10,8 @@ import com.umeng.socialize.media.UMWeb
import com.umeng.socialize.shareboard.ShareBoardConfig import com.umeng.socialize.shareboard.ShareBoardConfig
import com.yidianling.common.tools.LogUtil import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.ToastUtil import com.yidianling.common.tools.ToastUtil
import com.yidianling.ydlcommon.custom.dialog.CustomShareDialog import com.yidianling.ydlcommon.custom.view.dialog.CustomShareDialog
import com.yidianling.ydlcommon.custom.remind.ToastHelper import com.yidianling.ydlcommon.custom.utils.remind.ToastHelper
import com.umeng.socialize.media.UMMin import com.umeng.socialize.media.UMMin
......
...@@ -6,9 +6,9 @@ import com.alibaba.android.arouter.launcher.ARouter ...@@ -6,9 +6,9 @@ import com.alibaba.android.arouter.launcher.ARouter
import com.lzy.imagepicker.ImagePicker import com.lzy.imagepicker.ImagePicker
import com.lzy.imagepicker.view.CropImageView import com.lzy.imagepicker.view.CropImageView
import com.squareup.leakcanary.LeakCanary import com.squareup.leakcanary.LeakCanary
import com.squareup.leakcanary.RefWatcher
import com.yidianling.common.tools.RxTool import com.yidianling.common.tools.RxTool
import com.yidianling.ydlcommon.custom.log.LogHelper import com.yidianling.ydlcommon.custom.utils.BuryPointUtils
import com.yidianling.ydlcommon.custom.utils.log.LogHelper
/** /**
...@@ -25,7 +25,7 @@ object YdlRepository { ...@@ -25,7 +25,7 @@ object YdlRepository {
LogHelper.getInstance().deleteExpireLogSync() LogHelper.getInstance().deleteExpireLogSync()
//初始化工具类 //初始化工具类
RxTool.init(app) RxTool.init(app)
com.yidianling.ydlcommon.custom.tool.BuryPointUtils.init() BuryPointUtils.init()
initImagePicker() initImagePicker()
if (LeakCanary.isInAnalyzerProcess(app)) { if (LeakCanary.isInAnalyzerProcess(app)) {
...@@ -47,9 +47,10 @@ object YdlRepository { ...@@ -47,9 +47,10 @@ object YdlRepository {
} }
ARouter.init(app) ARouter.init(app)
} }
private fun initImagePicker() { private fun initImagePicker() {
val imagePicker = ImagePicker.getInstance() val imagePicker = ImagePicker.getInstance()
imagePicker.imageLoader = com.yidianling.ydlcommon.custom.imagepicker.YdlImageLoader() //设置图片加载器 imagePicker.imageLoader = com.yidianling.ydlcommon.custom.actions.imagepicker.YdlImageLoader() //设置图片加载器
imagePicker.isEdit = true //设置图片是否可编辑 imagePicker.isEdit = true //设置图片是否可编辑
imagePicker.isShowCamera = true //显示拍照按钮 imagePicker.isShowCamera = true //显示拍照按钮
imagePicker.isCrop = true //允许裁剪(单选才有效) imagePicker.isCrop = true //允许裁剪(单选才有效)
......
package com.yidianling.ydlcommon.custom.base
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.support.annotation.LayoutRes
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.LinearLayout
import com.tbruyelle.rxpermissions2.RxPermissions
import com.umeng.analytics.MobclickAgent
import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.ActivityManager
import com.yidianling.ydlcommon.custom.YdlBuryPointUtil
import com.yidianling.ydlcommon.custom.tool.AndroidSystemHelper
import com.yidianling.ydlcommon.custom.tool.StatusBarUtils
import com.yidianling.ydlcommon.custom.ui.LoadingDialogFragment
import com.yidianling.ydlcommon.custom.utils.PlayerFloatHelper
import java.lang.reflect.Field
import kotlin.properties.Delegates
/**
* 基础 Activity,所有的 Activity 都继承此类
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/27
*/
abstract class BaseActivity : SimplyBaseActivity() {
var mContext: Activity by Delegates.notNull()
private var loadingDialogFragment: LoadingDialogFragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
//修复Android 8.0 崩溃
AndroidSystemHelper.fixAndroidOrientationBug(this)
super.onCreate(savedInstanceState)
Log.d("TAG", javaClass.name)
mContext = this
val layoutResId = layoutResId()
if (layoutResId != 0) setContentView(layoutResId())
ActivityManager.getInstance().addStack(this)
initDataAndEvent()
}
override fun setRequestedOrientation(requestedOrientation: Int) {
if (AndroidSystemHelper.isAllowSetOrientation(this)) {
super.setRequestedOrientation(requestedOrientation)
}
}
override fun setContentView(@LayoutRes layoutResID: Int) {
if (isAddStatusView()) {
val containerView = View.inflate(this, R.layout.layout_root, null) as ViewGroup
val rootView = containerView.findViewById<LinearLayout>(R.id.ll_root);
initStatus(rootView);
val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
val child = View.inflate(this, layoutResID, null)
rootView.addView(child, params)
super.setContentView(containerView)
} else {
super.setContentView(layoutResID)
}
}
var statusView: View? = null
/**
* 初始化状态栏
*/
private fun initStatus(rootView: View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
statusView = rootView.findViewById<View>(R.id.view_status_place_holder)
statusView?.setBackgroundColor(Color.parseColor(getStatusColor()))
val statusBarHeight = StatusBarUtils.getStatusBarHeight(this)
val layoutParams = statusView?.getLayoutParams() as LinearLayout.LayoutParams
layoutParams.height = statusBarHeight
statusView?.layoutParams = layoutParams
StatusBarUtils.setTransparentForImageView(this, null)
}
if (statusBarDarkMode()) {
StatusBarUtils.statusBarLightMode(this)
}
}
override fun onDestroy() {
super.onDestroy()
ActivityManager.getInstance().removeStack(this)
fixInputMethodManagerLeak()
PlayerFloatHelper.removeView(this)
}
override fun onResume() {
super.onResume()
try {
if (this !is com.yidianling.ydlcommon.custom.h5.NewH5Activity && this::class.java.simpleName != "MainActivity") {
YdlBuryPointUtil.sendPv(this::class.java.simpleName)
}
} catch (e: Exception) {
e.printStackTrace()
}
MobclickAgent.onResume(this)
PlayerFloatHelper.showIfPlaying(this)
}
override fun onPause() {
super.onPause()
MobclickAgent.onPause(this)
}
@LayoutRes
protected abstract fun layoutResId(): Int
// 初始化数据和事件
protected abstract fun initDataAndEvent()
/**
* 请求运行时权限
* @param permissions 权限
* @param callback 回调接口
*/
protected fun requestPermissions(callback: PermissionCallback, vararg permissions: String) {
RxPermissions(this).request(*permissions)
.subscribe {
if (it) callback.onGranted()
else callback.onDenied()
}
}
fun showProgressDialog() {
showProgressDialog("")
}
//显示dialog
open fun showProgressDialog(str: String?) {
if (loadingDialogFragment == null) {
loadingDialogFragment = LoadingDialogFragment.newInstance(str)
}
if (loadingDialogFragment?.isAdded!!) {
return
}
loadingDialogFragment?.show(supportFragmentManager, BaseActivity::class.java.simpleName)
}
//移除dialog
open fun dismissProgressDialog() {
try {
if (loadingDialogFragment != null && loadingDialogFragment?.isAdded!!) {
loadingDialogFragment?.hide()
loadingDialogFragment = null
}
} catch (e: Exception) {
//防止以下错误
//java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
}
}
var resourcesConfig :Configuration ?=null
override fun getResources(): Resources {
//解决 修改系统字体大小后 H5页面大小比例不正常现象
val res = super.getResources()
if (resourcesConfig == null){
//避免重复创建
resourcesConfig = Configuration()
resourcesConfig!!.setToDefaults()
}
res.updateConfiguration(resourcesConfig, res.displayMetrics)
return res
}
/**
* 解决 InputMethodManager 导致的内存泄漏问题
*/
public fun fixInputMethodManagerLeak() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
return
}
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
val arr = arrayOf("mCurRootView", "mServedView", "mNextServedView")
var f: Field?
var obj_get: Any?
for (i in arr.indices) {
val param = arr[i]
try {
f = imm.javaClass.getDeclaredField(param)
if (f!!.isAccessible === false) {
f!!.isAccessible = true
} // author: sodino mail:sodino@qq.com
obj_get = f!!.get(imm)
if (obj_get != null && obj_get is View) {
val v_get = obj_get as View?
if (v_get!!.context === this) { // 被InputMethodManager持有引用的context是想要目标销毁的
f.set(imm, null) // 置空,破坏掉path to gc节点
} else {
// 不是想要目标销毁的,即为又进了另一层界面了,不要处理,避免影响原逻辑,也就不用继续for循环了
break
}
}
} catch (t: Throwable) {
t.printStackTrace()
}
}
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/05/09
*
* 基础数据管理类
*
*/
interface BaseDataManager<out R: BaseRam, out L: BaseLocal, out H: BaseHttp> {
fun getRam(): R
fun getLocal(): L
fun getHttp(): H
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.support.annotation.LayoutRes
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.tbruyelle.rxpermissions2.RxPermissions
import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.YdlBuryPointUtil
import com.yidianling.ydlcommon.custom.tool.StatusBarUtils
import com.yidianling.ydlcommon.custom.ui.LoadingDialogFragment
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/27
*
* 若需要采用Lazy方式加载的Fragment,初始化内容放到 initDataAndEventLazy 实现
* 若不需要Lazy加载则初始化内容放到 initDataAndEvent 即可
*
* 注意事项 1:
* 如果是与ViewPager一起使用,调用的是setUserVisibleHint。
*
* 注意事项 2:
* 如果是通过FragmentTransaction的show和hide的方法来控制显示,调用的是onHiddenChanged.
* 针对初始就show的Fragment 为了触发onHiddenChanged事件 达到lazy效果 需要先hide再show
*/
abstract class BaseFragment : Fragment() {
//Fragment的View加载完毕的标记
private var isViewCreated: Boolean = false
//Fragment对用户可见的标记
private var isUIVisible: Boolean = false
//Fragment 第一次加载的标记
private var isFirstLoad: Boolean = false
//是否有setUserVisibleHint方法
private var isSetUserVisibleHint = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
isFirstLoad = true
//如果未调用过SetUserVisibleHint方法,则在此埋点,防止数据重复
if (!isSetUserVisibleHint) {
try {
YdlBuryPointUtil.sendPv(this::class.java.simpleName)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val layoutResId = layoutResId()
return when {
layoutResId != 0 -> {
val childView = inflater.inflate(layoutResId, container, false)
if (isAddStatusView()){
val containerView = inflater.inflate(R.layout.layout_root, container, false)
val rootView = containerView.findViewById<LinearLayout>(R.id.ll_root);
initStatus(rootView);
rootView.addView(childView)
return rootView
}else{
return childView;
}
}
else -> super.onCreateView(inflater, container, savedInstanceState)
}
}
/**
* 初始化状态栏
*/
private fun initStatus(rootView:View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val statusView = rootView.findViewById<View>(R.id.view_status_place_holder)
statusView.setBackgroundColor(Color.parseColor(getStatusColor()))
val statusBarHeight = StatusBarUtils.getStatusBarHeight(activity)
val layoutParams = statusView.getLayoutParams() as LinearLayout.LayoutParams
layoutParams.height = statusBarHeight
statusView.layoutParams = layoutParams
}
}
protected lateinit var rootView: View
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
isViewCreated = true
rootView = view
initDataAndEvent()
lazyLoad()
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
isUIVisible = isVisibleToUser
isSetUserVisibleHint = true
lazyLoad()
if (isVisibleToUser) {
try {
YdlBuryPointUtil.sendPv(this::class.java.simpleName)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
isUIVisible = !hidden
lazyLoad()
}
private fun lazyLoad() {
if (isViewCreated && isUIVisible && isFirstLoad) {
initDataAndEventLazy()
//数据加载完毕,恢复标记,防止重复加载
isFirstLoad = false
}
}
override fun onDestroy() {
super.onDestroy()
isSetUserVisibleHint = false
// YdlRepository.getRefWatcher().watch(this)
}
// 请求运行时权限
protected fun requestPermissions(callback: PermissionCallback, vararg permissions: String) {
RxPermissions(activity).request(*permissions)
.subscribe {
if (it) callback.onGranted()
else callback.onDenied()
}
}
private var loadingDialogFragment: LoadingDialogFragment? = null
protected fun showProgressDialog(msg: String) {
if (loadingDialogFragment == null) {
loadingDialogFragment = LoadingDialogFragment.Companion.newInstance(msg)
}
loadingDialogFragment?.show(childFragmentManager, null)
}
protected fun dismissProgressDialog() {
if (loadingDialogFragment != null && loadingDialogFragment!!.isAdded) {
loadingDialogFragment!!.hide()
loadingDialogFragment = null
}
}
@LayoutRes
abstract fun layoutResId(): Int
abstract fun initDataAndEvent()
abstract fun initDataAndEventLazy()
protected var callback: Callback? = null
fun setCallback(callback: Callback): Fragment {
this.callback = callback
return this
}
open fun isAddStatusView(): Boolean{
return false
}
open fun getStatusColor(): String{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return "#FFFFFF"
}
return "#1da1f2"
}
// 用于单 fragment 的 activity 中用于替换 fragment 的接口
interface Callback {
fun replace(fragment: Fragment)
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
interface BaseHttp
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
interface BaseLocal
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
interface BaseRam
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
/**
* Android 6.0 以上运行时权限回调接口
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/02/28
*/
interface PermissionCallback {
fun onGranted()
fun onDenied()
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.support.annotation.LayoutRes
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.tool.AndroidBug5497Workaround
import com.yidianling.ydlcommon.custom.tool.StatusBarUtils
/**
* 简单的基础 Activity,只提供通用基础功能
*/
abstract class SimplyBaseActivity : AppCompatActivity() {
override fun setContentView(@LayoutRes layoutResID: Int) {
if (isAddStatusView()){
val containerView = View.inflate(this, R.layout.layout_root, null) as ViewGroup
val rootView = containerView.findViewById<LinearLayout>(R.id.ll_root);
initStatus(rootView);
val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
val child = View.inflate(this, layoutResID, null)
rootView.addView(child, params)
super.setContentView(containerView)
com.yidianling.ydlcommon.custom.tool.AndroidBug5497Workaround.assistActivity(this);
}else{
super.setContentView(layoutResID)
}
}
/**
* 初始化状态栏
*/
private fun initStatus(rootView:View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val statusView = rootView.findViewById<View>(R.id.view_status_place_holder)
statusView.setBackgroundColor(Color.parseColor(getStatusColor()))
val statusBarHeight = StatusBarUtils.getStatusBarHeight(this)
val layoutParams = statusView.getLayoutParams() as LinearLayout.LayoutParams
layoutParams.height = statusBarHeight
statusView.layoutParams = layoutParams
StatusBarUtils.setTransparentForImageView(this, null)
}
if (statusBarDarkMode()){
StatusBarUtils.statusBarLightMode(this)
}
}
override fun getResources(): Resources {
//解决 修改系统字体大小后 H5页面大小比例不正常现象
val res = super.getResources()
val config = Configuration()
config.setToDefaults()
res.updateConfiguration(config, res.displayMetrics)
return res
}
open fun isAddStatusView(): Boolean{
return false
}
open fun statusBarDarkMode(): Boolean{
return false
}
open fun getStatusColor(): String{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return "#FFFFFF"
}
return "#1da1f2"
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.base
import android.support.v4.app.Fragment
import com.yidianling.ydlcommon.R
/**
* 单个 Fragment 的 Activity,使用 Fragment 代替 Activity
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/27
*/
abstract class SingleFragmentActivity: BaseActivity() {
override final fun layoutResId(): Int {
return R.layout.activity_fragment
}
private val fm = supportFragmentManager
override fun initDataAndEvent() {
var fragment = fm.findFragmentById(R.id.fragment_container)
if (fragment == null) {
fragment = createFragment()
fm.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit()
}
}
// 切换 fragment
fun replace(fragment: Fragment) {
fm.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit()
}
protected abstract fun createFragment(): Fragment
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.bean
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/7/17
*/
data class CourseButtonBean(
var code: Int,//按钮状态码 5下单 2进入音频播放页 3进入群直播间 4选择子课程 11进入直播课程 13进入视频播放页 ,
var desc: String,//按钮文案
var isRebate: String,//是否是促销返利 1是双返利 2是单返利 0无返利 ,
var signUpTime: String,//报名时间
var type: Boolean//是否允许点击 true点击
)
\ No newline at end of file
package com.yidianling.ydlcommon.custom.bean
import com.yidianling.ydlcommon.custom.data.ShareData
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/7/11
*/
data class CourseExtraBean(
/**
* 课程价格
*/
var applyFee: String,
/**
* 课程类型 1.音频课程 2.线下 3.app群直播 4.app音视频直播 5.站外课程 6.系列课程 7.视频课程 8.app视频直播 ,
*/
var courseType: Int,
/**
* 是否包含音视频 1:只有音频 2:只有视屏 3:音视频都有
*/
var mediaTypes: Int,
/**
* 咨询师头像
*/
var doctorHead: String,
/**
* 咨询师名字
*/
var doctorName: String,
/**
* 课程id
*/
var id: String,
/**
* 是否购买
*/
var isBuy: Boolean,
/**
* 课程原价
*/
var originalApplyFee: String,
/**
* 课程图
*/
var pic: String,
/**
* 子课程数量
*/
var serialsNumber: Int,
/**
* 分享数据
*/
var shareData: ShareData,
/**
* 课程标题
*/
var title: String,
/**
* 用户评论次数:等于大于1表示评论过
*/
var userCommentNum: Int
)
\ No newline at end of file
package com.yidianling.ydlcommon.custom.bean
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/7/11
*/
data class CourseMediaBean(
/**
* 课程id ,
*/
var courseId: String,
/**
* 课程主讲人名字
*/
var doctorName: String,
/**
* 资料类型 1.音频 2.视频 ,
*/
var mediaType: Int,
/**
* 课程标题 ,
*/
var title: String,
/**
* 课程url ,
*/
var url: String,
/**
* 当前是否在播放
*/
var isPlaying: Boolean = false,
/**
* 是否是试听
*/
var isDemo: Boolean = false
)
\ No newline at end of file
package com.yidianling.ydlcommon.custom.bean
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/7/11
*/
data class CourseMediaDetailBean(
/**
* 课程概括
*/
val courseExtra: CourseExtraBean,
/**
* 试听
*/
val voiceSample: CourseMediaGroupBean,
/**
* 系列音/视频
*/
val voiceWhole: CourseMediaGroupBean
)
\ No newline at end of file
package com.yidianling.ydlcommon.custom.bean
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/7/11
*/
data class CourseMediaGroupBean(
/**
* 是否购买
*/
var isBuy: Boolean,
/**
* //是否是系列课
*/
var isSeries: Boolean,
/**
* 音频列表
*/
var courseMedia: List<CourseMediaBean>
)
\ No newline at end of file
package com.yidianling.ydlcommon.custom.data; package com.yidianling.ydlcommon.custom.bean;
public class MustUP { public class MustUP {
public VersionData version; public VersionData version;
......
package com.yidianling.ydlcommon.custom.data package com.yidianling.ydlcommon.custom.bean
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import java.io.Serializable import java.io.Serializable
......
package com.yidianling.ydlcommon.custom.data; package com.yidianling.ydlcommon.custom.bean;
import java.io.Serializable; import java.io.Serializable;
......
package com.yidianling.ydlcommon.custom.bean
import java.io.Serializable
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/8
*/
data class WebViewTimeBean(
val url: String,//加载的url
val initTime: String,//webview初始化时间
val loadTime: String,//加载url时间
val ffrom: String,//渠道
val osBuild: String,//设备信息
val version: String,//版本
val ts: String,//时间
val isFromApp: String,//2表示专家版1表示用户版
val uid: String,//用户uid,未登录时为""
val netSpeed: String,//网速
val netStatus: String//网络状态(wifi 4G 2G 3G
) : Serializable
\ No newline at end of file
package com.yidianling.ydlcommon.custom.bean;
/**
* @author yuanWai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/12/12
*/
public class YDLBaseDataBean {
public int endRow;
public boolean hasNextPage;
public boolean hasPreviousPage;
public boolean isFirstPage;
public boolean isLastPage;
public int navigateFirstPage = 0;
public int navigateLastPage = 0;
public int navigatePages = 0;
public int nextPage = 0;
public int pageNum = 0;
public int pageSize = 0;
/**
* 总页数
*/
public int pages = 0;
public int prePage = 0;
public int size = 0;
public int startRow = 0;
/**
* 数据总条数
*/
public int total = 0;
}
package com.yidianling.ydlcommon.custom.bean
import java.io.Serializable
/**
* @author yuanwai
* @描述:数据bean公共类--footer bean
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/10
*/
data class YDLFooterBean(/**
* 标题
*/
val title : String,
/**
* 1.http开头的 跳转 H5 2.app开头的 跳转原生界面
*/
val linkUrl : String) : Serializable
\ No newline at end of file
package com.yidianling.ydlcommon.custom.bean
import java.io.Serializable
/**
* @author yuanwai
* @描述:数据bean公共类--head bean
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/10
*/
data class YDLHeadBean(
/**
* 标题
*/
val title : String?,
/**
* 副标题
*/
val subTitle : String?,
/**
* 副标题跳转地址
*/
val subLinkUrl: String?) : Serializable
\ No newline at end of file
package com.yidianling.ydlcommon.custom.chat;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.yidianling.ydlcommon.R;
/**
* @author yuanwai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/7
*/
public class ChatPrivateTips extends FrameLayout{
public ChatPrivateTips(@NonNull Context context) {
super(context);
initView();
}
public ChatPrivateTips(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
public ChatPrivateTips(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView(){
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
View.inflate(getContext(), R.layout.dialog_chat_tips,this);
setLayoutParams(params);
}
}
package com.yidianling.ydlcommon.custom.data; package com.yidianling.ydlcommon.custom.constant;
/** /**
* 一些常量字符串 * 一些常量字符串
......
package com.yidianling.ydlcommon.custom.constant;
/**
* @author jiucheng
* @描述:页面参数传递常量
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/11/7
*/
public interface IntentConstants {
String INTENT_EXPERT_HEAD_URL = "intent_expert_head_url";
String INTENT_EXPERT_NAME = "intent_expert_name";
String INTENT_EXPERT_TIPS = "intent_expert_tips";
String INTENT_ROOM_ID = "intent_room_id";
String INTENT_REMAIN_TIME = "intent_remain_time";
String INTENT_RELATION_ID = "intent_relation_id";
String INTENT_CALL_ID = "INTENT_CALL_ID";
String INTENT_TOKEN = "intent_token";
String INTENT_SIGNAL_TOKEN= "intent_signal_token";
String INTENT_LISTENER_UID= "intent_listener_uid";
String INTENT_TOTAL_DURATION= "intent_total_duration";
String INTENT_LISTEN_ID= "intent_listen_id";
String INTENT_COMMENT_URL= "intent_comment_url";
}
package com.yidianling.ydlcommon.custom.constant;
/**
* @author jiucheng
* @描述:友盟统计--数据埋点常量
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/9/27
*/
public interface UMConstants {
/**
* =======================事件名常量===========================
*/
String EVENT_HOMEPAGER_BANNER_CLICK = "首页banner点击";
String EVENT_HOMEPAGER_CONFIDE_CLICK = "首页咨询分类点击";
String EVENT_HOMEPAGER_LOOP_CLICK = "首页轮播点击";
String EVENT_HOMEPAGER_CATEGORY_CLICK = "首页类目分类点击";
String EVENT_HOMEPAGER_COURSE_CLICK = "首页推荐课程点击";
String EVENT_HOMEPAGER_COURSE_MORE_CLICK = "首页推荐课程更多按钮点击";
String EVENT_HOMEPAGER_HOT_TOPIC_CLICK = "首页热门话题点击";
String EVENT_HOMEPAGER_HOT_TOPIC_MORE_CLICK = "首页热门话题更多点击";
String EVENT_TEST_HOME_SEARCH_CLICK = "测评主页搜索";
String EVENT_TEST_HOME_MINE_CLICK = "测评主页个人中心图标点击";
String EVENT_TEST_HOME_BANNER_CLICK = "测评主页banner点击";
String EVENT_TEST_HOME_CATEGORY_CLICK = "测评主页测评分类点击";
String EVENT_TEST_HOME_LOOP_CLICK = "测评主页轮播点击";
String EVENT_TEST_HOME_DAILY_CLICK = "测评主页每日精选点击";
String EVENT_TEST_HOME_DAILY_CHANGE_CLICK = "测评主页每日精选换一换点击";
String EVENT_TEST_HOME_HOT_CLICK = "测评主页热门推荐点击";
String EVENT_TEST_LIST_SEARCH_CLICK = "测评列表页搜索";
String EVENT_TEST_LIST_MORE_CLICK = "测评列表页更多点击";
String EVENT_TEST_LIST_CATEGORY_CLICK = "测评列表页分类点击";
String EVENT_TEST_LIST_TEST_TITLE_CLICK = "测评列表页测评题点击";
String EVENT_TEST_DETAIL_SHARE_CLICK = "测评详情页顶部分享点击";
String EVENT_TEST_DETAIL_START_CLICK = "测评详情页立即测试点击";
String EVENT_TEST_DETAIL_MORE_CLICK = "测评详情页更多点击";
String EVENT_PAY_CLICK = "支付页面底部按钮点击";
String EVENT_TEST_RESULT_BOTTOM_CLICK = "测评结果页底部点击";
String EVENT_TEST_RESULT_MORE_CLICK = "测评结果页更多点击";
String EVENT_TEST_RESULT_SHARE_CLICK = "测评结果页顶部分享点击";
String EVENT_EXPERT_SEARCH_CLICK = "搜索";
String EVENT_EXPERT_TOP_GUIDE_CLICK = "顶部引导点击";
String EVENT_EXPERT_FILTER_CLICK = "筛选";
String EVENT_EXPERT_CLICK = "列表点击";
String EVENT_DOWN_ORDER_NAME_CLICK = "姓名点击";
String EVENT_DOWN_ORDER_AGE_CLICK = "年龄点击";
String EVENT_DOWN_ORDER_PHONE_CLICK = "手机点击";
String EVENT_DOWN_ORDER_DES_CLICK = "描述点击";
String EVENT_DOWN_ORDER_COMMIT_CLICK = "提交点击";
/**
* =======================属性名常量===========================
*/
String PROPERTY_HOMEPAGER_BANNER_URL = "banner链接";
String PROPERTY_HOMEPAGER_CONFIDE_ID = "分类id";
String PROPERTY_HOMEPAGER_CONFIDE_NAME = "分类名称";
String PROPERTY_HOMEPAGER_LOOP_NAME = "轮播信息";
String PROPERTY_HOMEPAGER_CATEGORY_NAME = "名称";
String PROPERTY_HOMEPAGER_COURSE_NAME = "课程推荐名称";
String PROPERTY_HOMEPAGER_COURSE_URL = "课程推荐连接";
String PROPERTY_HOMEPAGER_HOT_TOPIC_NAME = "热门话题名称";
String PROPERTY_TEST_HOME_BANNER_URL = "banner链接";
String PROPERTY_TEST_HOME_BANNER_NAME = "banner标题";
String PROPERTY_TEST_HOME_CATEGORY_ID = "分类id";
String PROPERTY_TEST_HOME_CATEGORY_NAME = "分类名称";
String PROPERTY_TEST_HOME_LOOP_NAME = "轮播信息";
String PROPERTY_TEST_HOME_DAILY_NAME = "每日精选名称";
String PROPERTY_TEST_HOME_DAILY_URL = "每日精选链接";
String PROPERTY_TEST_HOME_HOT_URL = "热门推荐链接";
String PROPERTY_TEST_HOME_HOT_NAME = "热门推荐标题";
String PROPERTY_TEST_LIST_CATEGORY_NAME = "分类名称";
String PROPERTY_TEST_LIST_TEST_NAME = "测评标题";
String PROPERTY_TEST_DETAIL_SHARE_NAME = "分享标题";
String PROPERTY_PAY_WAYS_NAME = "支付方式名称";
String PROPERTY_PAY_NAME = "支付商品名称";
String PROPERTY_EST_RESULT_BOTTOM_NAME = "按钮名称";
String PROPERTY_EST_RESULT_SHARE_NAME = "测评名称";
String PROPERTY_EST_RESULT_TEST_NAME = "测评标题";
String PROPERTY_EXPERT_SEARCH_KEY_WORDS = "关键字";
String PROPERTY_EXPERT_TOP_GUIDE_NAME = "模块名称";
String PROPERTY_EXPERT_FILTER_THEME = "主题";
String PROPERTY_EXPERT_FILTER_AREA = "地区";
String PROPERTY_EXPERT_FILTER_SORT = "排序";
String PROPERTY_EXPERT_LIST_ID = "咨询师id";
String PROPERTY_EXPERT_LIST_NAME = "咨询师名称";
String PROPERTY_EXPERT_LIST_CHAT = "咨询师私聊";
String PROPERTY_DOWN_ORDER_NAME = "姓名点击";
String PROPERTY_DOWN_ORDER_AGE = "年龄点击";
String PROPERTY_DOWN_ORDER_PHONE = "手机点击";
String PROPERTY_DOWN_ORDER_DES = "描述点击";
String PROPERTY_DOWN_ORDER_COMMIT = "提交点击";
}
...@@ -9,7 +9,7 @@ import com.yidianling.ydlcommon.BuildConfig ...@@ -9,7 +9,7 @@ import com.yidianling.ydlcommon.BuildConfig
* e-mail : zhangwch@yidianling.com * e-mail : zhangwch@yidianling.com
* time : 2018/02/01 * time : 2018/02/01
*/ */
class YdlConstants { class YDLConstants {
companion object { companion object {
/** /**
...@@ -19,24 +19,9 @@ class YdlConstants { ...@@ -19,24 +19,9 @@ class YdlConstants {
const val HOLDER_PARAM = "holder_param" const val HOLDER_PARAM = "holder_param"
// activity 跳转时传递数据的 bundle 的名称 // activity 跳转时传递数据的 bundle 的名称
const val BUNDLE = "bundle" const val BUNDLE = "bundle"
const val API_HOST = BuildConfig.SERVER_URL
var API_HOST_H5 = com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.H5_URL!!
var API_HOST_WEB = com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.WEB_URL!!
const val SHAREZJ = com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.M_BASE_URL + "experts/"
const val BIND_PHONE_ACTION = "wxbind" const val BIND_PHONE_ACTION = "wxbind"
const val HELP_URL = "https://h2.yidianling.com/ex-help/96" const val HELP_URL = "https://h2.yidianling.com/ex-help/96"
var ZJZHUYE = API_HOST_H5 + "experts/"
const val SILENCED_CODE = 1000020 const val SILENCED_CODE = 1000020
//预约详情
var YUYDETAIL = API_HOST_H5 + "booking/order-detail?orderid="
const val PUBLISH_TYPE = "publish_type" const val PUBLISH_TYPE = "publish_type"
} }
......
package com.yidianling.ydlcommon.custom.course
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import com.alibaba.android.arouter.launcher.ARouter
import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.ydlcommon.custom.player.MusicPlayerHelper
import com.yidianling.ydlcommon.custom.player.player.NotifyClickListener
import com.yidianling.ydlcommon.custom.player.service.HMusicPlayService
@SuppressLint("StaticFieldLeak")
/**
* 课程播放控制类
* Created by harvie on 2015/4/28.
*/
object CoursePlayer {
val TAG = "CoursePlayer"
init {
MusicPlayerHelper.listener = object :
NotifyClickListener {
override fun notifyDetailClick() {
//点击通知栏详情
startCoursePlayActivity(
mContext,
1
)
}
}
}
var mContext = BaseApplication.getApp()
var course_id: Int = 0//课程id
var headUrl: String? = null //专家头像
var playType = 0//播放类型 1.课程播放 2.课程试听
//播放控制参数
var musicControl: HMusicPlayService.MusicController? = null
fun isPlaying(): Boolean {
return musicControl?.isPlaying() ?: false
}
fun pause() {
MusicPlayerHelper.pause(mContext)
}
fun play() {
MusicPlayerHelper.start(mContext)
}
/**
* 跳转音频课程播放,仅通过快捷方式进入课程时使用
* from 1表示通知栏点进来,2表示悬浮图标点进来
*/
fun startCoursePlayActivity(context: Context?, from: Int) {
if (context != null && course_id > 0) {
// val intent = Intent(context, CoursePlayActivity::class.java)
// intent.putExtra("course_id", course_id)
// intent.putExtra("course_type", playType)
// intent.putExtra("from", from)
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// context.startActivity(intent)
// val it = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
// context.sendBroadcast(it)
ARouter.getInstance()
.build("/course/play")
.withInt("course_id", course_id)
.withInt("course_type", playType)
.withInt("from",from)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.navigation()
}
}
fun onDestroy(context: Context) {
course_id = 0
headUrl = null
musicControl?.pause()
musicControl = null
//销毁后台服务
MusicPlayerHelper.stopService(context)
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http package com.yidianling.ydlcommon.custom.data
import com.yidianling.ydlcommon.custom.base.BaseHttp import com.yidianling.ydlcommon.custom.http.BaseResponse
import com.yidianling.ydlcommon.custom.http.LogParam
import com.yidianling.ydlcommon.custom.http.params.* import com.yidianling.ydlcommon.custom.http.params.*
import com.yidianling.ydlcommon.custom.http.response.Balance import com.yidianling.ydlcommon.custom.http.response.Balance
import com.yidianling.ydlcommon.custom.http.response.Recharge import com.yidianling.ydlcommon.custom.http.response.Recharge
...@@ -15,32 +16,32 @@ import io.reactivex.Observable ...@@ -15,32 +16,32 @@ import io.reactivex.Observable
* e-mail : zhangwch@yidianling.com * e-mail : zhangwch@yidianling.com
* time : 2018/02/03 * time : 2018/02/03
*/ */
interface YdlCommonHttp: BaseHttp { interface IPlatformHttp {
fun uploadLog(param: LogParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Any>> fun uploadLog(param: LogParam): Observable<BaseResponse<Any>>
fun wxRecharge(param: WXRechargeIdParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<WXPay>> fun wxRecharge(param: WXRechargeIdParam): Observable<BaseResponse<WXPay>>
fun getBalance(param: BalanceParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Balance>> fun getBalance(param: BalanceParam): Observable<BaseResponse<Balance>>
//获取红包列表 //获取红包列表
fun getCoupon() : Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<ArrayList<RedPacketBean>>> fun getCoupon() : Observable<BaseResponse<ArrayList<RedPacketBean>>>
//测评下单接口 //测评下单接口
fun addOrder(param : AddOrderParam) : Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<TestAddOrderBean>> fun addOrder(param : AddOrderParam) : Observable<BaseResponse<TestAddOrderBean>>
// 获得充值单号 // 获得充值单号
fun recharge(param: RechargeParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Recharge>> fun recharge(param: RechargeParam): Observable<BaseResponse<Recharge>>
// 付款 // 付款
fun pay(param: BalancePayParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Any>> fun pay(param: BalancePayParam): Observable<BaseResponse<Any>>
// 微信支付 // 微信支付
fun wxPay(param: PayParam.WxPayParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<WXPay>> fun wxPay(param: PayParam.WxPayParam): Observable<BaseResponse<WXPay>>
// 阿里支付 // 阿里支付
fun aliPay(param: PayParam.AliPayParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Recharge>> fun aliPay(param: PayParam.AliPayParam): Observable<BaseResponse<Recharge>>
//获取红包列表 //获取红包列表
fun getRedList(param: RedListParam) : Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Any>> fun getRedList(param: RedListParam) : Observable<BaseResponse<Any>>
} }
\ No newline at end of file
package com.yidianling.ydlcommon.custom.data package com.yidianling.ydlcommon.custom.data
import com.yidianling.ydlcommon.custom.base.BaseLocal
/** /**
* author : Zhangwenchao * author : Zhangwenchao
* e-mail : zhangwch@yidianling.com * e-mail : zhangwch@yidianling.com
* time : 2018/04/26 * time : 2018/04/26
*/ */
interface YdlLocal: BaseLocal { interface IPlatformLocal{
//消息语音提示 //消息语音提示
fun isVoice(): Boolean fun isVoice(): Boolean
......
package com.yidianling.ydlcommon.custom.data package com.yidianling.ydlcommon.custom.data
import com.yidianling.ydlcommon.custom.GlobalInfo import com.yidianling.ydlcommon.custom.GlobalInfo
import com.yidianling.ydlcommon.custom.base.BaseRam
/** /**
* author : Zhangwenchao * author : Zhangwenchao
* e-mail : zhangwch@yidianling.com * e-mail : zhangwch@yidianling.com
* time : 2018/05/03 * time : 2018/05/03
*/ */
interface YdlRam: BaseRam { interface IPlatformRam{
fun getGlobalInfo(): GlobalInfo? fun getGlobalInfo(): GlobalInfo?
......
package com.yidianling.ydlcommon.custom.data
object PlatformDataManager {
fun getRam(): IPlatformRam {
return PlatformRamImpl.getInstance()
}
fun getLocal(): IPlatformLocal {
return PlatformLocalImpl.getInstance()
}
fun getHttp(): IPlatformHttp {
return PlatformHttpImpl.getInstance()
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http package com.yidianling.ydlcommon.custom.data
import com.yidianling.ydlcommon.core.base.BaseApplication import com.ydl.ydlnet.YDLHttpUtils
import com.yidianling.common.tools.RxAppTool import com.yidianling.common.tools.RxAppTool
import com.yidianling.common.tools.RxDeviceTool import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.ydlcommon.custom.http.*
import com.yidianling.ydlcommon.custom.http.params.* import com.yidianling.ydlcommon.custom.http.params.*
import com.yidianling.ydlcommon.custom.http.response.Balance import com.yidianling.ydlcommon.custom.http.response.Balance
import com.yidianling.ydlcommon.custom.http.response.Recharge import com.yidianling.ydlcommon.custom.http.response.Recharge
...@@ -23,10 +25,10 @@ import okhttp3.RequestBody ...@@ -23,10 +25,10 @@ import okhttp3.RequestBody
* e-mail : zhangwch@yidianling.com * e-mail : zhangwch@yidianling.com
* time : 2018/02/05 * time : 2018/02/05
*/ */
class YdlCommonHttpImpl private constructor() : YdlCommonHttp { class PlatformHttpImpl private constructor() : IPlatformHttp {
companion object { companion object {
fun getInstance(): YdlCommonHttpImpl { fun getInstance(): PlatformHttpImpl {
return Holder.INSTANCE return Holder.INSTANCE
} }
...@@ -39,14 +41,13 @@ class YdlCommonHttpImpl private constructor() : YdlCommonHttp { ...@@ -39,14 +41,13 @@ class YdlCommonHttpImpl private constructor() : YdlCommonHttp {
private fun getYdlCommonApi(): YdlCommonApi { private fun getYdlCommonApi(): YdlCommonApi {
if (api == null) { if (api == null) {
api = RetrofitProvider.getRetrofit() api = YDLHttpUtils.obtainApi(YdlCommonApi::class.java)
.create(YdlCommonApi::class.java)
} }
return api!! return api!!
} }
override fun uploadLog(param: LogParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Any>> { override fun uploadLog(param: LogParam): Observable<BaseResponse<Any>> {
// return RxUtils.mapObservable(param) // return RxUtils.mapObservable(param)
// .flatMap { api.uploadLog(it) } // .flatMap { api.uploadLog(it) }
return Observable.just(param) return Observable.just(param)
...@@ -77,37 +78,37 @@ class YdlCommonHttpImpl private constructor() : YdlCommonHttp { ...@@ -77,37 +78,37 @@ class YdlCommonHttpImpl private constructor() : YdlCommonHttp {
.flatMap { getYdlCommonApi().uploadLog(it) } .flatMap { getYdlCommonApi().uploadLog(it) }
} }
override fun wxRecharge(param: WXRechargeIdParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<WXPay>> { override fun wxRecharge(param: WXRechargeIdParam): Observable<BaseResponse<WXPay>> {
return RxUtils.mapObservable(param) return RxUtils.mapObservable(param)
.flatMap { getYdlCommonApi().wxRecharge(it) } .flatMap { getYdlCommonApi().wxRecharge(it) }
} }
override fun getBalance(param: BalanceParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Balance>> { override fun getBalance(param: BalanceParam): Observable<BaseResponse<Balance>> {
return RxUtils.mapObservable(param) return RxUtils.mapObservable(param)
.flatMap { getYdlCommonApi().getBalance(it) } .flatMap { getYdlCommonApi().getBalance(it) }
} }
override fun recharge(param: RechargeParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Recharge>> { override fun recharge(param: RechargeParam): Observable<BaseResponse<Recharge>> {
return RxUtils.mapObservable(param) return RxUtils.mapObservable(param)
.flatMap { getYdlCommonApi().recharge(it) } .flatMap { getYdlCommonApi().recharge(it) }
} }
override fun pay(param: BalancePayParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Any>> { override fun pay(param: BalancePayParam): Observable<BaseResponse<Any>> {
return RxUtils.mapObservable(param) return RxUtils.mapObservable(param)
.flatMap { getYdlCommonApi().pay(it) } .flatMap { getYdlCommonApi().pay(it) }
} }
override fun wxPay(param: PayParam.WxPayParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<WXPay>> { override fun wxPay(param: PayParam.WxPayParam): Observable<BaseResponse<WXPay>> {
return RxUtils.mapObservable(param) return RxUtils.mapObservable(param)
.flatMap { getYdlCommonApi().wxPay(it) } .flatMap { getYdlCommonApi().wxPay(it) }
} }
override fun aliPay(param: PayParam.AliPayParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Recharge>> { override fun aliPay(param: PayParam.AliPayParam): Observable<BaseResponse<Recharge>> {
return RxUtils.mapObservable(param) return RxUtils.mapObservable(param)
.flatMap { getYdlCommonApi().aliPay(it) } .flatMap { getYdlCommonApi().aliPay(it) }
} }
override fun getCoupon(): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<ArrayList<RedPacketBean>>> { override fun getCoupon(): Observable<BaseResponse<ArrayList<RedPacketBean>>> {
return RxUtils.mapObservable( return RxUtils.mapObservable(
RedPacketParam( RedPacketParam(
"" ""
...@@ -116,17 +117,17 @@ class YdlCommonHttpImpl private constructor() : YdlCommonHttp { ...@@ -116,17 +117,17 @@ class YdlCommonHttpImpl private constructor() : YdlCommonHttp {
.flatMap { getYdlCommonApi().getCoupon(it) } .flatMap { getYdlCommonApi().getCoupon(it) }
} }
override fun addOrder(param: AddOrderParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<TestAddOrderBean>> { override fun addOrder(param: AddOrderParam): Observable<BaseResponse<TestAddOrderBean>> {
return RxUtils.mapObservable((param)) return RxUtils.mapObservable((param))
.flatMap { getYdlCommonApi().testAddOrder(it) } .flatMap { getYdlCommonApi().testAddOrder(it) }
} }
override fun getRedList(param: RedListParam): Observable<com.yidianling.ydlcommon.custom.http.BaseResponse<Any>> { override fun getRedList(param: RedListParam): Observable<BaseResponse<Any>> {
return RxUtils.mapObservable((param)) return RxUtils.mapObservable((param))
.flatMap { getYdlCommonApi().getRedList(it) } .flatMap { getYdlCommonApi().getRedList(it) }
} }
private object Holder { private object Holder {
internal val INSTANCE = YdlCommonHttpImpl() internal val INSTANCE = PlatformHttpImpl()
} }
} }
\ No newline at end of file
...@@ -9,14 +9,14 @@ import com.yidianling.ydlcommon.core.base.BaseApplication ...@@ -9,14 +9,14 @@ import com.yidianling.ydlcommon.core.base.BaseApplication
* e-mail : zhangwch@yidianling.com * e-mail : zhangwch@yidianling.com
* time : 2018/04/27 * time : 2018/04/27
*/ */
internal class YdlLocalImpl private constructor(): YdlLocal { internal class PlatformLocalImpl private constructor(): IPlatformLocal {
companion object { companion object {
private val YDL_COMMON = "ydl_common" private val YDL_COMMON = "ydl_common"
private val VOICE = "voice" private val VOICE = "voice"
private val SHAKE = "shake" private val SHAKE = "shake"
fun getInstance(): YdlLocalImpl { fun getInstance(): PlatformLocalImpl {
return Holder.INSTANCE return Holder.INSTANCE
} }
} }
...@@ -42,6 +42,6 @@ internal class YdlLocalImpl private constructor(): YdlLocal { ...@@ -42,6 +42,6 @@ internal class YdlLocalImpl private constructor(): YdlLocal {
} }
private object Holder { private object Holder {
val INSTANCE = YdlLocalImpl() val INSTANCE = PlatformLocalImpl()
} }
} }
\ No newline at end of file
...@@ -9,7 +9,7 @@ import com.yidianling.ydlcommon.custom.router.YdlCommonOut ...@@ -9,7 +9,7 @@ import com.yidianling.ydlcommon.custom.router.YdlCommonOut
* e-mail : zhangwch@yidianling.com * e-mail : zhangwch@yidianling.com
* time : 2018/05/03 * time : 2018/05/03
*/ */
class YdlRamImpl private constructor(): YdlRam { class PlatformRamImpl private constructor(): IPlatformRam {
private var globalInfo: GlobalInfo? = null private var globalInfo: GlobalInfo? = null
private val sessionNewYearKeywordMap: MutableMap<String, GlobalInfo.GlobalData.NewYearKeyword?> by lazy { private val sessionNewYearKeywordMap: MutableMap<String, GlobalInfo.GlobalData.NewYearKeyword?> by lazy {
...@@ -17,7 +17,7 @@ class YdlRamImpl private constructor(): YdlRam { ...@@ -17,7 +17,7 @@ class YdlRamImpl private constructor(): YdlRam {
} }
companion object { companion object {
fun getInstance(): YdlRamImpl { fun getInstance(): PlatformRamImpl {
return Holder.INSTANCE return Holder.INSTANCE
} }
} }
...@@ -67,6 +67,6 @@ class YdlRamImpl private constructor(): YdlRam { ...@@ -67,6 +67,6 @@ class YdlRamImpl private constructor(): YdlRam {
} }
private object Holder { private object Holder {
val INSTANCE = YdlRamImpl() val INSTANCE = PlatformRamImpl()
} }
} }
\ No newline at end of file
package com.yidianling.ydlcommon.custom.data
import com.yidianling.ydlcommon.custom.base.BaseDataManager
import com.yidianling.ydlcommon.custom.http.YdlCommonHttp
import com.yidianling.ydlcommon.custom.http.YdlCommonHttpImpl
object YdlDataManager:
BaseDataManager<YdlRam, YdlLocal, YdlCommonHttp> {
override fun getRam(): YdlRam {
return YdlRamImpl.getInstance()
}
override fun getLocal(): YdlLocal {
return YdlLocalImpl.getInstance()
}
override fun getHttp(): YdlCommonHttp {
return YdlCommonHttpImpl.getInstance()
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.dialog
import android.app.DialogFragment
import android.os.Bundle
import android.view.*
import android.view.ViewGroup
/**
* @author yuanWai
* @描述:底部弹出弹窗
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/2/20
*/
abstract class BottomDialog : DialogFragment{
constructor() : super(){}
// override fun onActivityCreated(savedInstanceState: Bundle?) {
// super.onActivityCreated(savedInstanceState)
// dialog.window.attributes.windowAnimations = R.style.BottomDialogAnimation
// }
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
// setStyle(DialogFragment.STYLE_NORMAL, R.style.BottomDialog)
// }
override fun onStart() {
super.onStart()
//设置 dialog 的宽高
dialog.window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
//设置 dialog 的背景为 null
dialog.window.setBackgroundDrawable(null)
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View {
//去除标题栏
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
val window = dialog.window
val lp = window.attributes
lp.gravity = Gravity.BOTTOM //底部
lp.width = WindowManager.LayoutParams.MATCH_PARENT
// lp.windowAnimations = R.style.BottomDialogAnimation
window.attributes = lp
return createView(inflater, container)
}
//重写此方法,设置布局文件
protected abstract fun createView(inflater: LayoutInflater?, container: ViewGroup?): View
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.dialog;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.yidianling.ydlcommon.R;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import java.util.concurrent.TimeUnit;
/**
* 通用dialog
* a,支持单张图片显示
* b,支持单双按钮显示
* c,支持title
* d,支持message
* Created by yuawai on 2016/12/9.
*/
public class ChatTipsDialog extends Dialog {
//是否可以点击对话框外部
private Context context; //上下文对象
private Disposable dissMissTimer;
public static ChatTipsDialog create(Context context){
return new ChatTipsDialog(context);
}
public ChatTipsDialog(Context context) {
super(context, R.style.chatdialog_style);
this.context = context;
View v = LayoutInflater.from(context).inflate(R.layout.dialog_chat_tips,null);
getWindow().setGravity(Gravity.TOP);
setContentView(v,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
init();
// setCanceledOnTouchOutside(false);
}
public ChatTipsDialog(Context context, int theme) {
super(context, R.style.normaldialog_style);
this.context = context;
}
private void init(){
dissMissTimer = Observable.timer(5, TimeUnit.SECONDS).subscribe(aLong -> dissmissDialog());
}
private void dissmissDialog(){
if (null != dissMissTimer){
dissMissTimer.dispose();
}
dismiss();
}
@Override
public void show() {
if (null == context){
return;
}
if (context instanceof Activity){
if (((Activity)context).isFinishing()){
return;
}
}
super.show();
}
}
package com.yidianling.ydlcommon.custom.dialog
import android.app.Activity
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.view.Gravity
import android.view.Window
import android.view.WindowManager
import android.widget.EditText
import android.widget.TextView
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.emoji.EmojiFilterUtil
import com.yidianling.ydlcommon.custom.utils.InputMethonUtils
/**
* 通用文本输入框 dialog 如评论
* Created by harvie on 2017/6/30 0030.
*/
class InputTextDialog : Dialog{
private var text_cancel : TextView? =null
private var text_sure : TextView? =null
private var edit_content : EditText? = null
private var call : CallBack? =null
private var hintText = ""
private var activity : Activity? =null
constructor(context: Activity?) : super(context, R.style.commonDialog){
this.activity = context
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.dialog_input_text)
initView()
window.attributes.width = RxDeviceTool.getScreenWidth(context)
window.setGravity(Gravity.BOTTOM)
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
}
fun initView(){
text_cancel = findViewById<TextView>(R.id.text_cancel)
text_sure = findViewById<TextView>(R.id.text_sure)
edit_content = findViewById<EditText>(R.id.edit_content)
edit_content?.hint = hintText
EmojiFilterUtil.filterEmoji(context,edit_content)
text_cancel?.setOnClickListener {
call?.cancel(this)
}
text_sure?.setOnClickListener {
call?.commit(this,edit_content?.text.toString())
}
}
//设置回调监听
fun setCallBackListener(call : CallBack) : InputTextDialog {
this.call = call
return this
}
//设置hint文字
fun setHintText(hint : String): InputTextDialog {
this.hintText = hint
edit_content?.hint = hint
return this
}
override fun setOnShowListener(listener: DialogInterface.OnShowListener?) {
super.setOnShowListener(listener)
//默认弹出输入法
InputMethonUtils.showSoftInputFromWindow(context,edit_content)
}
interface CallBack{
fun cancel(dia : Dialog)
fun commit(dia : Dialog,content : String)
}
override fun show() {
if (null == activity){
return
}
if (activity!!.isFinishing){
return
}
super.show()
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.dialog.share
import android.content.Context
import android.view.View
import android.widget.LinearLayout
import com.yidianling.ydlcommon.R
/**
* @author yuanWai
* @描述:分享样式
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/2/21
*/
class YDLShareItemView : LinearLayout{
constructor(context: Context) : super(context){
initView()
}
private fun initView() {
View.inflate(context, R.layout.share_item_view,this)
}
fun initData(){
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.event
/**
* 账号被剔出事件
* Created by hgw on 2018/3/20.
*/
class AccountChangeEvent{
var code : Int = 0 //1表示账号被踢出,2表示需要重新登录
constructor(code: Int) {
this.code = code
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 16/1/12.
*/
public class AlipayResultEvent {
public int errCode;//“9000”则代表支付成功 “8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认
public AlipayResultEvent(int errCode) {
this.errCode = errCode;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* app运行状态发生改变 前后台切换
* Created by hgw on 2017/6/25.
*/
public class AppRunningStatusChange {
//是否在后台运行
public boolean isRuningBackground;
public AppRunningStatusChange(boolean isRuningBackground){
this.isRuningBackground = isRuningBackground;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* 黑名单更新通知
* Created by xiongyu on 2017/3/7.
*/
public class BlackEvent {
private boolean change;
public BlackEvent(boolean change) {
this.change = change;
}
public boolean isChange() {
return change;
}
public void setChange(boolean change) {
this.change = change;
}
}
package com.yidianling.ydlcommon.custom.event
/**
* 埋点事件统计
* Created by hgw on 2017/6/24.
*/
class BuryPointEventManager{
companion object{
//指纹开关事件
fun FingerprintClick(isOpen : Boolean){
}
/**
* 手势开关事件
*/
fun GestureClick(isOpen: Boolean){
}
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.event;
/**
* Created by Emma on 2016/8/22.
*/
public class CanMessageScrollEvent {
private boolean canScoll;
public boolean isCanScoll() {
return canScoll;
}
public void setCanScoll(boolean canScoll) {
this.canScoll = canScoll;
}
public CanMessageScrollEvent(boolean canScoll) {
this.canScoll = canScoll;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by Emma on 2016/8/26.
*/
public class CanMyWorryScollEvent {
private boolean canScoll;
public boolean isCanScoll() {
return canScoll;
}
public void setCanScoll(boolean canScoll) {
this.canScoll = canScoll;
}
public CanMyWorryScollEvent(boolean canScoll) {
this.canScoll = canScoll;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by jinkai on 16/7/11.
*/
public class DeleteReplyEvent {
public int position;
public DeleteReplyEvent(int position) {
this.position = position;
}
}
package com.yidianling.ydlcommon.custom.event;
import com.yidianling.ydlcommon.custom.event.bean.Worry;
/**
* Created by softrice on 16/1/8.
*/
public class DeleteWorryEvent {
public Worry worry;
public DeleteWorryEvent(Worry worry) {
this.worry = worry;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* 取消loading
* Created by harvie on 2017/6/5 0005.
*/
public class DismissLoadingEvent {
//code==1表示话题详情页,热门数据加载完毕时
private int code = 0;
public DismissLoadingEvent(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* 关闭activity
* Created by hgw on 2017/6/25.
*/
public class FinishActivityEvent {
public String activityName;
public FinishActivityEvent(String activityName){
this.activityName = activityName;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by jinkai on 16/5/19.
*/
public class IntentFisrstEvent {
}
package com.yidianling.ydlcommon.custom.event;
/**
* 收到消息后更新fragment对应的最新条目
*/
public class MsgContentUpDateEvent {
public String uid;
public String content;
// public EMMessage message;
public MsgContentUpDateEvent(String uid, String content/*,EMMessage message*/) {
this.uid = uid;
this.content = content;
// this.message=message;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by Emma on 2016/8/3.
*/
public class NotifyRecentListChangeEvent {
public int code;
public NotifyRecentListChangeEvent() {
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 16/1/8.
*/
public class PublishWorrryEvent {
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by jinkai on 16/7/15.
*/
public class RefreshRecentContactListEvent {
public boolean isFresh=false;
public RefreshRecentContactListEvent() {
}
public RefreshRecentContactListEvent(boolean isFresh) {
this.isFresh = isFresh;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by jinkai on 16/6/30.
*/
public class SelectTabCallPhoneEvent {
public int tab;
public SelectTabCallPhoneEvent(int tab) {
this.tab = tab;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 15/12/8.
*/
public class SelectTagEvent {
public int selectNum;
public SelectTagEvent(int selecNum) {
this.selectNum = selecNum;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by Emma on 2016/8/18.
*/
public class SetMsgHintEvent {
public boolean isShow;
public SetMsgHintEvent(boolean isShow) {
this.isShow = isShow;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 15/12/29.
*/
public class ShowDoctor {
int show;
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 15/12/29.
*/
public class ShowIntroduce {
public ShowIntroduce(int id) {
this.id = id;
}
int show;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
int id;
}
package com.yidianling.ydlcommon.custom.event
/**
* 群聊被踢出事件
* Created by hgw on 2018/3/20.
*/
class TeamRemoveEvent{
var code = 0 //1表示被踢出
var teamId : String? = null //群聊id
constructor(code: Int,teamId : String) {
this.code = code
this.teamId = teamId
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 16/1/5.
*/
public class ThankReplyUpdateEvent {
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 16/1/8.
*/
public class UpdateBindStatusEvent {
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 15/12/30.
*/
public class UpdateListenTimes {
int update;
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 16/1/7.
*/
public class UpdateTabUnreadNumEvent {
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 16/1/8.
*/
public class UpdateWorryContentEvent {
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 16/1/7.
*/
public class UpdateWorryReplyEvent {
}
package com.yidianling.ydlcommon.custom.event;
/**
* 用户头像
* Created by xiongyu on 2017/3/7.
*/
public class UserChangeEvent {
private boolean change_flag;
public UserChangeEvent(boolean change_flag) {
this.change_flag = change_flag;
}
public boolean isChange_flag() {
return change_flag;
}
public void setChange_flag(boolean change_flag) {
this.change_flag = change_flag;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 15/12/3.
*/
public class UserInfoChangeEvent {
public String head;
public String nick_name;
public int gender;
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 15/12/8.
*/
public class WXPayResultEvent {
public int errCode;
public WXPayResultEvent(int errCode) {
this.errCode = errCode;
}
}
package com.yidianling.ydlcommon.custom.event;
/**
* Created by softrice on 15/12/8.
*/
public class WarmChangeEvent {
public boolean isWarm;
public int warmNum;
public WarmChangeEvent(boolean isWarm, int warmNum) {
this.isWarm = isWarm;
this.warmNum = warmNum;
}
}
package com.yidianling.ydlcommon.custom.event.bean;
/*
id: 当前心事ID
uid: 当前心事的发表人的用户id
head: 当前心事的发表人的头像
name: 当前心事的发表人的名字
content: 当前心事的内容
count: 当前心事被回答的次数
time: 当前心事发表的时间
hits: 点击量(阅读数)
favTotalNum:当前心事总的温暖数
isFav:登陆者是否对当前心事送过温暖
*/
public class Worry {
public boolean is_top;
public String title;
public String id;
public int uid;
public String head;
public String name;
public int gender;
public String content;
public int count;
public String time;
public int hits;
public int favTotalNum;
public boolean isFav;
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.fm;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.ydlcommon.custom.course.CoursePlayer;
import com.yidianling.ydlcommon.custom.event.UpdatePlayStatusEvent;
import com.yidianling.ydlcommon.custom.notification.MusicPlayerService;
import de.greenrobot.event.EventBus;
import io.reactivex.Observable;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
/**
* FM播放管理
* Created by softrice on 2015/4/28.
*/
public class MyPlayer {
private String url;
private Context context;
public MediaPlayer m_player;
private static MyPlayer instance;
private String title;
private String cover;
private Boolean isBusy = false;// 互斥访问
private StateChangeListener listener;
private static int fmId;
public int time;
public int allTime;
Timer mTimer;
private boolean isPlayWhenLoss;
private boolean showNotification;
public int getFmId() {
return fmId;
}
public void setFmId(int fmId) {
this.fmId = fmId;
}
public void setListener(StateChangeListener listener) {
this.listener = listener;
}
boolean canNext = true;
//判断play是否启动
public static boolean isStart() {
return instance != null;
}
static public MyPlayer getInstance() {
if (instance == null) {
instance = new MyPlayer(BaseApplication.Companion.getApp());
}
return instance;
}
private MyPlayer(Context context) {
this.context = context;
m_player = new MediaPlayer();
initPlayer();
}
public MediaPlayer getMediaPlayer() {
return m_player;
}
private void initPlayer() {
m_player.setAudioStreamType(AudioManager.STREAM_MUSIC);
m_player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
LogUtil.d("Error on Listener, what: " + what + "extra: " + extra);
return false;
}
});
mTimer = new Timer(true);
mTimer.schedule(new TimerTask() {
@Override
public void run() {
if (m_player != null) {
try {
if (m_player.isPlaying()) {
if (listener != null) {
time = m_player.getCurrentPosition();
allTime = m_player.getDuration();
listener.update(m_player.getCurrentPosition(), m_player.getDuration());
}
}
} catch (IllegalStateException e) {
LogUtil.d("播放器状态非法");
}
}
}
}, 0, 100);
m_player.setOnBufferingUpdateListener((mp, percent) -> {
// if (listener != null)
// listener.update(mp.getCurrentPosition(), mp.getDuration());
// LogUtil.d(percent + "");
});
m_player.setOnCompletionListener(mp -> {
LogUtil.i("MediaPlayer Listener Completed");
if (listener != null)
listener.completion();
});
m_player.setOnPreparedListener(mp -> {
LogUtil.i("MediaPlayer Prepared Listener");
if (listener != null)
listener.prepared();
Observable.timer(300, TimeUnit.MILLISECONDS)
.subscribe(aLong -> {
if (showNotification) {
updateNotification();
}
});
});
}
public void rePlay() {
if (isBusy)
return;
if (m_player != null) {
m_player.start();
} else {
LogUtil.i("m_player is null");
}
updateNotification();
}
/*
* 播放新的音乐
*/
public void play(final String url, boolean showNotification) {
this.showNotification = showNotification;
this.url = url;
//RouterManager.INSTANCE.getCourseRouter().closePlayer();
// 修改调用方式 by 豪瑞 2019/2/18
if (CoursePlayer.INSTANCE.isPlaying()) {
CoursePlayer.INSTANCE.onDestroy(BaseApplication.Companion.getApp());
}
if (isBusy)
return;
if (m_player != null) {
m_player.reset();
if (listener != null) {
listener.cancel();
}
}
isBusy = true;
if (url == null)
return;
Runnable r = () -> {
try {
m_player.setDataSource(context, Uri.parse(url));
m_player.prepare();
LogUtil.i("Duration: " + m_player.getDuration());
m_player.start();
isBusy = false;
} catch (Exception e) {
LogUtil.i(e.getMessage());
}
};
AudioManager audioManager = (AudioManager) BaseApplication.Companion.getApp().getSystemService(Context.AUDIO_SERVICE);
if (audioManager != null) {
audioManager.requestAudioFocus(focusChange -> {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (!isPlaying() && isPlayWhenLoss) {
pause(showNotification);
if (showNotification) {
EventBus.getDefault().post(new UpdatePlayStatusEvent());
}
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
isPlayWhenLoss = isPlaying();
if (isPlaying()) {
pause(showNotification);
if (showNotification) {
EventBus.getDefault().post(new UpdatePlayStatusEvent());
}
}
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
isPlayWhenLoss = isPlaying();
if (isPlaying()) {
pause(showNotification);
if (showNotification) {
EventBus.getDefault().post(new UpdatePlayStatusEvent());
}
}
break;
default:
break;
}
}, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
}
new Thread(r).start();
if (showNotification) {
updateNotification();
}
}
private void updateNotification() {
Intent intent = new Intent(BaseApplication.Companion.getApp(), MusicPlayerService.class);
intent.putExtra("play_type", "fm");
BaseApplication.Companion.getApp().startService(intent);
}
/*
* 播放和暂停
*/
public void pause(boolean updateNotification) {
if (isBusy)
return;
if (m_player.isPlaying()) {// 正在播放
m_player.pause();// 暂停
} else {// 没有播放
m_player.start();
}
if (updateNotification) {
updateNotification();
}
}
/**
* 释放资源
*
* @return
*/
public void releaseMedia() {
if (m_player != null) {
m_player.reset();
m_player.release();
m_player = null;
instance = null;
}
}
public Boolean isPlaying() {
if (showNotification) {
try {
return m_player.isPlaying();
} catch (Exception e) {
e.printStackTrace();
return false;
}
} else {
return false;
}
}
public void seekTo(int position) {
m_player.seekTo(position);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCover() {
return cover;
}
public void setCover(String cover) {
this.cover = cover;
}
public interface StateChangeListener {
void update(int time, int allTime);
void completion();
void prepared();
void cancel();
}
}
package com.yidianling.ydlcommon.custom.h5 package com.yidianling.ydlcommon.custom.h5
import com.yidianling.ydlcommon.custom.data.ShareData import com.yidianling.ydlcommon.custom.bean.ShareData
/** /**
......
package com.yidianling.ydlcommon.custom.h5 package com.yidianling.ydlcommon.custom.h5
import com.yidianling.ydlcommon.custom.data.ShareData import com.yidianling.ydlcommon.custom.bean.ShareData
import java.io.Serializable import java.io.Serializable
/** /**
......
...@@ -2,10 +2,9 @@ package com.yidianling.ydlcommon.custom.h5 ...@@ -2,10 +2,9 @@ package com.yidianling.ydlcommon.custom.h5
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import com.google.gson.Gson import com.google.gson.Gson
import com.ydl.js_module.manager.WebViewRouterManager
import com.ydl.ydl_router.manager.YDLRouterManager import com.ydl.ydl_router.manager.YDLRouterManager
import com.yidianling.common.tools.LogUtil import com.yidianling.common.tools.LogUtil
import com.yidianling.ydlcommon.custom.log.LogHelper import com.yidianling.ydlcommon.custom.utils.log.LogHelper
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager
/** /**
...@@ -25,13 +24,6 @@ class JavascriptHandler { ...@@ -25,13 +24,6 @@ class JavascriptHandler {
LogUtil.i("js", params) LogUtil.i("js", params)
LogUtil.d("sendDataToOC") LogUtil.d("sendDataToOC")
//js交互路由 后期会去除掉这个路由 统一使用下面的路由
//该路由只有测试记录h5页面在使用 - 测试题支付/测试题详情/测试题结果
val webViewRouter = WebViewRouterManager()
if (webViewRouter.toNative(params)) {
//
return
}
//壹点灵路由 //壹点灵路由
if (YDLRouterManager.router(params)) { if (YDLRouterManager.router(params)) {
return return
......
...@@ -9,7 +9,6 @@ import android.content.Context; ...@@ -9,7 +9,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
...@@ -31,23 +30,22 @@ import com.yidianling.common.tools.LogUtil; ...@@ -31,23 +30,22 @@ import com.yidianling.common.tools.LogUtil;
import com.yidianling.common.tools.ToastUtil; import com.yidianling.common.tools.ToastUtil;
import com.yidianling.ydlcommon.BuildConfig; import com.yidianling.ydlcommon.BuildConfig;
import com.yidianling.ydlcommon.R; import com.yidianling.ydlcommon.R;
import com.yidianling.ydlcommon.core.base.BaseActivity;
import com.yidianling.ydlcommon.core.utils.StatusBarUtils;
import com.yidianling.ydlcommon.custom.TemporaryUtils; import com.yidianling.ydlcommon.custom.TemporaryUtils;
import com.yidianling.ydlcommon.custom.YdlBuryPointUtil; import com.yidianling.ydlcommon.custom.YdlBuryPointUtil;
import com.yidianling.ydlcommon.custom.base.BaseActivity;
import com.yidianling.ydlcommon.custom.dialog.YDLShareDialog;
import com.yidianling.ydlcommon.custom.event.LoginStateEvent; import com.yidianling.ydlcommon.custom.event.LoginStateEvent;
import com.yidianling.ydlcommon.custom.event.RefreshEvent; import com.yidianling.ydlcommon.custom.event.RefreshEvent;
import com.yidianling.ydlcommon.custom.http.UploadWebViewTimeUtils;
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager; import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager;
import com.yidianling.ydlcommon.custom.tool.BuryPointUtils;
import com.yidianling.ydlcommon.custom.tool.PopUtils;
import com.yidianling.ydlcommon.custom.tool.StatusBarUtils;
import com.yidianling.ydlcommon.custom.ui.LogoLoadingView; import com.yidianling.ydlcommon.custom.ui.LogoLoadingView;
import com.yidianling.ydlcommon.custom.utils.BuryPointUtils;
import com.yidianling.ydlcommon.custom.utils.NetWorkSpeedUtils; import com.yidianling.ydlcommon.custom.utils.NetWorkSpeedUtils;
import com.yidianling.ydlcommon.custom.utils.PopUtils;
import com.yidianling.ydlcommon.custom.utils.URLUtils; import com.yidianling.ydlcommon.custom.utils.URLUtils;
import com.yidianling.ydlcommon.custom.view.ProgressWebView; import com.yidianling.ydlcommon.custom.view.ProgressWebView;
import com.yidianling.ydlcommon.custom.view.SafeTipView; import com.yidianling.ydlcommon.custom.view.SafeTipView;
import com.yidianling.ydlcommon.custom.view.TitleBar; import com.yidianling.ydlcommon.custom.view.TitleBar;
import com.yidianling.ydlcommon.custom.view.dialog.YDLShareDialog;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
import in.srain.cube.views.ptr.PtrDefaultHandler; import in.srain.cube.views.ptr.PtrDefaultHandler;
import in.srain.cube.views.ptr.PtrFrameLayout; import in.srain.cube.views.ptr.PtrFrameLayout;
...@@ -204,6 +202,8 @@ public class NewH5Activity extends BaseActivity implements PtrHandler { ...@@ -204,6 +202,8 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
initStartTime = System.currentTimeMillis(); initStartTime = System.currentTimeMillis();
//设置h5页面默认statusbar的颜色
initStatusViewOptions(true,true,"#1da1f2");
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.activity_anim_in, overridePendingTransition(R.anim.activity_anim_in,
R.anim.activity_anim_out); R.anim.activity_anim_out);
...@@ -278,25 +278,9 @@ public class NewH5Activity extends BaseActivity implements PtrHandler { ...@@ -278,25 +278,9 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
} }
} }
@Override
public boolean isAddStatusView() {
return true;
}
@Override
public boolean statusBarDarkMode() {
return true;
}
@Override @Override
protected void initDataAndEvent() { protected void initDataAndEvent() {
//设置h5页面默认statusbar的颜色
if (null != getStatusView()) {
getStatusView().setBackgroundColor(Color.parseColor("#1da1f2"));
}
getParam(); getParam();
TellData tellData = (TellData) getIntent().getSerializableExtra("tell_data"); TellData tellData = (TellData) getIntent().getSerializableExtra("tell_data");
if (tellData == null) { if (tellData == null) {
...@@ -397,8 +381,8 @@ public class NewH5Activity extends BaseActivity implements PtrHandler { ...@@ -397,8 +381,8 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
} }
if (!useUrl.contains("barHeight")) { if (!useUrl.contains("barHeight")) {
String paramsStr = useUrl.contains("?") String paramsStr = useUrl.contains("?")
? "&barHeight=" + String.valueOf(StatusBarUtils.INSTANCE.getStatusBarHeight(NewH5Activity.this)) ? "&barHeight=" + String.valueOf(StatusBarUtils.Companion.getStatusBarHeight(NewH5Activity.this))
: "?barHeight=" + String.valueOf(StatusBarUtils.INSTANCE.getStatusBarHeight(NewH5Activity.this)); : "?barHeight=" + String.valueOf(StatusBarUtils.Companion.getStatusBarHeight(NewH5Activity.this));
useUrl = new StringBuffer().append(useUrl).append(paramsStr).toString(); useUrl = new StringBuffer().append(useUrl).append(paramsStr).toString();
} }
hideJavaTitleBar(); hideJavaTitleBar();
...@@ -619,7 +603,7 @@ public class NewH5Activity extends BaseActivity implements PtrHandler { ...@@ -619,7 +603,7 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
hasLoad = true; hasLoad = true;
loadDuration = System.currentTimeMillis() - loadStartTime; loadDuration = System.currentTimeMillis() - loadStartTime;
LogUtil.e("initDuration:" + initDuration + ",loadDuration:" + loadDuration); LogUtil.e("initDuration:" + initDuration + ",loadDuration:" + loadDuration);
UploadWebViewTimeUtils.Companion.uploadWebViewTime(h5Params.getUrl(), initDuration + "", loadDuration + "", workSpeedUtils.getNetSpeed()); // UploadWebViewTimeUtils.Companion.uploadWebViewTime(h5Params.getUrl(), initDuration + "", loadDuration + "", workSpeedUtils.getNetSpeed());
} }
if (shouldClearHistory) { if (shouldClearHistory) {
...@@ -688,7 +672,7 @@ public class NewH5Activity extends BaseActivity implements PtrHandler { ...@@ -688,7 +672,7 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
hasLoad = true; hasLoad = true;
loadDuration = System.currentTimeMillis() - loadStartTime; loadDuration = System.currentTimeMillis() - loadStartTime;
LogUtil.e("initDuration:" + initDuration + ",loadDuration:" + loadDuration); LogUtil.e("initDuration:" + initDuration + ",loadDuration:" + loadDuration);
UploadWebViewTimeUtils.Companion.uploadWebViewTime(h5Params.getUrl(), initDuration + "", loadDuration + "", workSpeedUtils.getNetSpeed()); // UploadWebViewTimeUtils.Companion.uploadWebViewTime(h5Params.getUrl(), initDuration + "", loadDuration + "", workSpeedUtils.getNetSpeed());
} }
if (shouldClearHistory) { if (shouldClearHistory) {
......
package com.yidianling.ydlcommon.custom.h5 package com.yidianling.ydlcommon.custom.h5
import com.yidianling.ydlcommon.custom.data.ShareData import com.yidianling.ydlcommon.custom.bean.ShareData
import java.io.Serializable import java.io.Serializable
/** /**
......
package com.ydl.js_module.listener
/**
* @author yuanWai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/12/5
*/
interface IJSInterface{
/**
* 跳转测试详情页
*/
fun test_detail(params : String?)
/**
* 跳转测试结果页
*/
fun test_result(params: String?)
/**
* 跳转支付页面
*/
fun test_pay(params: String?)
/**
* 跳转测试列表页
*/
fun test_list(params: String?)
}
\ No newline at end of file
package com.ydl.js_module.listener
import android.net.Uri
import android.text.TextUtils
import android.util.Log
import com.alibaba.android.arouter.launcher.ARouter
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydl_router.manager.YDLRouterParams
import com.yidianling.ydlcommon.BuildConfig
import com.yidianling.ydlcommon.custom.router.IYDLRouterConstant
/**
* @author yuanWai
* @描述:h5与本地交互(参数都为params的目的是,方便反射调用,只所以这么设计是因为方便,加方法直接改这个类就好)
* 方法名为<host_path> 例如:test/detail 方法名为:test_detail 参数统一为 params
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/12/5
*/
class JSInterfaceImpl : IJSInterface{
private val TAG = JSInterfaceImpl::class.java.name
override fun test_detail(params: String?) {
if (TextUtils.isEmpty(params)){
return
}
val uri = Uri.parse(params)
val test_items_id = uri.getQueryParameter("test_items_id")
if (TextUtils.isEmpty(test_items_id)){
return
}
Log.e("test_detail", "--------params=$params")
YDLRouterManager.router(
IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_URL, BuildConfig.MH5_URL+"ceshi/"+test_items_id),"")
}
override fun test_result(params: String?) {
if (TextUtils.isEmpty(params)){
return
}
val uri = Uri.parse(params)
val test_items_id = uri.getQueryParameter("test_items_id")
if (TextUtils.isEmpty(test_items_id)){
return
}
YDLRouterManager.router(
IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_URL, BuildConfig.MH5_URL+"ceshi/result/"+test_items_id),"")
}
override fun test_pay(params: String?) {
if (TextUtils.isEmpty(params)){
return
}
val uri = Uri.parse(params)
val weiMoney = uri.getQueryParameter("weiMoney")
val redPackArray = uri.getQueryParameter("redPackArray")
val payId = uri.getQueryParameter("payId")
val test_items_id = uri.getQueryParameter("test_items_id")
val orderId = uri.getQueryParameter("orderId")
if (TextUtils.isEmpty(weiMoney) || TextUtils.isEmpty(payId) || TextUtils.isEmpty(test_items_id)){
return
}
val url = StringBuffer(BuildConfig.MH5_URL)
url.append("ceshi/")
url.append(test_items_id)
url.append("?payId=")
url.append(payId)
url.append("&couponMoney=")
url.append(redPackArray)
url.append("&orderId=")
url.append(orderId)
YDLRouterManager.router(
IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_URL, Uri.encode(url.toString())),"")
}
override fun test_list(params: String?) {
if (!TextUtils.isEmpty(params)){
val uri = Uri.parse(params)
val tab = uri.getQueryParameter("tab")
if (TextUtils.isEmpty(tab)){
ARouter.getInstance().build("/ceshi/category_list").navigation()
return
}
ARouter.getInstance().build("/ceshi/category_list").withString("tab",tab).navigation()
}else{
ARouter.getInstance().build("/ceshi/category_list").navigation()
}
}
}
\ No newline at end of file
package com.ydl.js_module.manager
import com.ydl.js_module.listener.JSInterfaceImpl
import com.ydl.js_module.util.RouterParamsUrls
/**
* @author yuanWai
* @描述:路由反射调用
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/12/5
*/
class RouterAnalysis private constructor() {
/**
* 单例
*/
companion object {
val instance: RouterAnalysis by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
RouterAnalysis() }
}
private var mIJSInterface : JSInterfaceImpl? = null
fun routerInvoke(paramsUrls : RouterParamsUrls){
try {
getJSInterface().javaClass.getMethod(paramsUrls.getMethod(), String::class.java)
.invoke(getJSInterface(), paramsUrls.getParams())
} catch (e: Exception) {
}
}
private fun getJSInterface() : JSInterfaceImpl{
if (null == mIJSInterface){
mIJSInterface = JSInterfaceImpl()
}
return mIJSInterface!!
}
}
\ No newline at end of file
package com.ydl.js_module.util
import android.net.Uri
import android.text.TextUtils
import android.util.Log
/**
* @author yuanWai
* @描述:路由参数解析
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/12/5
*/
class RouterParamsUrls{
constructor(url : String){
initParam(url)
}
/**
* 参数
*/
private var params : String? = null
/**
* 路由uri格式
*/
private var uri: Uri? = null
private var method : String? = null
private fun initParam(url : String){
uri = Uri.parse(url)
if (null == uri){
return
}
params = url
if (!TextUtils.isEmpty(params) && params!!.lastIndexOf("\"") == params!!.length - 1){
params = params!!.substring(0,params!!.length - 1)
}
method = uri!!.host + uri!!.path.replace("/","_")
Log.e("http", "------$method")
}
/**
* 返回解析的参数
*/
fun getParams() : String?{
return params
}
fun getMethod() : String?{
return method
}
}
\ No newline at end of file
package com.ydl.js_module.manager
import com.ydl.js_module.util.RouterParamsUrls
import com.ydl.js_module.util.WebViewRouterUtils
/**
* @author yuanWai
* @描述:webview路由入口类(todo 目前先简单写,还可以做很多事情,比如操作webview界面)
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/12/5
*/
class WebViewRouterManager{
/**
* 调用原生方法入口
*/
fun toNative(url : String) : Boolean{
if (!WebViewRouterUtils.isRouterUrl(url)){
return false
}
val routerParamsUrls = RouterParamsUrls(url)
RouterAnalysis.instance.routerInvoke(routerParamsUrls)
return true
}
}
\ No newline at end of file
package com.ydl.js_module.util
import android.text.TextUtils
/**
* @author yuanWai
* @描述:webview路由工具类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/12/5
*/
class WebViewRouterUtils{
companion object {
private var ydlRouterUrl = "ydl-user://"
private var ydlRouterUrl2 = "ydl-zixun://"
private var ydlRouterUrl3 = "ydl-test://"
//todo 方法名称 后期会去掉这个路由 替换成 ydl-router统一处理 过渡方案
private var METHOD_1 = "test/detail"
private var METHOD_2 = "test/result"
private var METHOD_3 = "test/pay"
private var METHOD_4 = "test/list"
/**
* 是否符合路由规则
*/
fun isRouterUrl(url : String) : Boolean{
if (TextUtils.isEmpty(url)){
return false
}
if (url.contains(ydlRouterUrl) && containsMethod(url)){
return true
}
if (url.contains(ydlRouterUrl2) && containsMethod(url)){
return true
}
if (url.contains(ydlRouterUrl3) && containsMethod(url)){
return true
}
return false
}
/**
* 是否包含下列方法
*/
private fun containsMethod(url : String) : Boolean{
return (url.contains(METHOD_1) || url.contains(METHOD_2) || url.contains(METHOD_3) || url.contains(METHOD_4))
}
}
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ package com.yidianling.ydlcommon.custom.http; ...@@ -2,7 +2,7 @@ package com.yidianling.ydlcommon.custom.http;
import com.yidianling.ydlcommon.core.base.BaseApplication; import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.RxDeviceTool; import com.yidianling.common.tools.RxDeviceTool;
import com.yidianling.ydlcommon.custom.data.YdlDataManager; import com.yidianling.ydlcommon.custom.data.PlatformDataManager;
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager; import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager;
import com.yidianling.ydlcommon.custom.router.YdlUserInfo; import com.yidianling.ydlcommon.custom.router.YdlUserInfo;
...@@ -23,7 +23,7 @@ public class BaseCommand { ...@@ -23,7 +23,7 @@ public class BaseCommand {
public String isFromApp = "1";//2表示专家版1表示用户版 public String isFromApp = "1";//2表示专家版1表示用户版
public String ffrom = YdlDataManager.INSTANCE.getRam().getChannelName();//渠Y道来源 public String ffrom = PlatformDataManager.INSTANCE.getRam().getChannelName();//渠Y道来源
public BaseCommand() { public BaseCommand() {
YdlUserInfo userInfo = YdlCommonRouterManager.INSTANCE.getYdlCommonRoute().getUserInfo(); YdlUserInfo userInfo = YdlCommonRouterManager.INSTANCE.getYdlCommonRoute().getUserInfo();
......
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yidianling.ydlcommon.custom.http;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A cache that uses a bounded amount of space on a filesystem. Each cache
* entry has a string key and a fixed number of values. Each key must match
* the regex <strong>[a-z0-9_-]{1,120}</strong>. Values are byte sequences,
* accessible as streams or files. Each value must be between {@code 0} and
* {@code Integer.MAX_VALUE} bytes in length.
*
* <p>The cache stores its data in a directory on the filesystem. This
* directory must be exclusive to the cache; the cache may delete or overwrite
* files from its directory. It is an error for multiple processes to use the
* same cache directory at the same time.
*
* <p>This cache limits the number of bytes that it will store on the
* filesystem. When the number of stored bytes exceeds the limit, the cache will
* remove entries in the background until the limit is satisfied. The limit is
* not strict: the cache may temporarily exceed it while waiting for files to be
* deleted. The limit does not include filesystem overhead or the cache
* journal so space-sensitive applications should set a conservative limit.
*
* <p>Clients call {@link #edit} to create or update the values of an entry. An
* entry may have only one editor at one time; if a value is not available to be
* edited then {@link #edit} will return null.
* <ul>
* <li>When an entry is being <strong>created</strong> it is necessary to
* supply a full set of values; the empty value should be used as a
* placeholder if necessary.
* <li>When an entry is being <strong>edited</strong>, it is not necessary
* to supply data for every value; values default to their previous
* value.
* </ul>
* Every {@link #edit} call must be matched by a call to {@link Editor#commit}
* or {@link Editor#abort}. Committing is atomic: a read observes the full set
* of values as they were before or after the commit, but never a mix of values.
*
* <p>Clients call {@link #get} to read a snapshot of an entry. The read will
* observe the value at the time that {@link #get} was called. Updates and
* removals after the call do not impact ongoing reads.
*
* <p>This class is tolerant of some I/O errors. If files are missing from the
* filesystem, the corresponding entries will be dropped from the cache. If
* an error occurs while writing a cache value, the edit will fail silently.
* Callers should handle other problems by catching {@code IOException} and
* responding appropriately.
*/
public final class DiskLruCache implements Closeable {
static final String JOURNAL_FILE = "journal";
static final String JOURNAL_FILE_TEMP = "journal.tmp";
static final String JOURNAL_FILE_BACKUP = "journal.bkp";
static final String MAGIC = "libcore.io.DiskLruCache";
static final String VERSION_1 = "1";
static final long ANY_SEQUENCE_NUMBER = -1;
static final String STRING_KEY_PATTERN = "[a-z0-9_-]{1,120}";
static final Pattern LEGAL_KEY_PATTERN = Pattern.compile(STRING_KEY_PATTERN);
private static final String CLEAN = "CLEAN";
private static final String DIRTY = "DIRTY";
private static final String REMOVE = "REMOVE";
private static final String READ = "READ";
/*
* This cache uses a journal file named "journal". A typical journal file
* looks like this:
* libcore.io.DiskLruCache
* 1
* 100
* 2
*
* CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
* DIRTY 335c4c6028171cfddfbaae1a9c313c52
* CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
* REMOVE 335c4c6028171cfddfbaae1a9c313c52
* DIRTY 1ab96a171faeeee38496d8b330771a7a
* CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
* READ 335c4c6028171cfddfbaae1a9c313c52
* READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
*
* The first five lines of the journal form its header. They are the
* constant string "libcore.io.DiskLruCache", the disk cache's version,
* the application's version, the value count, and a blank line.
*
* Each of the subsequent lines in the file is a record of the state of a
* cache entry. Each line contains space-separated values: a state, a key,
* and optional state-specific values.
* o DIRTY lines track that an entry is actively being created or updated.
* Every successful DIRTY action should be followed by a CLEAN or REMOVE
* action. DIRTY lines without a matching CLEAN or REMOVE indicate that
* temporary files may need to be deleted.
* o CLEAN lines track a cache entry that has been successfully published
* and may be read. A publish line is followed by the lengths of each of
* its values.
* o READ lines track accesses for LRU.
* o REMOVE lines track entries that have been deleted.
*
* The journal file is appended to as cache operations occur. The journal may
* occasionally be compacted by dropping redundant lines. A temporary file named
* "journal.tmp" will be used during compaction; that file should be deleted if
* it exists when the cache is opened.
*/
private final File directory;
private final File journalFile;
private final File journalFileTmp;
private final File journalFileBackup;
private final int appVersion;
private long maxSize;
private final int valueCount;
private long size = 0;
private Writer journalWriter;
private final LinkedHashMap<String, Entry> lruEntries =
new LinkedHashMap<String, Entry>(0, 0.75f, true);
private int redundantOpCount;
/**
* To differentiate between old and current snapshots, each entry is given
* a sequence number each time an edit is committed. A snapshot is stale if
* its sequence number is not equal to its entry's sequence number.
*/
private long nextSequenceNumber = 0;
/** This cache uses a single background thread to evict entries. */
final ThreadPoolExecutor executorService =
new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private final Callable<Void> cleanupCallable = new Callable<Void>() {
public Void call() throws Exception {
synchronized (DiskLruCache.this) {
if (journalWriter == null) {
return null; // Closed.
}
trimToSize();
if (journalRebuildRequired()) {
rebuildJournal();
redundantOpCount = 0;
}
}
return null;
}
};
private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
this.directory = directory;
this.appVersion = appVersion;
this.journalFile = new File(directory, JOURNAL_FILE);
this.journalFileTmp = new File(directory, JOURNAL_FILE_TEMP);
this.journalFileBackup = new File(directory, JOURNAL_FILE_BACKUP);
this.valueCount = valueCount;
this.maxSize = maxSize;
}
/**
* Opens the cache in {@code directory}, creating a cache if none exists
* there.
*
* @param directory a writable directory
* @param valueCount the number of values per cache entry. Must be positive.
* @param maxSize the maximum number of bytes this cache should use to store
* @throws IOException if reading or writing the cache directory fails
*/
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
throws IOException {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
if (valueCount <= 0) {
throw new IllegalArgumentException("valueCount <= 0");
}
// If a bkp file exists, use it instead.
File backupFile = new File(directory, JOURNAL_FILE_BACKUP);
if (backupFile.exists()) {
File journalFile = new File(directory, JOURNAL_FILE);
// If journal file also exists just delete backup file.
if (journalFile.exists()) {
backupFile.delete();
} else {
renameTo(backupFile, journalFile, false);
}
}
// Prefer to pick up where we left off.
DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
if (cache.journalFile.exists()) {
try {
cache.readJournal();
cache.processJournal();
return cache;
} catch (IOException journalIsCorrupt) {
System.out
.println("DiskLruCache "
+ directory
+ " is corrupt: "
+ journalIsCorrupt.getMessage()
+ ", removing");
cache.delete();
}
}
// Create a new empty cache.
directory.mkdirs();
cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
cache.rebuildJournal();
return cache;
}
private void readJournal() throws IOException {
StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile), Util.US_ASCII);
try {
String magic = reader.readLine();
String version = reader.readLine();
String appVersionString = reader.readLine();
String valueCountString = reader.readLine();
String blank = reader.readLine();
if (!MAGIC.equals(magic)
|| !VERSION_1.equals(version)
|| !Integer.toString(appVersion).equals(appVersionString)
|| !Integer.toString(valueCount).equals(valueCountString)
|| !"".equals(blank)) {
throw new IOException("unexpected journal header: [" + magic + ", " + version + ", "
+ valueCountString + ", " + blank + "]");
}
int lineCount = 0;
while (true) {
try {
readJournalLine(reader.readLine());
lineCount++;
} catch (EOFException endOfJournal) {
break;
}
}
redundantOpCount = lineCount - lruEntries.size();
// If we ended on a truncated line, rebuild the journal before appending to it.
if (reader.hasUnterminatedLine()) {
rebuildJournal();
} else {
journalWriter = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(journalFile, true), Util.US_ASCII));
}
} finally {
Util.closeQuietly(reader);
}
}
private void readJournalLine(String line) throws IOException {
int firstSpace = line.indexOf(' ');
if (firstSpace == -1) {
throw new IOException("unexpected journal line: " + line);
}
int keyBegin = firstSpace + 1;
int secondSpace = line.indexOf(' ', keyBegin);
final String key;
if (secondSpace == -1) {
key = line.substring(keyBegin);
if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) {
lruEntries.remove(key);
return;
}
} else {
key = line.substring(keyBegin, secondSpace);
}
Entry entry = lruEntries.get(key);
if (entry == null) {
entry = new Entry(key);
lruEntries.put(key, entry);
}
if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) {
String[] parts = line.substring(secondSpace + 1).split(" ");
entry.readable = true;
entry.currentEditor = null;
entry.setLengths(parts);
} else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) {
entry.currentEditor = new Editor(entry);
} else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) {
// This work was already done by calling lruEntries.get().
} else {
throw new IOException("unexpected journal line: " + line);
}
}
/**
* Computes the initial size and collects garbage as a part of opening the
* cache. Dirty entries are assumed to be inconsistent and will be deleted.
*/
private void processJournal() throws IOException {
deleteIfExists(journalFileTmp);
for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
Entry entry = i.next();
if (entry.currentEditor == null) {
for (int t = 0; t < valueCount; t++) {
size += entry.lengths[t];
}
} else {
entry.currentEditor = null;
for (int t = 0; t < valueCount; t++) {
deleteIfExists(entry.getCleanFile(t));
deleteIfExists(entry.getDirtyFile(t));
}
i.remove();
}
}
}
/**
* Creates a new journal that omits redundant information. This replaces the
* current journal if it exists.
*/
private synchronized void rebuildJournal() throws IOException {
if (journalWriter != null) {
journalWriter.close();
}
Writer writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(journalFileTmp), Util.US_ASCII));
try {
writer.write(MAGIC);
writer.write("\n");
writer.write(VERSION_1);
writer.write("\n");
writer.write(Integer.toString(appVersion));
writer.write("\n");
writer.write(Integer.toString(valueCount));
writer.write("\n");
writer.write("\n");
for (Entry entry : lruEntries.values()) {
if (entry.currentEditor != null) {
writer.write(DIRTY + ' ' + entry.key + '\n');
} else {
writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
}
}
} finally {
if (null != writer){
writer.close();
}
}
if (journalFile.exists()) {
renameTo(journalFile, journalFileBackup, true);
}
renameTo(journalFileTmp, journalFile, false);
journalFileBackup.delete();
journalWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(journalFile, true), Util.US_ASCII));
}
private static void deleteIfExists(File file) throws IOException {
if (file.exists() && !file.delete()) {
throw new IOException();
}
}
private static void renameTo(File from, File to, boolean deleteDestination) throws IOException {
if (deleteDestination) {
deleteIfExists(to);
}
if (!from.renameTo(to)) {
throw new IOException();
}
}
/**
* Returns a snapshot of the entry named {@code key}, or null if it doesn't
* exist is not currently readable. If a value is returned, it is moved to
* the head of the LRU queue.
*/
public synchronized Snapshot get(String key) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (entry == null) {
return null;
}
if (!entry.readable) {
return null;
}
// Open all streams eagerly to guarantee that we see a single published
// snapshot. If we opened streams lazily then the streams could come
// from different edits.
InputStream[] ins = new InputStream[valueCount];
try {
for (int i = 0; i < valueCount; i++) {
ins[i] = new FileInputStream(entry.getCleanFile(i));
}
} catch (FileNotFoundException e) {
// A file must have been deleted manually!
for (int i = 0; i < valueCount; i++) {
if (ins[i] != null) {
Util.closeQuietly(ins[i]);
} else {
break;
}
}
return null;
}
redundantOpCount++;
journalWriter.append(READ + ' ' + key + '\n');
if (journalRebuildRequired()) {
executorService.submit(cleanupCallable);
}
return new Snapshot(key, entry.sequenceNumber, ins, entry.lengths);
}
/**
* Returns an editor for the entry named {@code key}, or null if another
* edit is in progress.
*/
public Editor edit(String key) throws IOException {
return edit(key, ANY_SEQUENCE_NUMBER);
}
private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER && (entry == null
|| entry.sequenceNumber != expectedSequenceNumber)) {
return null; // Snapshot is stale.
}
if (entry == null) {
entry = new Entry(key);
lruEntries.put(key, entry);
} else if (entry.currentEditor != null) {
return null; // Another edit is in progress.
}
Editor editor = new Editor(entry);
entry.currentEditor = editor;
// Flush the journal before creating files to prevent file leaks.
journalWriter.write(DIRTY + ' ' + key + '\n');
journalWriter.flush();
return editor;
}
/** Returns the directory where this cache stores its data. */
public File getDirectory() {
return directory;
}
/**
* Returns the maximum number of bytes that this cache should use to store
* its data.
*/
public synchronized long getMaxSize() {
return maxSize;
}
/**
* Changes the maximum number of bytes the cache can store and queues a job
* to trim the existing store, if necessary.
*/
public synchronized void setMaxSize(long maxSize) {
this.maxSize = maxSize;
executorService.submit(cleanupCallable);
}
/**
* Returns the number of bytes currently being used to store the values in
* this cache. This may be greater than the max size if a background
* deletion is pending.
*/
public synchronized long size() {
return size;
}
private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
Entry entry = editor.entry;
if (entry.currentEditor != editor) {
throw new IllegalStateException();
}
// If this edit is creating the entry for the first time, every index must have a value.
if (success && !entry.readable) {
for (int i = 0; i < valueCount; i++) {
if (!editor.written[i]) {
editor.abort();
throw new IllegalStateException("Newly created entry didn't create value for index " + i);
}
if (!entry.getDirtyFile(i).exists()) {
editor.abort();
return;
}
}
}
for (int i = 0; i < valueCount; i++) {
File dirty = entry.getDirtyFile(i);
if (success) {
if (dirty.exists()) {
File clean = entry.getCleanFile(i);
dirty.renameTo(clean);
long oldLength = entry.lengths[i];
long newLength = clean.length();
entry.lengths[i] = newLength;
size = size - oldLength + newLength;
}
} else {
deleteIfExists(dirty);
}
}
redundantOpCount++;
entry.currentEditor = null;
if (entry.readable | success) {
entry.readable = true;
journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
if (success) {
entry.sequenceNumber = nextSequenceNumber++;
}
} else {
lruEntries.remove(entry.key);
journalWriter.write(REMOVE + ' ' + entry.key + '\n');
}
journalWriter.flush();
if (size > maxSize || journalRebuildRequired()) {
executorService.submit(cleanupCallable);
}
}
/**
* We only rebuild the journal when it will halve the size of the journal
* and eliminate at least 2000 ops.
*/
private boolean journalRebuildRequired() {
final int redundantOpCompactThreshold = 2000;
return redundantOpCount >= redundantOpCompactThreshold //
&& redundantOpCount >= lruEntries.size();
}
/**
* Drops the entry for {@code key} if it exists and can be removed. Entries
* actively being edited cannot be removed.
*
* @return true if an entry was removed.
*/
public synchronized boolean remove(String key) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (entry == null || entry.currentEditor != null) {
return false;
}
for (int i = 0; i < valueCount; i++) {
File file = entry.getCleanFile(i);
if (file.exists() && !file.delete()) {
throw new IOException("failed to delete " + file);
}
size -= entry.lengths[i];
entry.lengths[i] = 0;
}
redundantOpCount++;
journalWriter.append(REMOVE + ' ' + key + '\n');
lruEntries.remove(key);
if (journalRebuildRequired()) {
executorService.submit(cleanupCallable);
}
return true;
}
/** Returns true if this cache has been closed. */
public synchronized boolean isClosed() {
return journalWriter == null;
}
private void checkNotClosed() {
if (journalWriter == null) {
throw new IllegalStateException("cache is closed");
}
}
/** Force buffered operations to the filesystem. */
public synchronized void flush() throws IOException {
checkNotClosed();
trimToSize();
journalWriter.flush();
}
/** Closes this cache. Stored values will remain on the filesystem. */
public synchronized void close() throws IOException {
if (journalWriter == null) {
return; // Already closed.
}
for (Entry entry : new ArrayList<Entry>(lruEntries.values())) {
if (entry.currentEditor != null) {
entry.currentEditor.abort();
}
}
trimToSize();
journalWriter.close();
journalWriter = null;
}
private void trimToSize() throws IOException {
while (size > maxSize) {
Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next();
remove(toEvict.getKey());
}
}
/**
* Closes the cache and deletes all of its stored values. This will delete
* all files in the cache directory including files that weren't created by
* the cache.
*/
public void delete() throws IOException {
close();
Util.deleteContents(directory);
}
private void validateKey(String key) {
Matcher matcher = LEGAL_KEY_PATTERN.matcher(key);
if (!matcher.matches()) {
throw new IllegalArgumentException("keys must match regex "
+ STRING_KEY_PATTERN + ": \"" + key + "\"");
}
}
private static String inputStreamToString(InputStream in) throws IOException {
return Util.readFully(new InputStreamReader(in, Util.UTF_8));
}
/** A snapshot of the values for an entry. */
public final class Snapshot implements Closeable {
private final String key;
private final long sequenceNumber;
private final InputStream[] ins;
private final long[] lengths;
private Snapshot(String key, long sequenceNumber, InputStream[] ins, long[] lengths) {
this.key = key;
this.sequenceNumber = sequenceNumber;
this.ins = ins;
this.lengths = lengths;
}
/**
* Returns an editor for this snapshot's entry, or null if either the
* entry has changed since this snapshot was created or if another edit
* is in progress.
*/
public Editor edit() throws IOException {
return DiskLruCache.this.edit(key, sequenceNumber);
}
/** Returns the unbuffered stream with the value for {@code index}. */
public InputStream getInputStream(int index) {
return ins[index];
}
/** Returns the string value for {@code index}. */
public String getString(int index) throws IOException {
return inputStreamToString(getInputStream(index));
}
/** Returns the byte length of the value for {@code index}. */
public long getLength(int index) {
return lengths[index];
}
public void close() {
for (InputStream in : ins) {
Util.closeQuietly(in);
}
}
}
private static final OutputStream NULL_OUTPUT_STREAM = new OutputStream() {
@Override
public void write(int b) throws IOException {
// Eat all writes silently. Nom nom.
}
};
/** Edits the values for an entry. */
public final class Editor {
private final Entry entry;
private final boolean[] written;
private boolean hasErrors;
private boolean committed;
private Editor(Entry entry) {
this.entry = entry;
this.written = (entry.readable) ? null : new boolean[valueCount];
}
/**
* Returns an unbuffered input stream to read the last committed value,
* or null if no value has been committed.
*/
public InputStream newInputStream(int index) throws IOException {
synchronized (DiskLruCache.this) {
if (entry.currentEditor != this) {
throw new IllegalStateException();
}
if (!entry.readable) {
return null;
}
try {
return new FileInputStream(entry.getCleanFile(index));
} catch (FileNotFoundException e) {
return null;
}
}
}
/**
* Returns the last committed value as a string, or null if no value
* has been committed.
*/
public String getString(int index) throws IOException {
InputStream in = newInputStream(index);
return in != null ? inputStreamToString(in) : null;
}
/**
* Returns a new unbuffered output stream to write the value at
* {@code index}. If the underlying output stream encounters errors
* when writing to the filesystem, this edit will be aborted when
* {@link #commit} is called. The returned output stream does not throw
* IOExceptions.
*/
public OutputStream newOutputStream(int index) throws IOException {
if (index < 0 || index >= valueCount) {
throw new IllegalArgumentException("Expected index " + index + " to "
+ "be greater than 0 and less than the maximum value count "
+ "of " + valueCount);
}
synchronized (DiskLruCache.this) {
if (entry.currentEditor != this) {
throw new IllegalStateException();
}
if (!entry.readable) {
written[index] = true;
}
File dirtyFile = entry.getDirtyFile(index);
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(dirtyFile);
} catch (FileNotFoundException e) {
// Attempt to recreate the cache directory.
directory.mkdirs();
try {
outputStream = new FileOutputStream(dirtyFile);
} catch (FileNotFoundException e2) {
// We are unable to recover. Silently eat the writes.
return NULL_OUTPUT_STREAM;
}
}
return new FaultHidingOutputStream(outputStream);
}
}
/** Sets the value at {@code index} to {@code value}. */
public void set(int index, String value) throws IOException {
Writer writer = null;
try {
writer = new OutputStreamWriter(newOutputStream(index), Util.UTF_8);
writer.write(value);
} finally {
Util.closeQuietly(writer);
}
}
/**
* Commits this edit so it is visible to readers. This releases the
* edit lock so another edit may be started on the same key.
*/
public void commit() throws IOException {
if (hasErrors) {
completeEdit(this, false);
remove(entry.key); // The previous entry is stale.
} else {
completeEdit(this, true);
}
committed = true;
}
/**
* Aborts this edit. This releases the edit lock so another edit may be
* started on the same key.
*/
public void abort() throws IOException {
completeEdit(this, false);
}
public void abortUnlessCommitted() {
if (!committed) {
try {
abort();
} catch (IOException ignored) {
}
}
}
private class FaultHidingOutputStream extends FilterOutputStream {
private FaultHidingOutputStream(OutputStream out) {
super(out);
}
@Override
public void write(int oneByte) {
try {
out.write(oneByte);
} catch (IOException e) {
hasErrors = true;
}
}
@Override
public void write(byte[] buffer, int offset, int length) {
try {
out.write(buffer, offset, length);
} catch (IOException e) {
hasErrors = true;
}
}
@Override
public void close() {
try {
out.close();
} catch (IOException e) {
hasErrors = true;
}
}
@Override
public void flush() {
try {
out.flush();
} catch (IOException e) {
hasErrors = true;
}
}
}
}
private final class Entry {
private final String key;
/** Lengths of this entry's files. */
private final long[] lengths;
/** True if this entry has ever been published. */
private boolean readable;
/** The ongoing edit or null if this entry is not being edited. */
private Editor currentEditor;
/** The sequence number of the most recently committed edit to this entry. */
private long sequenceNumber;
private Entry(String key) {
this.key = key;
this.lengths = new long[valueCount];
}
public String getLengths() throws IOException {
StringBuilder result = new StringBuilder();
for (long size : lengths) {
result.append(' ').append(size);
}
return result.toString();
}
/** Set lengths using decimal numbers like "10123". */
private void setLengths(String[] strings) throws IOException {
if (strings.length != valueCount) {
throw invalidLengths(strings);
}
try {
for (int i = 0; i < strings.length; i++) {
lengths[i] = Long.parseLong(strings[i]);
}
} catch (NumberFormatException e) {
throw invalidLengths(strings);
}
}
private IOException invalidLengths(String[] strings) throws IOException {
throw new IOException("unexpected journal line: " + java.util.Arrays.toString(strings));
}
public File getCleanFile(int i) {
return new File(directory, key + "." + i);
}
public File getDirtyFile(int i) {
return new File(directory, key + "." + i + ".tmp");
}
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.util.Log;
import com.yidianling.common.tools.RxAppTool;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
/**
* Created by zhy on 15/7/28.
*/
public class DiskLruCacheHelper {
private static final String DIR_NAME = "diskCache";
private static final int MAX_COUNT = 10 * 1024 * 1024;
private static final int DEFAULT_APP_VERSION = 1;
/**
* The default valueCount when open DiskLruCache.
*/
private static final int DEFAULT_VALUE_COUNT = 1;
private static final String TAG = "DiskLruCacheHelper";
private DiskLruCache mDiskLruCache;
public DiskLruCacheHelper(Context context) throws IOException {
mDiskLruCache = generateCache(context, DIR_NAME, MAX_COUNT);
}
public DiskLruCacheHelper(Context context, String dirName) throws IOException {
mDiskLruCache = generateCache(context, dirName, MAX_COUNT);
}
public DiskLruCacheHelper(Context context, String dirName, int maxCount) throws IOException {
mDiskLruCache = generateCache(context, dirName, maxCount);
}
//custom cache dir
public DiskLruCacheHelper(File dir) throws IOException {
mDiskLruCache = generateCache(null, dir, MAX_COUNT);
}
public DiskLruCacheHelper(Context context, File dir) throws IOException {
mDiskLruCache = generateCache(context, dir, MAX_COUNT);
}
public DiskLruCacheHelper(Context context, File dir, int maxCount) throws IOException {
mDiskLruCache = generateCache(context, dir, maxCount);
}
private DiskLruCache generateCache(Context context, File dir, int maxCount) throws IOException {
if (!dir.exists() || !dir.isDirectory()) {
throw new IllegalArgumentException(
dir + " is not a directory or does not exists. ");
}
int appVersion = context == null ? DEFAULT_APP_VERSION : Utils.getAppVersion(context);
DiskLruCache diskLruCache = DiskLruCache.open(
dir,
appVersion,
DEFAULT_VALUE_COUNT,
maxCount);
return diskLruCache;
}
private DiskLruCache generateCache(Context context, String dirName, int maxCount) throws IOException {
DiskLruCache diskLruCache = DiskLruCache.open(
getDiskCacheDir(context, dirName),
Utils.getAppVersion(context),
DEFAULT_VALUE_COUNT,
maxCount);
return diskLruCache;
}
// =======================================
// ============== String 数据 读写 =============
// =======================================
public void put(String key, String value) {
DiskLruCache.Editor edit = null;
BufferedWriter bw = null;
try {
edit = editor(key);
if (edit == null) return;
OutputStream os = edit.newOutputStream(0);
bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write(value);
edit.commit();//write CLEAN
} catch (IOException e) {
try {
//s
edit.abort();//write REMOVE
} catch (IOException e1) {
e1.printStackTrace();
}
} finally {
try {
if (bw != null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String getAsString(String key) {
InputStream inputStream = null;
inputStream = get(key);
if (inputStream == null) return null;
String str = null;
try {
str = Util.readFully(new InputStreamReader(inputStream, Util.UTF_8));
} catch (Exception e) {
e.printStackTrace();
try {
inputStream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return str;
}
public void put(String key, JSONObject jsonObject) {
put(key, jsonObject.toString());
}
public JSONObject getAsJson(String key) {
String val = getAsString(key);
try {
if (val != null)
return new JSONObject(val);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
// =======================================
// ============ JSONArray 数据 读写 =============
// =======================================
public void put(String key, JSONArray jsonArray) {
put(key, jsonArray.toString());
}
public JSONArray getAsJSONArray(String key) {
String JSONString = getAsString(key);
try {
JSONArray obj = new JSONArray(JSONString);
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// =======================================
// ============== byte 数据 读写 =============
// =======================================
/**
* 保存 byte数据 到 缓存中
*
* @param key 保存的key
* @param value 保存的数据
*/
public void put(String key, byte[] value) {
OutputStream out = null;
DiskLruCache.Editor editor = null;
try {
editor = editor(key);
if (editor == null) {
return;
}
out = editor.newOutputStream(0);
out.write(value);
out.flush();
editor.commit();//write CLEAN
} catch (Exception e) {
e.printStackTrace();
try {
editor.abort();//write REMOVE
} catch (IOException e1) {
e1.printStackTrace();
}
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public byte[] getAsBytes(String key) {
byte[] res = null;
InputStream is = get(key);
if (is == null) return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] buf = new byte[256];
int len = 0;
while ((len = is.read(buf)) != -1) {
baos.write(buf, 0, len);
}
res = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return res;
}
// =======================================
// ============== 序列化 数据 读写 =============
// =======================================
public void put(String key, Serializable value) {
DiskLruCache.Editor editor = editor(key);
ObjectOutputStream oos = null;
if (editor == null) return;
try {
OutputStream os = editor.newOutputStream(0);
oos = new ObjectOutputStream(os);
oos.writeObject(value);
oos.flush();
editor.commit();
} catch (IOException e) {
e.printStackTrace();
try {
editor.abort();
} catch (IOException e1) {
e1.printStackTrace();
}
} finally {
try {
if (oos != null)
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public <T> T getAsSerializable(String key) {
T t = null;
InputStream is = get(key);
ObjectInputStream ois = null;
if (is == null) return null;
try {
ois = new ObjectInputStream(is);
t = (T) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return t;
}
// =======================================
// ============== bitmap 数据 读写 =============
// =======================================
public void put(String key, Bitmap bitmap) {
put(key, Utils.bitmap2Bytes(bitmap));
}
public Bitmap getAsBitmap(String key) {
byte[] bytes = getAsBytes(key);
if (bytes == null) return null;
return Utils.bytes2Bitmap(bytes);
}
// =======================================
// ============= drawable 数据 读写 =============
// =======================================
public void put(String key, Drawable value) {
put(key, Utils.drawable2Bitmap(value));
}
public Drawable getAsDrawable(String key) {
byte[] bytes = getAsBytes(key);
if (bytes == null) {
return null;
}
return Utils.bitmap2Drawable(Utils.bytes2Bitmap(bytes));
}
// =======================================
// ============= other methods =============
// =======================================
public boolean remove(String key) {
try {
key = Utils.hashKeyForDisk(key);
return mDiskLruCache.remove(key);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public void close() throws IOException {
mDiskLruCache.close();
}
public void delete() throws IOException {
mDiskLruCache.delete();
}
public void flush() throws IOException {
mDiskLruCache.flush();
}
public boolean isClosed() {
return mDiskLruCache.isClosed();
}
public long size() {
return mDiskLruCache.size();
}
public void setMaxSize(long maxSize) {
mDiskLruCache.setMaxSize(maxSize);
}
public File getDirectory() {
return mDiskLruCache.getDirectory();
}
public long getMaxSize() {
return mDiskLruCache.getMaxSize();
}
// =======================================
// ===遇到文件比较大的,可以直接通过流读写 =====
// =======================================
//basic editor
public DiskLruCache.Editor editor(String key) {
try {
key = Utils.hashKeyForDisk(key);
//wirte DIRTY
DiskLruCache.Editor edit = mDiskLruCache.edit(key);
//edit maybe null :the entry is editing
if (edit == null) {
Log.w(TAG, "the entry spcified key:" + key + " is editing by other . ");
}
return edit;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String getString(String key) {
ByteArrayOutputStream bos = null;
FileInputStream ins = null;
try {
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(Utils.hashKeyForDisk(key));
if (snapshot == null) //not find entry , or entry.readable = false
{
Log.e(TAG, "not find entry , or entry.readable = false");
return null;
}
//write READ
ins = (FileInputStream) snapshot.getInputStream(0);
bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = ins.read(buf)) != -1) {
bos.write(buf, 0, len);
}
byte[] data = bos.toByteArray();
return new String(data);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
closeIgnoringException(ins);
closeIgnoringException(bos);
}
}
//basic get
public InputStream get(String key) {
try {
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(Utils.hashKeyForDisk(key));
if (snapshot == null) //not find entry , or entry.readable = false
{
Log.e(TAG, "not find entry , or entry.readable = false");
return null;
}
//write READ
return snapshot.getInputStream(0);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// =======================================
// ============== 序列化 数据 读写 =============
// =======================================
private File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
//小米monkey测试为空 感觉小米是用模拟器测试的 这里当为空时 返回应用包名路径
if (null == context.getExternalCacheDir()){
cachePath = RxAppTool.getAppPackageName(context);
}else {
cachePath = context.getExternalCacheDir().getPath();
}
} else {
cachePath = context.getCacheDir().getPath();
}
return new File(cachePath + File.separator + uniqueName);
}
private void closeIgnoringException(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException ex) {
}
}
}
}
package com.yidianling.ydlcommon.custom.http;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonWriter;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Converter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* Created by Jim on 2017/12/9 0009.
*/
class GsonRespConvertFactory extends Converter.Factory{
public static GsonRespConvertFactory create() {
return create(new Gson());
}
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonRespConvertFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonRespConvertFactory(gson);
}
private final Gson gson;
private GsonRespConvertFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
package com.yidianling.ydlcommon.custom.http;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.yidianling.common.tools.LogUtil;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import java.io.IOException;
import java.io.StringReader;
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
String resp = value.string();
LogUtil.d("resp: " + resp);
BaseResponse response = gson.fromJson(resp, BaseResponse.class);
JsonReader reader = new JsonReader(new StringReader(resp));
try {
return adapter.read(reader);
} catch (Exception e) {
LogUtil.e("catch Exception!!!");
throw new ResultException(response.code, response.msg);
} finally {
value.close();
}
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.common.tools.RxNetTool;
import com.yidianling.ydlcommon.BuildConfig;
import okhttp3.Response;
import okhttp3.*;
import okhttp3.internal.http.HttpHeaders;
import okio.Buffer;
import okio.BufferedSource;
import java.io.IOException;
import java.nio.charset.Charset;
import static okhttp3.internal.Util.closeQuietly;
/**
* Created by Jim on 2017/12/20 0020.
*/
class PostCacheInterceptor implements Interceptor {
final DiskLruCacheHelper cache;
public PostCacheInterceptor(DiskLruCacheHelper cache) {
this.cache = cache;
}
private final int REQUEST_URL = 0;
private final int REQUEST_METHOD = 1;
private final int REQUESTCONTENTTYPE = 2;
private final int PROTOCAL = 3;
private final int CODE = 4;
private final int MESSAGE = 5;
private final int REPONSE_BODY = 6;
private final int MEDIA_TYPE = 7;
private final int SETN_REQUEST_AT_MILLIS = 8;
private final int RECEIVE_REPONSE_AT_MILLIS = 9;
private final int CACHE_LENGTH = 10;
@Override
public Response intercept(Chain chain) throws IOException {
//匹配是否为需要读取缓存逻辑
if (!isNeedCache(chain.request().url().toString())) {
//没有网络连接的时候 并且不再缓存策略里的 返回无网络
if (!RxNetTool.isConnected(BaseApplication.Companion.getApp())) {
Request request = chain.request();
Response originalResponse = chain.proceed(request);
int maxTime = 0;
return originalResponse.newBuilder()
//这里的设置的是我们的没有网络的缓存时间,想设置多少就是多少。
.header("Cache-Control", "public, only-if-cached, max-stale="+maxTime)
.removeHeader("Pragma")
.build();
}
return chain.proceed(chain.request());
}
//获取缓存
String key = createKey(chain.request());
LogUtil.d("cache key: " + key);
Response cacheResponse = null;
String cacheRes = cache != null && key != null
? cache.getAsString(key)
: null;
if (!TextUtils.isEmpty(cacheRes)) {
LogUtil.d("cacheRes: " + cacheRes);
cacheResponse = combineCacheToResponse(cacheRes);
}
//没有网络连接的时候读取缓存
if (!RxNetTool.isConnected(BaseApplication.Companion.getApp())) {
if (cacheResponse != null) {
return cacheResponse;
}else {
Request request = chain.request();
Response originalResponse = chain.proceed(request);
int maxTime = 0;
return originalResponse.newBuilder()
//这里的设置的是我们的没有网络的缓存时间,想设置多少就是多少。
.header("Cache-Control", "public, only-if-cached, max-stale="+maxTime)
.removeHeader("Pragma")
.build();
}
}
//获取网络响应
Request netWorkRequest = chain.request();
Response networkResponse = null;
try {
networkResponse = chain.proceed(netWorkRequest);
} finally {
if (networkResponse == null) {
LogUtil.d("close cache response...");
if (cacheResponse != null && cacheResponse.body() != null) {
closeQuietly(cacheResponse.body());
}
return networkResponse;
}
}
LogUtil.d("prepare update cache response...");
//更新缓存
if (cacheResponse != null) {
Response response = null;
response = networkResponse.newBuilder()
.request(new Request.Builder()
.method("GET", null)
.url(netWorkRequest.url())
.headers(netWorkRequest.headers())
.tag(netWorkRequest.tag())
.build())
.build();
LogUtil.d("update cache response");
if (key != null) {
cache.put(key, createCache(response));
}
return networkResponse;
}
Request newRequest = new Request.Builder()
.method("GET", null)
.url(netWorkRequest.url())
.headers(netWorkRequest.headers())
.tag(netWorkRequest.tag())
.build();
Response newResponse = networkResponse.newBuilder()
.request(newRequest)
.build();
LogUtil.d("init cache response");
//放入缓存
if (cache != null) {
LogUtil.d("url: " + netWorkRequest.url().toString());
if (HttpHeaders.hasBody(newResponse)) {
try {
LogUtil.d("chain request url: " + newResponse.request().url());
if (key != null) {
cache.put(key, createCache(newResponse));
LogUtil.d("put cache response key: " + key);
}
String resp1 = cache.getAsString(key);
LogUtil.d("resp1: " + resp1);
return networkResponse;
} catch (Exception e) {
LogUtil.d("put cache exception: " + e);
}
}
}
return newResponse;
}
private String createKey(Request request) {
RequestBody requestBody = request.body();
Charset charset = Charset.forName("UTF-8");
String url = request.url().toString();
StringBuilder sb = new StringBuilder();
sb.append(url + "&");
if (null == requestBody && request.method().equals("GET")){
// sb.append(request.url().query());
}else {
if (null == requestBody){
return sb.toString();
}
MediaType type = requestBody.contentType();
if (type != null) {
charset = type.charset() == null ? charset : type.charset();
}
Buffer buffer = new Buffer();
try {
requestBody.writeTo(buffer);
sb.append(buffer.readString(charset));
} catch (Exception e) {
LogUtil.d("read request error: " + e);
} finally {
buffer.close();
}
}
LogUtil.e("http-----------param="+sb.toString());
if (url.startsWith(BuildConfig.SERVER_URL + "sq-active/active-list")) {
return createTrendsKey(sb.toString());
} else if (url.startsWith(BuildConfig.SERVER_URL + "sq-active/topic-list")) {
return url + "&" + createTopicKey(sb.toString());
} else if (url.startsWith(BuildConfig.SERVER_URL + "site/index")) {
return url + "&" + createHomeKey(sb.toString());
} else if (url.startsWith(BuildConfig.SERVER_JAVA_API_URL + "ask/list-old")){
return url + "&" + createAskListKey(sb.toString());
}
return sb.toString();
// LogUtil.d("original key: " + sb.toString());
// int tsStartIndex = sb.indexOf("ts=");
// int tsEndIndex = sb.indexOf("&", tsStartIndex) >= 0 ? sb.indexOf("&", tsStartIndex) + 1 : sb.length();
// if (tsStartIndex >= 0 && tsEndIndex >= 0) {
// sb.delete(tsStartIndex, tsEndIndex);
// }
//
// int tokenStartIndex = sb.indexOf("accessToken=");
// int tokenEndIndex = sb.indexOf("&", tokenStartIndex) >= 0 ? sb.indexOf("&", tokenStartIndex) + 1 : sb.length();
// if (tokenStartIndex >= 0 && tokenEndIndex >= 0) {
// sb.delete(tokenStartIndex, tokenEndIndex);
// }
//
// int uidStartIndex = sb.indexOf("uid=");
// int uidEndIndex = sb.indexOf("&", uidStartIndex) >= 0 ? sb.indexOf("&", uidStartIndex) + 1 : sb.length();
// if (uidStartIndex >= 0 && uidEndIndex >= 0) {
// sb.delete(uidStartIndex, uidEndIndex);
// }
}
//根据键返回索引
private int[] getIndexofKeyValue(String str, String originStr) {
int[] indexs = new int[2];
indexs[0] = originStr.indexOf(str);
indexs[1] = originStr.indexOf("&", indexs[0]) >= 0 ? originStr.indexOf("&", indexs[0]) : originStr.length();
LogUtil.d("index0: " + indexs[0] + " index1: " + indexs[1]);
return indexs;
}
private @Nullable
String createTrendsKey(String originKey) {
StringBuilder builder = new StringBuilder();
builder.append(subString(originKey, getIndexofKeyValue("version=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("tab=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("id=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("topic_id=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("page=", originKey)));
LogUtil.d("trends key: " + builder.toString());
if (builder.toString().endsWith("page=1")) {
return BuildConfig.SERVER_URL + "sq-active/active-list" + "&" + builder.toString();
}
return null;
}
private String createHomeKey(String originKey) {
StringBuilder builder = new StringBuilder();
builder.append(subString(originKey, getIndexofKeyValue("version=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("os_type=", originKey)));
LogUtil.d("home key: " + builder.toString());
return builder.toString();
}
private String createAskListKey(String originKey){
StringBuilder builder = new StringBuilder();
builder.append(subString(originKey, getIndexofKeyValue("tab=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("page=", originKey)));
builder.append(subString(originKey, getIndexofKeyValue("topicId=", originKey)));
builder.append(subString(originKey, getIndexofKeyValue("id=", originKey)));
LogUtil.e("ask key: " + builder.toString());
return builder.toString();
}
private String createTopicKey(String originKey) {
StringBuilder builder = new StringBuilder();
builder.append(subString(originKey, getIndexofKeyValue("version=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("cate=", originKey)) + "&");
builder.append(subString(originKey, getIndexofKeyValue("my=", originKey)));
LogUtil.d("topic key: " + builder.toString());
return builder.toString();
}
private boolean isNeedCache(String url) {
return url.startsWith(BuildConfig.SERVER_URL + "sq-active/active-list") ||
url.startsWith(BuildConfig.SERVER_URL + "sq-active/topic-list") ||
url.startsWith(BuildConfig.SERVER_URL + "site/index") ||
url.startsWith(BuildConfig.SERVER_JAVA_API_URL + "ask/list-old");
}
private Response combineCacheToResponse(String cache) {
String[] caches = cache.split("&#&#");
if (caches == null || caches.length <= 0) {
return null;
}
Request request = new Request.Builder()
.url(caches[REQUEST_URL])
.method(caches[REQUEST_METHOD], null)
.build();
Response.Builder builder = new Response.Builder();
try {
builder.protocol(Protocol.get(caches[PROTOCAL]));
} catch (IOException e) {
e.printStackTrace();
}
try {
LogUtil.e("http----json="+ResponseBody.create(MediaType.parse(caches[MEDIA_TYPE]), caches[REPONSE_BODY]).string());
} catch (IOException e) {
e.printStackTrace();
}
return builder.message(caches[MESSAGE])
.code(Integer.valueOf(caches[CODE]))
.request(request)
.receivedResponseAtMillis(Long.valueOf(caches[RECEIVE_REPONSE_AT_MILLIS]))
.sentRequestAtMillis(Long.valueOf(caches[SETN_REQUEST_AT_MILLIS]))
.body(ResponseBody.create(MediaType.parse(caches[MEDIA_TYPE]), caches[REPONSE_BODY]))
.build();
}
private String createCache(Response response) {
String[] caches = new String[CACHE_LENGTH];
caches[REQUEST_URL] = response.request().url().toString();
caches[REQUEST_METHOD] = response.request().method();
if (response.request().body() != null && response.request().body().contentType() != null) {
caches[REQUESTCONTENTTYPE] = response.request().body().contentType().toString();
} else {
caches[REQUESTCONTENTTYPE] = "application/x-www-form-urlencoded";
}
caches[PROTOCAL] = response.protocol().toString();
caches[CODE] = response.code() + "";
caches[MESSAGE] = response.message();
if (response.body() != null && response.body().contentType() != null) {
caches[MEDIA_TYPE] = response.body().contentType().toString();
} else {
caches[MEDIA_TYPE] = "application/x-www-form-urlencoded";
}
caches[SETN_REQUEST_AT_MILLIS] = response.sentRequestAtMillis() + "";
caches[RECEIVE_REPONSE_AT_MILLIS] = response.receivedResponseAtMillis() + "";
if (HttpHeaders.hasBody(response)) {
BufferedSource source = response.body().source();
Buffer buffer = null;
try {
source.request(Long.MAX_VALUE);
buffer = source.buffer();
Charset charset = response.body().contentType().charset();
if (charset == null) {
charset = Charset.forName("UTF-8");
}
caches[REPONSE_BODY] = buffer.clone().readString(charset);
} catch (IOException e) {
e.printStackTrace();
}
}
String cache = "";
for (String str : caches) {
cache += str + "&#&#";
}
return cache;
}
static boolean isEndToEnd(String fieldName) {
return !"Connection".equalsIgnoreCase(fieldName)
&& !"Keep-Alive".equalsIgnoreCase(fieldName)
&& !"Proxy-Authenticate".equalsIgnoreCase(fieldName)
&& !"Proxy-Authorization".equalsIgnoreCase(fieldName)
&& !"TE".equalsIgnoreCase(fieldName)
&& !"Trailers".equalsIgnoreCase(fieldName)
&& !"Transfer-Encoding".equalsIgnoreCase(fieldName)
&& !"Upgrade".equalsIgnoreCase(fieldName);
}
private String subString(String str, int[] index) {
if (index == null || index.length < 2) {
return null;
}
if (index[0] < 0 || index[1] < 0) {
return null;
}
return str.substring(index[0], index[1]);
}
}
package com.yidianling.ydlcommon.custom.http;
import java.io.IOException;
/**
* Created by Jim on 2017/12/9 0009.
*/
class ResultException extends IOException {
private int errorCode;
private String errorMsg;
public ResultException(int errorCode, String msg) {
this.errorCode = errorCode;
this.errorMsg = msg;
}
public int getErrorCode() {
return errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public void setErrorMsg(String msg) {
this.errorMsg = msg;
}
}
package com.yidianling.ydlcommon.custom.http
//import com.yidianling.common.tools.RxAppTool
//import com.yidianling.common.tools.RxDeviceTool
import android.annotation.SuppressLint
import android.text.TextUtils
import com.facebook.stetho.okhttp3.StethoInterceptor
import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxAppTool
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.ydlcommon.BuildConfig
import com.yidianling.ydlcommon.custom.constant.YdlConstants
import com.yidianling.ydlcommon.custom.data.YdlDataManager
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import okio.BufferedSink
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.security.cert.X509Certificate
import java.util.*
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import javax.net.ssl.X509TrustManager
/**
* Retrofit 提供类,提供单例的 Retrofit 对象
*
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*/
class RetrofitProvider private constructor() {
companion object {
// private val BASE_URL_TEST = "https://testapp2.yidianling.com/v3/"
// private val BASE_URL = "https://app2.yidianling.com/v3/"
private const val AUTHORIZATION_NAME = "Authorization"
private const val SESSION_KEY = "dc59cf294f37d237c1f06240568ffe21"
private const val YDL = "Ydl"
private const val UID = "uid"
private const val FFROM = "ffrom"
private const val IS_FROM_APP = "isFromApp"
private const val OS_BUILD = "osBuild"
private const val TS = "ts"
private const val VERSION = "version"
private const val TOKEN = "accessToken"
private fun getInstance(): RetrofitProvider {
return Holder.INSTANCE
}
// 调用此方法获取 Retrofit 对象
fun getRetrofit(): Retrofit {
return getInstance().getRetrofit()
}
//销毁对象
fun clearRetrofit() {
return getInstance().clearRetrofit()
}
}
private fun clearRetrofit() {
retrofit = null
}
private var retrofit: Retrofit? = null
private fun getRetrofit(): Retrofit {
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.POST)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClick())
.build()
}
return retrofit!!
}
private fun okHttpClick(): OkHttpClient {
var build = OkHttpClient.Builder()
build.retryOnConnectionFailure(false)
try {
build.addInterceptor(
com.yidianling.ydlcommon.custom.http.PostCacheInterceptor(
com.yidianling.ydlcommon.custom.http.DiskLruCacheHelper(
BaseApplication.getApp()
)
)
)
} catch (e: Exception) {
}
build.addInterceptor(commonParams())
build.addInterceptor(requestHead())
build.connectTimeout(15, TimeUnit.SECONDS)
build.readTimeout(15, TimeUnit.SECONDS)
build.writeTimeout(15, TimeUnit.SECONDS)
//设置okhttp的连接池保活时间为1秒
//build.connectionPool(ConnectionPool(5,1,TimeUnit.SECONDS))
//使用自定义线程池方案,防止线程数超出最大限制造成OOM(华为部分机型线程数限制300)
build.dispatcher(Dispatcher(ThreadPoolExecutor(2, 20, 20L, TimeUnit.SECONDS, LinkedBlockingQueue<Runnable>(64), ThreadPoolExecutor.DiscardOldestPolicy())))
val xtm = trustManager()
val factory = com.yidianling.ydlcommon.custom.http.YDLSSLFactory.getSocketFactory();
if (BuildConfig.DEBUG) {
build.addInterceptor(HttpLoggingInterceptor {
//打印retrofit日志
LogUtil.i("RetrofitLog", "retrofitBack = $it")
}.setLevel(HttpLoggingInterceptor.Level.BODY))
build.addNetworkInterceptor(StethoInterceptor())
}
if (factory != null) {
build.sslSocketFactory(factory, com.yidianling.ydlcommon.custom.http.YDLSSLFactory.getSafeTrustManager())
.hostnameVerifier { _, _ -> true }
}
return build.build()
}
// 添加公共参数
private fun commonParams(): Interceptor {
return Interceptor {
val request = it.request()
var body = request.body()
if (body is FormBody) {
val bodyBuild = FormBody.Builder()
for (i in 0 until body.size()) {
val name = body.name(i)
val value = body.value(i)
// 去除假参数和值为空的参数
if (YdlConstants.HOLDER_PARAM != name && !TextUtils.isEmpty(value)) {
bodyBuild.addEncoded(name, value)
}
}
bodyBuild.addEncoded(FFROM, YdlDataManager.getRam().getChannelName())
.addEncoded(IS_FROM_APP, "1")
.addEncoded(
OS_BUILD, """${RxDeviceTool.getBuildBrandModel()},${RxDeviceTool.getSDKVersionName()},${RxAppTool.getAppVersionName(
BaseApplication.getApp())}""")
.addEncoded(TS, (System.currentTimeMillis() / 1000).toString())
.addEncoded(
VERSION, RxAppTool.getAppVersionName(
BaseApplication.getApp()))
val loginBean = YdlCommonRouterManager.getYdlCommonRoute()?.getUserInfo()
if (loginBean != null) {
bodyBuild.addEncoded(UID, loginBean.userId)
bodyBuild.addEncoded(TOKEN, loginBean.token)
}
body = bodyBuild.build()
} else if (body is MultipartBody) {
}
it.proceed(request.newBuilder().post(body!!).build())
}
}
private data class Param(val name: String, val value: String)
// 添加请求头
private fun requestHead(): Interceptor {
return Interceptor {
val request = it.request()
val body = request.body()
val paramsString = StringBuilder()
val params = ArrayList<Param>()
if (body is FormBody) {
(0 until body.size()).mapTo(destination = params) {
Param(
body.name(it),
body.value(it)
)
}
} else if (body is MultipartBody) {
for (part in body.parts()) {
if ("text/plain; charset=utf-8" == part.body().contentType()!!.toString()) {
val headerStr = part.headers()!!.toString()
val name = headerStr.split("\"\\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].split("=\"".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
val buffer = Buffer()
part.body().writeTo(buffer as BufferedSink)
val value = buffer.readUtf8()
params.add(Param(name, value))
}
}
}
params.sortWith(Comparator { o1, o2 ->
val res = o1.name.compareTo(o2.name)
when {
res == 0 -> 0
res > 0 -> -1
else -> 1
}
})
params.withIndex().forEach { (index, param) ->
if (index != 0) paramsString.append("&")
paramsString.append("${param.name}=${param.value}")
}
paramsString.append(SESSION_KEY)
val head = "$YDL ${EncryptUtils.encryptMD5ToString(
paramsString.toString()
)}"
it.proceed(request.newBuilder()
.header(AUTHORIZATION_NAME, head)
// .header("Content-Type","application/json")
.build())
}
}
private fun log(): Interceptor {
return HttpLoggingInterceptor {
when {
BuildConfig.DEBUG -> LogUtil.d("RetrofitLog", it)
}
}.setLevel(HttpLoggingInterceptor.Level.BODY)
}
@SuppressLint("TrustAllX509TrustManager")
private fun trustManager(): X509TrustManager {
return object : X509TrustManager {
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
override fun getAcceptedIssuers(): Array<X509Certificate?> {
return arrayOfNulls(0)
}
}
}
private object Holder {
val INSTANCE = RetrofitProvider()
}
}
\ No newline at end of file
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yidianling.ydlcommon.custom.http;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
* Buffers input from an {@link InputStream} for reading lines.
*
* <p>This class is used for buffered reading of lines. For purposes of this class, a line ends
* with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated
* line at end of input is invalid and will be ignored, the caller may use {@code
* hasUnterminatedLine()} to detect it after catching the {@code EOFException}.
*
* <p>This class is intended for reading input that strictly consists of lines, such as line-based
* cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction
* with {@link java.io.InputStreamReader} provides similar functionality, this class uses different
* end-of-input reporting and a more restrictive definition of a line.
*
* <p>This class supports only charsets that encode '\r' and '\n' as a single byte with value 13
* and 10, respectively, and the representation of no other character contains these values.
* We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1.
* The default charset is US_ASCII.
*/
class StrictLineReader implements Closeable {
private static final byte CR = (byte) '\r';
private static final byte LF = (byte) '\n';
private final InputStream in;
private final Charset charset;
/*
* Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end
* and the data in the range [pos, end) is buffered for reading. At end of input, if there is
* an unterminated line, we set end == -1, otherwise end == pos. If the underlying
* {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1.
*/
private byte[] buf;
private int pos;
private int end;
/**
* Constructs a new {@code LineReader} with the specified charset and the default capacity.
*
* @param in the {@code InputStream} to read data from.
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
* supported.
* @throws NullPointerException if {@code in} or {@code charset} is null.
* @throws IllegalArgumentException if the specified charset is not supported.
*/
public StrictLineReader(InputStream in, Charset charset) {
this(in, 8192, charset);
}
/**
* Constructs a new {@code LineReader} with the specified capacity and charset.
*
* @param in the {@code InputStream} to read data from.
* @param capacity the capacity of the buffer.
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
* supported.
* @throws NullPointerException if {@code in} or {@code charset} is null.
* @throws IllegalArgumentException if {@code capacity} is negative or zero
* or the specified charset is not supported.
*/
public StrictLineReader(InputStream in, int capacity, Charset charset) {
if (in == null || charset == null) {
throw new NullPointerException();
}
if (capacity < 0) {
throw new IllegalArgumentException("capacity <= 0");
}
if (!(charset.equals(Util.US_ASCII))) {
throw new IllegalArgumentException("Unsupported encoding");
}
this.in = in;
this.charset = charset;
buf = new byte[capacity];
}
/**
* Closes the reader by closing the underlying {@code InputStream} and
* marking this reader as closed.
*
* @throws IOException for errors when closing the underlying {@code InputStream}.
*/
public void close() throws IOException {
synchronized (in) {
if (buf != null) {
buf = null;
in.close();
}
}
}
/**
* Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"},
* this end of line marker is not included in the result.
*
* @return the next line from the input.
* @throws IOException for underlying {@code InputStream} errors.
* @throws EOFException for the end of source stream.
*/
public String readLine() throws IOException {
synchronized (in) {
if (buf == null) {
throw new IOException("LineReader is closed");
}
// Read more data if we are at the end of the buffered data.
// Though it's an error to read after an exception, we will let {@code fillBuf()}
// throw again if that happens; thus we need to handle end == -1 as well as end == pos.
if (pos >= end) {
fillBuf();
}
// Try to find LF in the buffered data and return the line if successful.
for (int i = pos; i != end; ++i) {
if (buf[i] == LF) {
int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
String res = new String(buf, pos, lineEnd - pos, charset.name());
pos = i + 1;
return res;
}
}
// Let's anticipate up to 80 characters on top of those already read.
ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
@Override
public String toString() {
int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
try {
return new String(buf, 0, length, charset.name());
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e); // Since we control the charset this will never happen.
}
}
};
while (true) {
out.write(buf, pos, end - pos);
// Mark unterminated line in case fillBuf throws EOFException or IOException.
end = -1;
fillBuf();
// Try to find LF in the buffered data and return the line if successful.
for (int i = pos; i != end; ++i) {
if (buf[i] == LF) {
if (i != pos) {
out.write(buf, pos, i - pos);
}
pos = i + 1;
return out.toString();
}
}
}
}
}
public boolean hasUnterminatedLine() {
return end == -1;
}
/**
* Reads new input data into the buffer. Call only with pos == end or end == -1,
* depending on the desired outcome if the function throws.
*/
private void fillBuf() throws IOException {
int result = in.read(buf, 0, buf.length);
if (result == -1) {
throw new EOFException();
}
pos = 0;
end = result;
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http
import com.google.gson.Gson
import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxNetTool
import com.yidianling.ydlcommon.custom.bean.WebViewTimeBean
import com.yidianling.ydlcommon.custom.data.YdlDataManager
import com.yidianling.ydlcommon.custom.http.api.ApiRequestUtil
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
/**
* @author jiucheng
* @描述:上传webview的初始化时间、加载url时间
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/8
*/
class UploadWebViewTimeUtils {
companion object {
/**
* 上传webview初始化时间及加载url时间
* @param url 加载的url
* @param initTime webview初始化时间
* @param loadTime url加载时间
* @param netSpeed 网速
*/
fun uploadWebViewTime(url: String, initTime: String, loadTime: String, netSpeed: String) {
val userInfo = YdlCommonRouterManager.getYdlCommonRoute()?.getUserInfo()
var uid = ""
if (userInfo != null) {
uid = userInfo.userId
}
var bean = WebViewTimeBean(
url,
initTime,
loadTime,
YdlDataManager.getRam().getChannelName(),
RxDeviceTool.getBuildMANUFACTURER() + "," + RxDeviceTool.getBuildBrandModel() + "," + RxDeviceTool.getOsBuileVersion() + "," + RxDeviceTool.getAppVersionName(
BaseApplication.getApp()
),
RxDeviceTool.getAppVersionName(BaseApplication.getApp()),
(System.currentTimeMillis() / 1000).toString() + "",
"1",
uid,
netSpeed,
RxNetTool.getNetWorkTypeName(BaseApplication.getApp())
)
var gson = Gson()
var params = gson.toJson(bean)
ApiRequestUtil.uploadWebViewTime(params)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ baseResponse -> LogUtil.d("upload status : " + baseResponse.code + " " + baseResponse.msg) })
{ throwable -> LogUtil.d("upload log error: $throwable") }
}
}
}
\ No newline at end of file
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yidianling.ydlcommon.custom.http;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.nio.charset.Charset;
/**
* Junk drawer of utility methods.
*/
final class Util
{
static final Charset US_ASCII = Charset.forName("US-ASCII");
static final Charset UTF_8 = Charset.forName("UTF-8");
private Util()
{
}
static String readFully(Reader reader) throws IOException
{
try
{
StringWriter writer = new StringWriter();
char[] buffer = new char[1024];
int count;
while ((count = reader.read(buffer)) != -1)
{
writer.write(buffer, 0, count);
}
return writer.toString();
} finally
{
reader.close();
}
}
/**
* Deletes the contents of {@code dir}. Throws an IOException if any file
* could not be deleted, or if {@code dir} is not a readable directory.
*/
static void deleteContents(File dir) throws IOException
{
File[] files = dir.listFiles();
if (files == null)
{
throw new IOException("not a readable directory: " + dir);
}
for (File file : files)
{
if (file.isDirectory())
{
deleteContents(file);
}
if (!file.delete())
{
throw new IOException("failed to delete file: " + file);
}
}
}
static void closeQuietly(/*Auto*/Closeable closeable)
{
if (closeable != null)
{
try
{
closeable.close();
} catch (RuntimeException rethrown)
{
throw rethrown;
} catch (Exception ignored)
{
}
}
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
class Utils
{
public static int getAppVersion(Context context)
{
try
{
PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return info.versionCode;
} catch (PackageManager.NameNotFoundException e)
{
e.printStackTrace();
}
return 1;
}
public static String hashKeyForDisk(String key)
{
String cacheKey;
try
{
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e)
{
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
}
public static String bytesToHexString(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++)
{
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1)
{
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
public static byte[] bitmap2Bytes(Bitmap bm)
{
if (bm == null)
{
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
public static Bitmap bytes2Bitmap(byte[] bytes)
{
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
/**
* Drawable → Bitmap
*/
public static Bitmap drawable2Bitmap(Drawable drawable)
{
if (drawable == null)
{
return null;
}
// 取 drawable 的长宽
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
// 取 drawable 的颜色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
// 建立对应 bitmap
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
// 建立对应 bitmap 的画布
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
// 把 drawable 内容画到画布中
drawable.draw(canvas);
return bitmap;
}
/*
* Bitmap → Drawable
*/
@SuppressWarnings("deprecation")
public static Drawable bitmap2Drawable(Bitmap bm)
{
if (bm == null)
{
return null;
}
BitmapDrawable bd = new BitmapDrawable(bm);
bd.setTargetDensity(bm.getDensity());
return new BitmapDrawable(bm);
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.ydlcommon.BuildConfig;
import com.yidianling.ydlcommon.R;
import com.yidianling.ydlcommon.custom.remind.ToastHelper;
import javax.net.ssl.*;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* Created by haorui on 2019/7/9.
* Des:SSL证书工具类
*/
public class YDLSSLFactory {
private static final String KEY_STORE_TYPE_BKS = "BKS";//证书类型
private static final String KEY_STORE_TYPE_P12 = "PKCS12";//证书类型
private static final String KEY_STORE_PASSWORD = "123456";//证书密码(客户端证书密码)
private static final String KEY_STORE_TRUST_PASSWORD = "123456";//授信证书密码(服务端证书密码)
/**
* 单向证书认证
*
* @returndailyContent
*/
public static SSLSocketFactory getSocketFactory() {
if (BuildConfig.DEBUG){
return getTrustAllSocketFactory();
}
checkNetProxy();
try {
InputStream inputStream = BaseApplication.Companion.getApp().getResources().openRawResource(R.raw.ydl_trust);
//keystore添加证书内容和密码
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
keyStore.load(inputStream, KEY_STORE_PASSWORD.toCharArray());
//key管理器工厂
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());
//证书工厂类,生成证书
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
//生成证书,添加别名
keyStore.setCertificateEntry("certificate", certificateFactory.generateCertificate(inputStream));
//信任管理器工厂
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//构建一个ssl上下文,加入ca证书格式,与后台保持一致
SSLContext sslContext = SSLContext.getInstance("TLS");
//参数,添加受信任证书和生成随机数
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
//获得scoket工厂
return sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 双向证书认证
* 目前服务器暂不支持双向认证
* 使用时需要补充客户端证书
*
* @return
*/
public static SSLSocketFactory getTwoWaySocketFactory() {
if (BuildConfig.DEBUG){
return getTrustAllSocketFactory();
}
checkNetProxy();
try {
//将ca证书导入输入流
InputStream trust_input = BaseApplication.Companion.getApp().getResources().openRawResource(R.raw.ydl_trust);//服务器授信证书
InputStream client_input = BaseApplication.Companion.getApp().getResources().openRawResource(R.raw.ydl_trust);//客户端证书
//keystore添加证书内容和密码
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(trust_input, KEY_STORE_TRUST_PASSWORD.toCharArray());
//证书工厂类,生成证书
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
//生成证书,添加别名
keyStore.setCertificateEntry("certificate", certificateFactory.generateCertificate(trust_input));
//信任管理器工厂
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//双向验证,配置服务器验证客户端的证书
KeyStore keyStore1 = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore1.load(client_input, KEY_STORE_PASSWORD.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore1, KEY_STORE_PASSWORD.toCharArray());
//构建一个ssl上下文,加入ca证书格式,与后台保持一致
SSLContext sslContext = SSLContext.getInstance("TLS");
//参数,添加受信任证书和生成随机数
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
//获得scoket工厂
return sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 信任所有的证书
*/
private static SSLSocketFactory getTrustAllSocketFactory() {
X509TrustManager xtm = getUnSafeTrustManager();
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{xtm}, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (KeyManagementException e) {
e.printStackTrace();
return null;
}
return sslContext.getSocketFactory();
}
private static void checkNetProxy() {
//代理服务检测
if(System.getProperty("http.proxyHost") != null || System.getProperty("http.proxyPort") != null) {
//正常情况下这两个返回值是null,如果发现不为空那么就表示当前设备被挂代理了,那么就有可能被抓包的风险了
ToastHelper.Companion.show("当前设备正在使用代理服务,请注意应用安全");
}
}
public static SafeTrustManager getSafeTrustManager(){
return new SafeTrustManager();
}
public static UnSafeTrustManager getUnSafeTrustManager(){
return new UnSafeTrustManager();
}
public static class UnSafeTrustManager implements X509TrustManager{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException{}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException{}
@Override
public X509Certificate[] getAcceptedIssuers(){
return new X509Certificate[]{};
}
}
public static class SafeTrustManager implements X509TrustManager{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException{}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException{
for (X509Certificate cert : chain) {
cert.checkValidity();
try {
cert.verify(cert.getPublicKey());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
}
}
@Override
public X509Certificate[] getAcceptedIssuers(){
return new X509Certificate[0];
}
}
}
package com.yidianling.ydlcommon.custom.http
import com.yidianling.common.tools.LogUtil
/**
* @author yuanwai
* @描述:自定义错误信息
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/30
*/
public open class YDLThrowable(val msg: String?, val throwable: YDLThrowable?, val urlParam: String?, val errorCode: Int?) : Throwable(msg!!, throwable!!) {
constructor() : this("",null,"",-1)
constructor(message: String?) : this(message, null, "", -1)
constructor(message: String?, thro: YDLThrowable?) : this(message, thro, "", -1)
constructor(message: String?, thro: YDLThrowable?, urlParams: String?) : this(message, thro, urlParams, -1)
init {
LogUtil.e("http-----------$urlParam----errorcode=$errorCode---msg=$msg")
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http;
import android.content.Context;
import android.util.Log;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.google.gson.JsonParseException;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.common.tools.RxAppTool;
import com.yidianling.common.tools.RxDeviceTool;
import com.yidianling.common.tools.ToastUtil;
import com.yidianling.ydlcommon.BuildConfig;
import com.yidianling.ydlcommon.R;
import com.yidianling.ydlcommon.custom.data.YdlDataManager;
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager;
import com.yidianling.ydlcommon.custom.router.YdlUserInfo;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import retrofit2.HttpException;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import javax.net.ssl.SSLSocketFactory;
import java.io.File;
import java.lang.reflect.Field;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 网络请求
* 根据不同请求返回不同的Call
*/
public class YdlRetrofitUtils {
public static String YDL_H5 = BuildConfig.YDL_H5_URL;
public static String POST = BuildConfig.SERVER_URL;
public static String BASE_JAVA_URL = BuildConfig.SERVER_JAVA_URL;
public static String H5_URL = BuildConfig.H5_URL;
public static String MH5_URL = BuildConfig.MH5_URL;
public static String WEB_URL = BuildConfig.WEB_URL;
public static String SERVER_COUPON_URL = BuildConfig.SERVER_COUPON_JAVA_URL;
public static String SERVER_TEMP_JAVA_URL = BuildConfig.SERVER_TEMP_JAVA_URL;
public static String SERVER_API_JAVA_URL = BuildConfig.SERVER_JAVA_API_URL;
public static String ACTION_URL = BuildConfig.ACTION_URL;
private static final int DEFAULT_TIMEOUT = 15;
private static final String AUTHORIZATION_NAME = "Authorization";
private static final String SESSION_KEY_DEFAULT_VALUE = "dc59cf294f37d237c1f06240568ffe21";
private static Retrofit retrofit;
public static final String M_BASE_URL = "http://m.ydl.com/";//m站的baseUrl
private static final String UID = "uid";
private static final String FFROM = "ffrom";
private static final String IS_FROM_APP = "isFromApp";
private static final String OS_BUILD = "osBuild";
private static final String TS = "ts";
private static final String VERSION = "version";
private static final String TOKEN = "accessToken";
private static final String OS_TYPE = "osType";// 1.ios 2.android
private static final String APP_NAME = "appName";//用于标识 是哪个应用 yidianling:用户版 xinlizixun:心理咨询 haoshi:情感壹点灵 zhuanjia:专家版
public static void handleError(Context context, Throwable t) {
t.printStackTrace();
if (t instanceof SocketTimeoutException || t instanceof UnknownHostException || t instanceof HttpException) {
if (context != null) {
ToastUtil.toastShort(context.getString(R.string.network_error));
}
} else if (t instanceof JsonParseException) {
if (context != null) {
ToastUtil.toastShort(context.getString(R.string.gson_parse_error));
}
} else {
// ToastUtil.toastShort(context, t.getMessage());
LogUtil.e(t.toString());
}
}
//根据不同的请求获取不同的请求头(RxJava)
public static Retrofit getRxRetrofit() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(POST)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(getOkHttp())
.build();
}
return retrofit;
}
/**
* 销毁时调用
*/
public static void clearRxRetrofit() {
retrofit = null;
}
//获取网络请求表
public static Map<String, String> getMaps(BaseCommand cmd) {
Map<String, String> map = new HashMap<>();
List<FormatText> list = getPostList(cmd);
int size = list.size();
for (int i = 0; i < size; i++) {
FormatText formatText = list.get(i);
map.put(formatText.getmKey(), String.valueOf(formatText.getmValue()));
}
return map;
}
//获取文件传输网络请求表
@SuppressWarnings("unused")
public static Map<String, RequestBody> getFileMaps(BaseCommand cmd, String key, File[] files) {
Map<String, RequestBody> map = new TreeMap<>();
List<FormatText> list = getPostList(cmd);
int size = list.size();
for (int i = 0; i < size; i++) {
FormatText formatText = list.get(i);
// RequestBody rb = RequestBody.create(MediaType.parse("multipart/form-data"),list.get(i).getmValue());
RequestBody rb = RequestBody.create(MediaType.parse("text/plain"), String.valueOf(list.get(i).getmValue()));
map.put(formatText.getmKey(), rb);
}
if (files != null && files.length > 0) {
if (files.length == 1) {
if (files[0] != null) {
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), files[0]);
map.put(key + "\"; filename=\"" + files[0].getName() + "", fileBody);
}
} else {
for (int i = 0; i < files.length; i++) {
if (files[i] != null) {
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), files[i]);
map.put(key + i + "\"; filename=\"" + files[i].getName() + "", fileBody);
}
}
}
}
return map;
}
//获取网络请求表
private static Map<String, RequestBody> getFileMaps(List<FormatText> list, String key, File[] file) {
Map<String, RequestBody> map = new TreeMap<>();
int size = list.size();
for (int i = 0; i < size; i++) {
FormatText formatText = list.get(i);
// RequestBody rb = RequestBody.create(MediaType.parse("multipart/form-data"),list.get(i).getmValue());
RequestBody rb = RequestBody.create(MediaType.parse("text/plain"), String.valueOf(list.get(i).getmValue()));
map.put(formatText.getmKey(), rb);
}
if (file != null && file.length > 0) {
if (file.length == 1) {
if (file[0] != null) {
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file[0]);
map.put(key + "\"; filename=\"" + file[0].getName() + "", fileBody);
}
} else {
for (int i = 0; i < file.length; i++) {
if (file[i] != null) {
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file[i]);
map.put(key + i + "\"; filename=\"" + file[i].getName() + "", fileBody);
}
}
}
}
return map;
}
//获取网络请求表
public static Map<String, String> getMaps(List<FormatText> list) {
Map<String, String> map = new HashMap<>();
int size = list.size();
for (int i = 0; i < size; i++) {
FormatText formatText = list.get(i);
map.put(formatText.getmKey(), String.valueOf(formatText.getmValue()));
}
return map;
}
/**
* 用于MD5加密
*
* @param clear 明文
* @return 密文
*/
private static String digestMD5(String clear) {
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'};
try {
byte[] strTemp = clear.getBytes("utf-8");
// 使用MD5创建MessageDigest对象
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(strTemp);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (byte b : md) {
// 将每个数(int)b进行双字节加密
str[k++] = hexDigits[b >> 4 & 0xf];
str[k++] = hexDigits[b & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
}
private static OkHttpClient getOkHttp() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.retryOnConnectionFailure(false);
try {
builder.addInterceptor(new PostCacheInterceptor(new DiskLruCacheHelper(BaseApplication.Companion.getApp())));
} catch (Exception e) {
}
builder.addInterceptor(chain -> {
RequestBody body = chain.request().body();
List<FormatText> list = new ArrayList<>();
if (body instanceof FormBody) {
FormBody formBody = (FormBody) body;
for (int i = 0; i < formBody.size(); i++) {
list.add(new FormatText(formBody.name(i), formBody.value(i)));
}
}
if (body instanceof MultipartBody) {
MultipartBody multipartBody = (MultipartBody) body;
List<MultipartBody.Part> parts = multipartBody.parts();
for (MultipartBody.Part part : parts) {
//noinspection ConstantConditions
if ("text/plain; charset=utf-8".equals(part.body().contentType().toString())) {
//noinspection ConstantConditions
String headerStr = part.headers().toString();
String name = headerStr.split("\"\\n")[0].split("=\"")[1];
Log.e("Tag","header="+headerStr+"--name="+name);
Buffer buffer = new Buffer();
part.body().writeTo(buffer);
String value = buffer.readUtf8();
list.add(new FormatText(name, value));
}
}
}
String head = "Ydl " + getSign(list);
LogUtil.i("RetrofitLog", "head = " + head);
Request.Builder build = chain.request()
.newBuilder()
.header(AUTHORIZATION_NAME, head)
.addHeader("Connection","close")
.addHeader(FFROM, YdlDataManager.INSTANCE.getRam().getChannelName())
.addHeader(IS_FROM_APP, "1")
.addHeader(VERSION, RxDeviceTool.getAppVersionName(BaseApplication.Companion.getApp()))
.addHeader(OS_BUILD, RxDeviceTool.getBuildMANUFACTURER() + "," + RxDeviceTool.getBuildBrandModel() + "," + RxDeviceTool.getOsBuileVersion() + "," + RxDeviceTool.getAppVersionName(BaseApplication.Companion.getApp()))
.addHeader(OS_TYPE,"2")
.addHeader(APP_NAME,"yidianling");
YdlUserInfo loginBean = YdlCommonRouterManager.INSTANCE.getYdlCommonRoute().getUserInfo();
if (loginBean != null) {
build.addHeader(TOKEN, loginBean.getToken())
.addHeader(UID, loginBean.getUserId());
}
return chain.proceed(build.build());
});
if (BuildConfig.DEBUG) {
builder.addInterceptor(new HttpLoggingInterceptor(message -> {
//打印retrofit日志
LogUtil.i("RetrofitLog", "retrofitBack = " + message);
}).setLevel(HttpLoggingInterceptor.Level.BODY));
builder.addNetworkInterceptor(new StethoInterceptor());
}
//使用自定义SSLSocketFactory
SSLSocketFactory factory = YDLSSLFactory.getSocketFactory();
if (factory != null) {
//noinspection deprecation
builder.sslSocketFactory(factory)
.hostnameVerifier((hostname, session) -> true
);
}
builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
return builder.build();
}
//获取请求头签名
private static String getSign(List<FormatText> list) {
//将请求参数倒序排列
Collections.sort(list, new SortData());
StringBuilder stringBuilder = new StringBuilder();
int size = list.size();
for (int i = 0; i < size; i++) {
FormatText formatText = list.get(i);
if (i != 0) {
stringBuilder.append("&");
}
stringBuilder.append(String.format("%s=%s", formatText.getmKey(), formatText.getmValue()));
}
stringBuilder.append(SESSION_KEY_DEFAULT_VALUE);
return digestMD5(stringBuilder.toString());
}
public static String getCommonParam() {
StringBuffer sb = new StringBuffer();
YdlUserInfo userInfo = YdlCommonRouterManager.INSTANCE.getYdlCommonRoute().getUserInfo();
sb.append(FFROM).append("=").append(YdlDataManager.INSTANCE.getRam().getChannelName())
.append("&").append(IS_FROM_APP).append("=").append("1")
.append("&").append(OS_BUILD).append("=").append(RxDeviceTool.getBuildBrandModel()).append(",").append(RxDeviceTool.getSDKVersionName()).append(",").append(RxAppTool.getAppVersionName(BaseApplication.Companion.getApp()))
.append("&").append(TS).append("=").append(System.currentTimeMillis() / 1000)
.append("&").append(VERSION).append("=").append(RxAppTool.getAppVersionName(BaseApplication.Companion.getApp()));
if (null != userInfo) {
sb.append("&").append(UID).append("=").append(userInfo.getUserId())
.append("&").append(TOKEN).append("=").append(userInfo.getToken());
}
return sb.toString();
}
//用来命名排序规则的
static class SortData implements Comparator<FormatText> {
@Override
public int compare(FormatText lhs, FormatText rhs) {
int res = lhs.getmKey().compareTo(rhs.getmKey());
if (res == 0) {
return 0;
}
return res > 0 ? -1 : 1;
}
}
public static List<FormatText> getPostList(BaseCommand crq) {
List<FormatText> formTextList = new ArrayList<>();
Field[] fields = crq.getClass().getFields();
for (Field field : fields) {
try {
boolean accessFlag = field.isAccessible();
field.setAccessible(true);
Object o = field.get(crq);
if (o != null) {
FormatText formatText;
formatText = new FormatText(field.getName(), String.valueOf(o));
formTextList.add(formatText);
}
field.setAccessible(accessFlag);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return formTextList;
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.http.api; package com.yidianling.ydlcommon.custom.http.api;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.yidianling.ydlcommon.custom.data.MustUP; import com.ydl.ydlnet.YDLHttpUtils;
import com.yidianling.ydlcommon.custom.bean.MustUP;
import com.yidianling.ydlcommon.custom.http.BaseAPIResponse; import com.yidianling.ydlcommon.custom.http.BaseAPIResponse;
import com.yidianling.ydlcommon.custom.http.BaseResponse; import com.yidianling.ydlcommon.custom.http.BaseResponse;
import com.yidianling.ydlcommon.custom.http.FormatText; import com.yidianling.ydlcommon.custom.http.FormatText;
import com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils;
import com.yidianling.ydlcommon.custom.http.params.ActionDataBean; import com.yidianling.ydlcommon.custom.http.params.ActionDataBean;
import com.yidianling.ydlcommon.custom.utils.NetworkParamsUtils;
import io.reactivex.Observable; import io.reactivex.Observable;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.RequestBody; import okhttp3.RequestBody;
...@@ -21,24 +22,14 @@ import java.util.List; ...@@ -21,24 +22,14 @@ import java.util.List;
public class ApiRequestUtil { public class ApiRequestUtil {
//强制更新埋点 //强制更新埋点
public static Observable<BaseResponse<MustUP>> appWillUp(Command.APPWillUp cmd) { public static Observable<BaseResponse<MustUP>> appWillUp(Command.APPWillUp cmd) {
List<FormatText> list = YdlRetrofitUtils.getPostList(cmd); List<FormatText> list = NetworkParamsUtils.getPostList(cmd);
return YdlRetrofitUtils.getRxRetrofit().create(NetApiStore.class).appWillUp(YdlRetrofitUtils.getMaps(list)); return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).appWillUp(NetworkParamsUtils.getMaps(list));
} }
//上传错误日志信息 //上传错误日志信息
public static Observable<BaseResponse> upLoadLoginStatus(Command.upLoadLoginStatus cmd) { public static Observable<BaseResponse> upLoadLoginStatus(Command.upLoadLoginStatus cmd) {
List<FormatText> list = YdlRetrofitUtils.getPostList(cmd); List<FormatText> list = NetworkParamsUtils.getPostList(cmd);
return YdlRetrofitUtils.getRxRetrofit().create(NetApiStore.class).upLoadLoginStatus(YdlRetrofitUtils.getMaps(list)); return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).upLoadLoginStatus(NetworkParamsUtils.getMaps(list));
}
/**
* 上传webview初始化及加载url时间接口
*
* @param param
* @return
*/
public static Observable<BaseResponse> uploadWebViewTime(String param) {
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), param);
return YdlRetrofitUtils.getRxRetrofit().newBuilder().baseUrl(YdlRetrofitUtils.SERVER_TEMP_JAVA_URL).build().create(NetApiStore.class).uploadWebViewTime(body);
} }
/** /**
...@@ -46,6 +37,6 @@ public class ApiRequestUtil { ...@@ -46,6 +37,6 @@ public class ApiRequestUtil {
*/ */
public static Observable<BaseAPIResponse<String>> actionDataCount(ActionDataBean actionDataParams) { public static Observable<BaseAPIResponse<String>> actionDataCount(ActionDataBean actionDataParams) {
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), new Gson().toJson(actionDataParams)); RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), new Gson().toJson(actionDataParams));
return YdlRetrofitUtils.getRxRetrofit().newBuilder().baseUrl(YdlRetrofitUtils.ACTION_URL).build().create(NetApiStore.class).actionDataCount(body); return YDLHttpUtils.Companion.obtainApi(NetApiStore.class).actionDataCount(body);
} }
} }
package com.yidianling.ydlcommon.custom.http.api; package com.yidianling.ydlcommon.custom.http.api;
import com.yidianling.ydlcommon.custom.data.MustUP; import com.yidianling.ydlcommon.custom.bean.MustUP;
import com.yidianling.ydlcommon.custom.http.BaseAPIResponse; import com.yidianling.ydlcommon.custom.http.BaseAPIResponse;
import com.yidianling.ydlcommon.custom.http.BaseResponse; import com.yidianling.ydlcommon.custom.http.BaseResponse;
import io.reactivex.Observable; import io.reactivex.Observable;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import retrofit2.http.Body; import retrofit2.http.*;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
import java.util.Map; import java.util.Map;
import static com.yidianling.ydlcommon.core.base.config.AppConfigKt.YDL_DOMAIN;
import static com.yidianling.ydlcommon.core.base.config.AppConfigKt.YDL_DOMAIN_JAVA;
/** /**
* 网络请求api * 网络请求api
* Created by Emma on 2016/8/23. * Created by Emma on 2016/8/23.
...@@ -27,12 +27,9 @@ interface NetApiStore { ...@@ -27,12 +27,9 @@ interface NetApiStore {
@FormUrlEncoded @FormUrlEncoded
Observable<BaseResponse> upLoadLoginStatus(@FieldMap Map<String, String> maps); Observable<BaseResponse> upLoadLoginStatus(@FieldMap Map<String, String> maps);
//上传webview初始化及加载url时间接口
@POST("slowlog/h5")
Observable<BaseResponse> uploadWebViewTime(@Body RequestBody body);
//行为动作埋点统计接口 //行为动作埋点统计接口
@POST("maidian/writeMaiDianData") @Headers(YDL_DOMAIN+ YDL_DOMAIN_JAVA)
@POST("data/bigdata/maidian/writeMaiDianData")
Observable<BaseAPIResponse<String>> actionDataCount(@Body RequestBody body); Observable<BaseAPIResponse<String>> actionDataCount(@Body RequestBody body);
} }
package com.yidianling.ydlcommon.custom.mvp
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*
* 基础 presenter 类,初始化 view 和 model
* 泛型分别为 view 类型和 model 类型
*/
abstract class BasePresenter<V: MVPView, out M: MVPModel>(val view: V):
MVPPresenter<V, M> {
protected val model: M by lazy { createModel() }
override fun onViewDestroy() { }
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.mvp
import com.yidianling.ydlcommon.custom.base.BaseActivity
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*
* 使用 mvp 的 Activity
*/
abstract class MVPActivity<out P: MVPPresenter<*, *>>: BaseActivity(),
MVPView {
protected val presenter: P by lazy { createPresenter() }
override fun onDestroy() {
super.onDestroy()
presenter.onViewDestroy()
}
protected abstract fun createPresenter(): P
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.mvp
import com.yidianling.ydlcommon.custom.base.BaseFragment
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*
* 使用 mvp 的 Fragment
*/
abstract class MVPFragment<out P: MVPPresenter<*, *>>: BaseFragment(),
MVPView {
protected val presenter by lazy { createPresenter() }
override fun onDestroy() {
super.onDestroy()
presenter.onViewDestroy()
}
protected abstract fun createPresenter(): P
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.mvp
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
* 基础 model 接口
*/
interface MVPModel
\ No newline at end of file
package com.yidianling.ydlcommon.custom.mvp
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*
* 基础 presenter 接口,泛型分别为 view 类型和 model 类型
*/
interface MVPPresenter<in V: MVPView, out M: MVPModel> {
fun createModel(): M
fun onViewDestroy()
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.mvp
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*
* 基础 view 接口
*/
interface MVPView
\ No newline at end of file
package com.yidianling.ydlcommon.custom.mvp
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/01/29
*
* 用于 Rx
*/
abstract class RxPresenter<V: MVPView, out M: MVPModel>(view: V): BasePresenter<V, M>(view) {
private val compositeDisposable: CompositeDisposable by lazy { CompositeDisposable() }
override fun onViewDestroy() {
super.onViewDestroy()
clearDisposable()
}
fun addDisposable(d: Disposable) {
compositeDisposable.add(d)
}
fun removeDisposable(d: Disposable) {
compositeDisposable.remove(d)
}
private fun clearDisposable() {
compositeDisposable.clear()
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.notification
import android.app.Notification
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import android.support.v4.content.ContextCompat
import android.widget.RemoteViews
import com.bumptech.glide.request.RequestOptions
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydl_image.target.YDLNotificationTarget
import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.common.tools.LogUtil
import com.yidianling.ydlcommon.R
class MusicPlayerService : Service() {
companion object {
val TAG = MusicPlayerService::class.java.simpleName!!
val ACTION_PLAY = "play"
val ACTION_PAUSE = "pause"
val ACTION_STOP = "stop"
val ACTION_DETAIL = "detail"
val REQUEST_CODE = 100
fun startServiceFromCourse(context: Context,playType:String,headUrl:String?,title:String?){
var i=Intent(context, MusicPlayerService::class.java)
i.putExtra("play_type",playType)
i.putExtra("head_url",headUrl)
i.putExtra("title",title)
context.startService(i)
}
}
// private var coursePlayer = CoursePlayer2
// private val myPlayer = MyPlayer.getInstance()
private var playType: String? = null
override fun onBind(intent: Intent): IBinder? = null
@Suppress("DEPRECATION")
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
LogUtil.d(TAG, "onStartCommand")
playType = intent?.getStringExtra("play_type")
val remoteViews = createRemoteViews()
val builder = Notification.Builder(applicationContext)
.setContent(remoteViews)
.setSmallIcon(R.drawable.ic_music_not) // 设置状态栏内的小图标
.setWhen(System.currentTimeMillis()) // 设置该通知发生的时间
val notification = builder.build() // 获取构建好的Notification
val target = YDLNotificationTarget(BaseApplication.getApp(), R.id.iv_head, remoteViews, notification, 110)
if (playType == "course") {
val headUrl=intent?.getStringExtra("head_url")
val title=intent?.getStringExtra("title")
GlideApp.with(this)
.asBitmap()
.load(headUrl)
.apply(RequestOptions.centerCropTransform())
.into(target)
// GlideApp.with(this)
// .asBitmap()
// .load(headUrl)
//// .apply(RequestOptions.centerCropTransform())
// .into(target)
remoteViews.setTextViewText(R.id.tv_title, title)
if (PlayerState.isCoursePlaying()) {
val intentPause = Intent(ACTION_PAUSE)
intentPause.putExtra("play_type", playType)
val pIntentPause = PendingIntent.getBroadcast(applicationContext,
REQUEST_CODE, intentPause, PendingIntent.FLAG_UPDATE_CURRENT)
remoteViews.setOnClickPendingIntent(R.id.btn_pause_play, pIntentPause)
remoteViews.setImageViewResource(R.id.btn_pause_play, R.drawable.ic_pause_24dp)
} else {
val intentPlay = Intent(ACTION_PLAY)
intentPlay.putExtra("play_type", playType)
val pIntentPlay = PendingIntent.getBroadcast(applicationContext,
REQUEST_CODE, intentPlay, PendingIntent.FLAG_UPDATE_CURRENT)
remoteViews.setOnClickPendingIntent(R.id.btn_pause_play, pIntentPlay)
remoteViews.setImageViewResource(R.id.btn_pause_play, R.drawable.ic_play_24dp)
}
} else {
// GlideApp.with(this)
// .asBitmap()
// .load(myPlayer.cover)
// .centerCrop()
// .into(target)
// remoteViews.setTextViewText(R.id.tv_title, myPlayer.title)
// if (myPlayer.isPlaying) {
// val intentPause = Intent(ACTION_PAUSE)
// intentPause.putExtra("play_type", playType)
// val pIntentPause = PendingIntent.getBroadcast(applicationContext, REQUEST_CODE, intentPause, PendingIntent.FLAG_UPDATE_CURRENT)
// remoteViews.setOnClickPendingIntent(R.id.btn_pause_play, pIntentPause)
// remoteViews.setImageViewResource(R.id.btn_pause_play, R.mipmap.ic_pause_24dp)
// } else {
// val intentPlay = Intent(ACTION_PLAY)
// intentPlay.putExtra("play_type", playType)
// val pIntentPlay = PendingIntent.getBroadcast(applicationContext, REQUEST_CODE, intentPlay, PendingIntent.FLAG_UPDATE_CURRENT)
// remoteViews.setOnClickPendingIntent(R.id.btn_pause_play, pIntentPlay)
// remoteViews.setImageViewResource(R.id.btn_pause_play, R.mipmap.ic_play_24dp)
// }
}
startForeground(110, notification)
return START_STICKY
}
private fun createRemoteViews(): RemoteViews {
val remoteViews = RemoteViews(packageName, R.layout.ui_music_notification)
val intentStop = Intent(ACTION_STOP)
intentStop.putExtra("play_type", playType)
val pIntentStop = PendingIntent.getBroadcast(applicationContext,
REQUEST_CODE, intentStop, PendingIntent.FLAG_UPDATE_CURRENT)
remoteViews.setOnClickPendingIntent(R.id.btn_close, pIntentStop)
val intentDetail = Intent(ACTION_DETAIL)
intentDetail.putExtra("play_type", playType)
val pIntentDetail = PendingIntent.getBroadcast(applicationContext,
REQUEST_CODE, intentDetail, PendingIntent.FLAG_UPDATE_CURRENT)
remoteViews.setOnClickPendingIntent(R.id.iv_head, pIntentDetail)
remoteViews.setOnClickPendingIntent(R.id.tv_title, pIntentDetail)
val color = getColor()
remoteViews.setTextColor(R.id.tv_title, color)
return remoteViews
}
private fun getColor(): Int {
var color = ContextCompat.getColor(BaseApplication.getApp(), R.color.default_text_color)
val tempColor =
com.yidianling.ydlcommon.custom.notification.NotificationHelper.getNotificationColor(BaseApplication.getApp())
if (tempColor != com.yidianling.ydlcommon.custom.notification.NotificationHelper.INVALID_COLOR) {
color = tempColor
}
return color
}
override fun onDestroy() {
stopForeground(true)
super.onDestroy()
}
}
package com.yidianling.ydlcommon.custom.notification;
import android.app.Notification;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import com.yidianling.common.tools.LogUtil;
import java.util.ArrayList;
import java.util.List;
/**
* 获取通知字体颜色
* Created by zqk on 17-11-15.
*/
public class NotificationHelper {
private static final String NOTIFICATION_TITLE = "notification_title";
public static final int INVALID_COLOR = -1; // 无效颜色
private static int notificationTitleColor = INVALID_COLOR; // 获取到的颜色缓存
/**
* 获取系统通知栏主标题颜色,根据Activity继承自AppCompatActivity或FragmentActivity采取不同策略。
*
* @param context 上下文环境
* @return 系统主标题颜色
*/
public static int getNotificationColor(Context context) {
try {
if (notificationTitleColor == INVALID_COLOR) {
if (context instanceof AppCompatActivity) {
notificationTitleColor = getNotificationColorCompat(context);
} else {
notificationTitleColor = getNotificationColorInternal(context);
}
}
} catch (Exception ignored) {
}
return notificationTitleColor;
}
/**
* 通过一个空的Notification拿到Notification.lceContentView,通过{@link RemoteViews#apply(Context, ViewGroup)}方法返回通知栏消息根布局实例。
*
* @param context 上下文
* @return 系统主标题颜色
*/
private static int getNotificationColorInternal(Context context) {
Notification.Builder builder = new Notification.Builder(context);
builder.setContentTitle(NOTIFICATION_TITLE);
Notification notification = builder.build();
try {
ViewGroup root = (ViewGroup) notification.contentView.apply(context, new FrameLayout(context));
TextView titleView = (TextView) root.findViewById(android.R.id.title);
if (null == titleView) {
iteratorView(root, view -> {
if (view instanceof TextView) {
TextView textView = (TextView) view;
if (NOTIFICATION_TITLE.equals(textView.getText().toString())) {
notificationTitleColor = textView.getCurrentTextColor();
}
}
});
return notificationTitleColor;
} else {
return titleView.getCurrentTextColor();
}
} catch (Exception e) {
LogUtil.e(e.getMessage());
return getNotificationColorCompat(context);
}
}
/**
* 使用getNotificationColorInternal()方法,Activity不能继承自AppCompatActivity(实测5.0以下机型可以,5.0及以上机型不行),
* 大致的原因是默认通知布局文件中的ImageView(largeIcon和smallIcon)被替换成了AppCompatImageView,
* 而在5.0及以上系统中,AppCompatImageView的setBackgroundResource(int)未被标记为RemotableViewMethod,导致apply时抛异常。
*
* @param context 上下文
* @return 系统主标题颜色
*/
private static int getNotificationColorCompat(Context context) {
try {
Notification.Builder builder = new Notification.Builder(context);
Notification notification = builder.build();
int layoutId = notification.contentView.getLayoutId();
ViewGroup root = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null);
TextView titleView = (TextView) root.findViewById(android.R.id.title);
if (null == titleView) {
return getTitleColorIteratorCompat(root);
} else {
return titleView.getCurrentTextColor();
}
} catch (Exception e) {
}
return INVALID_COLOR;
}
private static void iteratorView(View view, Filter filter) {
if (view == null || filter == null) {
return;
}
filter.filter(view);
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
iteratorView(child, filter);
}
}
}
private static int getTitleColorIteratorCompat(View view) {
if (view == null) {
return INVALID_COLOR;
}
List<TextView> textViews = getAllTextViews(view);
int maxTextSizeIndex = findMaxTextSizeIndex(textViews);
if (maxTextSizeIndex != Integer.MIN_VALUE) {
return textViews.get(maxTextSizeIndex).getCurrentTextColor();
}
return INVALID_COLOR;
}
private static int findMaxTextSizeIndex(List<TextView> textViews) {
float max = Integer.MIN_VALUE;
int maxIndex = Integer.MIN_VALUE;
int index = 0;
for (TextView textView : textViews) {
if (max < textView.getTextSize()) {
// 找到字号最大的字体,默认把它设置为主标题字号大小
max = textView.getTextSize();
maxIndex = index;
}
index++;
}
return maxIndex;
}
/**
* 实现遍历View树中的TextView,返回包含TextView的集合。
*
* @param root 根节点
* @return 包含TextView的集合
*/
private static List<TextView> getAllTextViews(View root) {
final List<TextView> textViews = new ArrayList<>();
iteratorView(root, view -> {
if (view instanceof TextView) {
textViews.add((TextView) view);
}
});
return textViews;
}
private interface Filter {
void filter(View view);
}
}
package com.yidianling.ydlcommon.custom.notification
/**
* Created by Jim on 2018/3/9 0009.
*/
object PlayerState : PlayerStateObserver() {
private var coursePlayerState: Int = 0
private var fmPlayerState: Int = 0
override fun updateFMPayerState() {
}
override fun updateCoursePayerState(state: Int?) {
if (state!=null){
coursePlayerState =state
}else{
coursePlayerState ==-1
}
}
fun isCoursePlaying():Boolean{
return coursePlayerState == CURRENT_STATE_PLAYING
}
fun isFmPlaying():Boolean{
return fmPlayerState == IS_FM_PLAYING
}
}
package com.yidianling.ydlcommon.custom.notification
import java.util.*
/**
* Created by Jim on 2018/3/9 0009.
*/
abstract class PlayerStateObervable {
protected var mObservers: ArrayList<PlayerStateObserver> = ArrayList()
abstract fun registerObervers(observer: PlayerStateObserver)
abstract fun updateObervers(state: Int?)
}
package com.yidianling.ydlcommon.custom.notification
/**
* Created by Jim on 2018/3/9 0009.
*/
abstract class PlayerStateObserver {
abstract fun updateCoursePayerState(state: Int?)
abstract fun updateFMPayerState()
companion object {
val IS_FM_PLAYING = 1
val IS_FM_PAUSE = 2
val IS_FM_STOP = 3
val CURRENT_STATE_NORMAL = 0
val CURRENT_STATE_PREPARING = 1
val CURRENT_STATE_PREPARING_CHANGING_URL = 2
val CURRENT_STATE_PLAYING = 3
val CURRENT_STATE_PAUSE = 5
val CURRENT_STATE_AUTO_COMPLETE = 6
val CURRENT_STATE_ERROR = 7
}
}
package com.yidianling.ydlcommon.custom.notification;
public class UpdatePlayStatusEvent {
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.notification;
/**
* Created by zqk on 17-11-15.
*/
public class UpdateSafeTipViewEvent {
}
...@@ -12,19 +12,19 @@ import android.view.Gravity ...@@ -12,19 +12,19 @@ import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.base.BaseActivity import com.yidianling.ydlcommon.core.base.BaseActivity
import com.yidianling.ydlcommon.custom.data.YdlDataManager import com.yidianling.ydlcommon.custom.data.PlatformDataManager
import com.yidianling.ydlcommon.custom.http.RxUtils import com.yidianling.ydlcommon.custom.http.RxUtils
import com.yidianling.ydlcommon.custom.http.ThrowableConsumer import com.yidianling.ydlcommon.custom.http.ThrowableConsumer
import com.yidianling.ydlcommon.custom.http.params.* import com.yidianling.ydlcommon.custom.http.params.*
import com.yidianling.ydlcommon.custom.http.response.TestAddOrderBean import com.yidianling.ydlcommon.custom.http.response.TestAddOrderBean
import com.yidianling.ydlcommon.custom.log.LogHelper import com.yidianling.ydlcommon.custom.utils.log.LogHelper
import com.yidianling.ydlcommon.custom.pay.PayParams.CREATOR.INLET_NORMAL import com.yidianling.ydlcommon.custom.pay.PayParams.CREATOR.INLET_NORMAL
import com.yidianling.ydlcommon.custom.pay.PayParams.CREATOR.INLET_TEST import com.yidianling.ydlcommon.custom.pay.PayParams.CREATOR.INLET_TEST
import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketBean import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketBean
import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketPayBean import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketPayBean
import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketPopWindow import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketPopWindow
import com.yidianling.ydlcommon.custom.remind.ToastHelper import com.yidianling.ydlcommon.custom.utils.remind.ToastHelper
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
...@@ -256,7 +256,7 @@ internal class PayActivity : BaseActivity() { ...@@ -256,7 +256,7 @@ internal class PayActivity : BaseActivity() {
* 请求账户余额接口 * 请求账户余额接口
*/ */
private fun requestMyBalance() { private fun requestMyBalance() {
YdlDataManager.getHttp().getBalance( PlatformDataManager.getHttp().getBalance(
BalanceParam( BalanceParam(
1 1
) )
...@@ -308,7 +308,7 @@ internal class PayActivity : BaseActivity() { ...@@ -308,7 +308,7 @@ internal class PayActivity : BaseActivity() {
* 设置付款保障文案 * 设置付款保障文案
*/ */
private fun setPaymentText() { private fun setPaymentText() {
val globalInfo = YdlDataManager.getRam().getGlobalInfo() val globalInfo = PlatformDataManager.getRam().getGlobalInfo()
if (globalInfo != null) { if (globalInfo != null) {
tv_hint_title.text = globalInfo.info.pay_notice.title tv_hint_title.text = globalInfo.info.pay_notice.title
tv_hint_content.text = globalInfo.info.pay_notice.content.replace("<br>", "\n") tv_hint_content.text = globalInfo.info.pay_notice.content.replace("<br>", "\n")
...@@ -556,7 +556,7 @@ internal class PayActivity : BaseActivity() { ...@@ -556,7 +556,7 @@ internal class PayActivity : BaseActivity() {
if (null == redPacketPayBean || null == redPacketPayBean!!.payParams) { if (null == redPacketPayBean || null == redPacketPayBean!!.payParams) {
return return
} }
YdlDataManager.getHttp().addOrder( PlatformDataManager.getHttp().addOrder(
AddOrderParam( AddOrderParam(
redPacketPayBean!!.payParams.payId, redPacketPayBean!!.payParams.payId,
redPacketId!! redPacketId!!
...@@ -585,7 +585,7 @@ internal class PayActivity : BaseActivity() { ...@@ -585,7 +585,7 @@ internal class PayActivity : BaseActivity() {
if (null == payParams) { if (null == payParams) {
return return
} }
YdlDataManager.getHttp().recharge( PlatformDataManager.getHttp().recharge(
RechargeParam( RechargeParam(
payParams!!.needPay.toInt().toString() payParams!!.needPay.toInt().toString()
) )
...@@ -595,7 +595,7 @@ internal class PayActivity : BaseActivity() { ...@@ -595,7 +595,7 @@ internal class PayActivity : BaseActivity() {
.flatMap { .flatMap {
rechargeId = it.rechargeId rechargeId = it.rechargeId
when (select) { when (select) {
0 -> YdlDataManager.getHttp().wxRecharge( 0 -> PlatformDataManager.getHttp().wxRecharge(
WXRechargeIdParam( WXRechargeIdParam(
it.rechargeId it.rechargeId
) )
...@@ -608,7 +608,7 @@ internal class PayActivity : BaseActivity() { ...@@ -608,7 +608,7 @@ internal class PayActivity : BaseActivity() {
} }
} }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { showProgressDialog("") } .doOnSubscribe { showProgressDialog() }
.doAfterTerminate { dismissProgressDialog() } .doAfterTerminate { dismissProgressDialog() }
.subscribe(Consumer { .subscribe(Consumer {
LogHelper.getInstance().writeLogSync("支付成功") LogHelper.getInstance().writeLogSync("支付成功")
...@@ -651,7 +651,7 @@ internal class PayActivity : BaseActivity() { ...@@ -651,7 +651,7 @@ internal class PayActivity : BaseActivity() {
* @param payId 支付Id * @param payId 支付Id
*/ */
private fun balancePayById(payId: String) { private fun balancePayById(payId: String) {
YdlDataManager.getHttp().pay( PlatformDataManager.getHttp().pay(
BalancePayParam( BalancePayParam(
payId payId
) )
...@@ -691,7 +691,7 @@ internal class PayActivity : BaseActivity() { ...@@ -691,7 +691,7 @@ internal class PayActivity : BaseActivity() {
} }
} }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { showProgressDialog("") } .doOnSubscribe { showProgressDialog() }
.doAfterTerminate { dismissProgressDialog() } .doAfterTerminate { dismissProgressDialog() }
.subscribe(Consumer { .subscribe(Consumer {
LogHelper.getInstance().writeLogSync("支付成功") LogHelper.getInstance().writeLogSync("支付成功")
...@@ -733,7 +733,7 @@ internal class PayActivity : BaseActivity() { ...@@ -733,7 +733,7 @@ internal class PayActivity : BaseActivity() {
* @param payId 支付id * @param payId 支付id
*/ */
private fun wxPayById(payId: String): Observable<PayStatus> { private fun wxPayById(payId: String): Observable<PayStatus> {
return YdlDataManager.getHttp().wxPay(PayParam.WxPayParam(payId)) return PlatformDataManager.getHttp().wxPay(PayParam.WxPayParam(payId))
.compose(RxUtils.resultData()) .compose(RxUtils.resultData())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnNext { dismissProgressDialog() } .doOnNext { dismissProgressDialog() }
...@@ -768,7 +768,7 @@ internal class PayActivity : BaseActivity() { ...@@ -768,7 +768,7 @@ internal class PayActivity : BaseActivity() {
* @param payId 支付Id * @param payId 支付Id
*/ */
private fun aliPayById(payId: String): Observable<PayStatus> { private fun aliPayById(payId: String): Observable<PayStatus> {
return YdlDataManager.getHttp().aliPay(PayParam.AliPayParam(payId)) return PlatformDataManager.getHttp().aliPay(PayParam.AliPayParam(payId))
.compose(RxUtils.resultData()) .compose(RxUtils.resultData())
.flatMap { .flatMap {
when (inlet) { when (inlet) {
...@@ -788,7 +788,7 @@ internal class PayActivity : BaseActivity() { ...@@ -788,7 +788,7 @@ internal class PayActivity : BaseActivity() {
/** /**
* 显示加载中弹窗 * 显示加载中弹窗
*/ */
override fun showProgressDialog(str: String?) { fun showProgressDialog() {
if (dialog != null && dialog!!.isShowing) { if (dialog != null && dialog!!.isShowing) {
return return
} }
...@@ -814,7 +814,7 @@ internal class PayActivity : BaseActivity() { ...@@ -814,7 +814,7 @@ internal class PayActivity : BaseActivity() {
/** /**
* 隐藏加载中弹窗 * 隐藏加载中弹窗
*/ */
override fun dismissProgressDialog() { fun dismissProgressDialog() {
if (dialog != null && dialog!!.isShowing) { if (dialog != null && dialog!!.isShowing) {
dialog!!.dismiss() dialog!!.dismiss()
} }
......
...@@ -9,15 +9,14 @@ import android.support.v7.app.AlertDialog ...@@ -9,15 +9,14 @@ import android.support.v7.app.AlertDialog
import android.view.* import android.view.*
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.YdlBuryPointUtil import com.yidianling.ydlcommon.custom.YdlBuryPointUtil
import com.yidianling.ydlcommon.custom.data.YdlDataManager import com.yidianling.ydlcommon.custom.data.PlatformDataManager
import com.yidianling.ydlcommon.custom.h5.NewH5Activity
import com.yidianling.ydlcommon.custom.http.RxUtils import com.yidianling.ydlcommon.custom.http.RxUtils
import com.yidianling.ydlcommon.custom.http.params.PayParam import com.yidianling.ydlcommon.custom.http.params.PayParam
import com.yidianling.ydlcommon.custom.log.LogHelper
import com.yidianling.ydlcommon.custom.pay.PayStatus import com.yidianling.ydlcommon.custom.pay.PayStatus
import com.yidianling.ydlcommon.custom.pay.RxPay import com.yidianling.ydlcommon.custom.pay.RxPay
import com.yidianling.ydlcommon.custom.remind.ToastHelper import com.yidianling.ydlcommon.custom.utils.StringUtils
import com.yidianling.ydlcommon.custom.tool.StringUtils import com.yidianling.ydlcommon.custom.utils.log.LogHelper
import com.yidianling.ydlcommon.custom.utils.remind.ToastHelper
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
...@@ -82,9 +81,9 @@ class PayDialog : Dialog{ ...@@ -82,9 +81,9 @@ class PayDialog : Dialog{
if (data!=null){ if (data!=null){
text_title.text = data!!.payTitle?:"倾诉服务" text_title.text = data!!.payTitle?:"倾诉服务"
setFoodPrice("¥${com.yidianling.ydlcommon.custom.tool.StringUtils.save2Double(data?.orderPrice?:0.00)}") setFoodPrice("¥${StringUtils.save2Double(data?.orderPrice?:0.00)}")
setSaleText("-¥${com.yidianling.ydlcommon.custom.tool.StringUtils.save2Double(data?.coupnPrice?:0.00)}") setSaleText("-¥${StringUtils.save2Double(data?.coupnPrice?:0.00)}")
setAvliableMoney("-¥${com.yidianling.ydlcommon.custom.tool.StringUtils.save2Double(data?.avliableMoney?:0.00)}") setAvliableMoney("-¥${StringUtils.save2Double(data?.avliableMoney?:0.00)}")
setPayMoney() setPayMoney()
} }
} }
...@@ -147,7 +146,7 @@ class PayDialog : Dialog{ ...@@ -147,7 +146,7 @@ class PayDialog : Dialog{
if (price < 0.00){ if (price < 0.00){
price = 0.00 price = 0.00
} }
text_money.text = "¥${com.yidianling.ydlcommon.custom.tool.StringUtils.save2Double(price)}" text_money.text = "¥${StringUtils.save2Double(price)}"
}else{ }else{
text_money.text = "--" text_money.text = "--"
} }
...@@ -202,7 +201,7 @@ class PayDialog : Dialog{ ...@@ -202,7 +201,7 @@ class PayDialog : Dialog{
* @param payId 支付id * @param payId 支付id
*/ */
private fun wxPayById(payId: String): Observable<PayStatus> { private fun wxPayById(payId: String): Observable<PayStatus> {
return YdlDataManager.getHttp().wxPay(PayParam.WxPayParam(payId)) return PlatformDataManager.getHttp().wxPay(PayParam.WxPayParam(payId))
.compose(RxUtils.resultData()) .compose(RxUtils.resultData())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.flatMap { RxPay.wxPay(activity, it.option) } .flatMap { RxPay.wxPay(activity, it.option) }
...@@ -213,7 +212,7 @@ class PayDialog : Dialog{ ...@@ -213,7 +212,7 @@ class PayDialog : Dialog{
* @param payId 支付Id * @param payId 支付Id
*/ */
private fun aliPayById(payId: String): Observable<PayStatus> { private fun aliPayById(payId: String): Observable<PayStatus> {
return YdlDataManager.getHttp().aliPay(PayParam.AliPayParam(payId)) return PlatformDataManager.getHttp().aliPay(PayParam.AliPayParam(payId))
.compose(RxUtils.resultData()) .compose(RxUtils.resultData())
.flatMap { .flatMap {
RxPay.aliPay(activity, it.aliSign) RxPay.aliPay(activity, it.aliSign)
......
package com.yidianling.ydlcommon.custom.pay.redpacket.jump
import com.yidianling.ydlcommon.custom.mvp.MVPModel
import com.yidianling.ydlcommon.custom.mvp.MVPPresenter
import com.yidianling.ydlcommon.custom.mvp.MVPView
import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketBean
/**
* @author yuanWai
* @描述:跳转支付页面中间页约束类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/24
*/
interface IJumpPayContract {
interface View : MVPView {
/**
* 红包列表结果
* @param data 数据集
*/
fun couponResult(data : ArrayList<RedPacketBean>)
fun onError(t: Throwable?)
fun onFailed(msg: String?)
}
interface Presenter :
MVPPresenter<View, Model> {
/**
* 请求红包列表接口
*/
fun requestCoupon()
}
interface Model : MVPModel
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.pay.redpacket.jump
import android.app.Activity
import android.content.Context
import android.content.Intent
import com.yidianling.ydlcommon.custom.mvp.MVPActivity
import com.yidianling.ydlcommon.custom.pay.PayActivity
import com.yidianling.ydlcommon.custom.pay.PayParams
import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketBean
import com.yidianling.ydlcommon.custom.pay.redpacket.RedPacketPayBean
/**
* @author yuanWai
* @描述:跳转支付页 中间处理页 (目前只有测评模块调用)
* 这个页面会先掉红包接口 获取红包列表之后 在跳转支付页面 用来缓解 支付页调用太多接口等待不友好现象
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/24
*/
class JumpPayActivity : MVPActivity<IJumpPayContract.Presenter>(),
IJumpPayContract.View {
private var payParams : PayParams? = null
companion object {
private const val PARAM = "param"
fun start(context: Context,payParams: PayParams) {
val intent = Intent(context, JumpPayActivity::class.java)
intent.putExtra(PARAM,payParams)
context.startActivity(intent)
}
fun newIntent(context: Context,payParams: PayParams) : Intent{
return Intent(context, JumpPayActivity::class.java).putExtra(
PARAM,payParams)
}
}
override fun layoutResId(): Int {
return 0
}
override fun createPresenter(): IJumpPayContract.Presenter {
return JumpPayPresenterImpl(this)
}
//获取入参
private fun getParam(){
if (null == intent){
finish()
}
if (intent.hasExtra(PARAM)){
payParams = intent.getParcelableExtra(PARAM)
}
}
override fun initDataAndEvent() {
showProgressDialog()
getParam()
// 隐藏ActionBar
supportActionBar?.hide()
//请求红包列表接口
presenter.requestCoupon()
}
override fun couponResult(data: ArrayList<RedPacketBean>) {
dismissProgressDialog()
if (null == payParams){
jumpPay(
RedPacketPayBean(
PayParams(),
data
)
)
}else{
jumpPay(RedPacketPayBean(payParams!!, data))
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
setResult(Activity.RESULT_OK)
}
override fun onFailed(msg: String?) {
dismissProgressDialog()
if (null == payParams){
jumpPay(
RedPacketPayBean(
PayParams(),
ArrayList()
)
)
}else{
jumpPay(RedPacketPayBean(payParams!!, ArrayList()))
}
finish()
}
private fun jumpPay(data: RedPacketPayBean) {
startActivity(PayActivity.newIntent(this,data))
finish()
}
override fun onError(t: Throwable?) {
dismissProgressDialog()
if (null == payParams){
jumpPay(
RedPacketPayBean(
PayParams(),
ArrayList()
)
)
}else{
jumpPay(RedPacketPayBean(payParams!!, ArrayList()))
}
finish()
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.pay.redpacket.jump
/**
* @author yuanWai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/24
*/
class JumpPayModelImpl : IJumpPayContract.Model {
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.pay.redpacket.jump
import com.yidianling.ydlcommon.custom.data.YdlDataManager
import com.yidianling.ydlcommon.custom.http.RxUtils
import com.yidianling.ydlcommon.custom.http.ThrowableConsumer
import com.yidianling.ydlcommon.custom.mvp.RxPresenter
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
/**
* @author yuanwai
* @描述:测评首页逻辑实现类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
class JumpPayPresenterImpl (view: IJumpPayContract.View) :
RxPresenter<IJumpPayContract.View, IJumpPayContract.Model>(view),
IJumpPayContract.Presenter {
override fun createModel(): IJumpPayContract.Model {
return JumpPayModelImpl()
}
/**
* 请求红包列表
*/
override fun requestCoupon() {
YdlDataManager.getHttp().getCoupon()
.subscribeOn(Schedulers.io())
.compose(RxUtils.resultData())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
view.couponResult(it)
}, object : ThrowableConsumer() {
override fun accept(msg: String) {
view.onFailed(msg)
}
})
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.picker.util;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Base64;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.common.tools.RxDeviceTool;
import com.yidianling.common.tools.ToastUtil;
import com.yidianling.ydlcommon.R;
import com.yidianling.ydlcommon.custom.picker.util.file.AttachmentStore;
import com.yidianling.ydlcommon.custom.picker.util.file.FileUtil;
import com.yidianling.ydlcommon.custom.picker.util.media.BitmapDecoder;
import com.yidianling.ydlcommon.custom.picker.util.media.SampleSizeUtil;
import com.yidianling.ydlcommon.custom.picker.util.storage.StorageType;
import com.yidianling.ydlcommon.custom.picker.util.storage.StorageUtil;
import com.yidianling.ydlcommon.custom.tool.StringUtils;
import java.io.*;
import static com.yidianling.common.tools.RxImageTool.getImageType;
public class ImageUtil {
public static class ImageSize {
public int width = 0;
public int height = 0;
public ImageSize(int width, int height) {
this.width = width;
this.height = height;
}
}
public final static float MAX_IMAGE_RATIO = 5f;
public static Bitmap getDefaultBitmapWhenGetFail() {
try {
return getBitmapImmutableCopy(BaseApplication.Companion.getApp().getResources(), R.drawable.nim_image_download_failed);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static final Bitmap getBitmapImmutableCopy(Resources res, int id) {
return getBitmap(res.getDrawable(id)).copy(Config.RGB_565, false);
}
public static final Bitmap getBitmap(Drawable dr) {
if (dr == null) {
return null;
}
if (dr instanceof BitmapDrawable) {
return ((BitmapDrawable) dr).getBitmap();
}
return null;
}
public static Bitmap rotateBitmapInNeeded(String path, Bitmap srcBitmap) {
if (TextUtils.isEmpty(path) || srcBitmap == null) {
return null;
}
ExifInterface localExifInterface;
try {
localExifInterface = new ExifInterface(path);
int rotateInt = localExifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
float rotate = getImageRotate(rotateInt);
if (rotate != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
Bitmap dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
srcBitmap.getWidth(), srcBitmap.getHeight(), matrix,
false);
if (dstBitmap == null) {
return srcBitmap;
} else {
if (srcBitmap != null && !srcBitmap.isRecycled()) {
srcBitmap.recycle();
}
return dstBitmap;
}
} else {
return srcBitmap;
}
} catch (IOException e) {
e.printStackTrace();
return srcBitmap;
}
}
/**
* 获得旋转角度
*
* @param rotate
* @return
*/
public static float getImageRotate(int rotate) {
float f;
if (rotate == 6) {
f = 90.0F;
} else if (rotate == 3) {
f = 180.0F;
} else if (rotate == 8) {
f = 270.0F;
} else {
f = 0.0F;
}
return f;
}
public static String makeThumbnail(Context context, File imageFile) {
String thumbFilePath = StorageUtil.getWritePath(imageFile.getName(),
StorageType.TYPE_THUMB_IMAGE);
File thumbFile = AttachmentStore.create(thumbFilePath);
if (thumbFile == null) {
return null;
}
boolean result = scaleThumbnail(
imageFile,
thumbFile,
getImageMaxEdge(),
getImageMinEdge(),
CompressFormat.JPEG,
60);
if (!result) {
AttachmentStore.delete(thumbFilePath);
return null;
}
return thumbFilePath;
}
public static int getImageMaxEdge() {
return (int) (165.0 / 320.0 * RxDeviceTool.getScreenWidth(BaseApplication.Companion.getApp()));
}
public static int getImageMinEdge() {
return (int) (76.0 / 320.0 * RxDeviceTool.getScreenWidth(BaseApplication.Companion.getApp()));
}
public static Boolean scaleThumbnail(File srcFile, File dstFile, int dstMaxWH, int dstMinWH, CompressFormat compressFormat, int quality) {
Boolean bRet = false;
Bitmap srcBitmap = null;
Bitmap dstBitmap = null;
BufferedOutputStream bos = null;
try {
int[] bound = BitmapDecoder.decodeBound(srcFile);
ImageSize size = getThumbnailDisplaySize(bound[0], bound[1], dstMaxWH, dstMinWH);
srcBitmap = BitmapDecoder.decodeSampled(srcFile.getPath(), size.width, size.height);
// 旋转
ExifInterface localExifInterface = new ExifInterface(srcFile.getAbsolutePath());
int rotateInt = localExifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
float rotate = getImageRotate(rotateInt);
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
float inSampleSize = 1;
if (srcBitmap.getWidth() >= dstMinWH && srcBitmap.getHeight() <= dstMaxWH
&& srcBitmap.getWidth() >= dstMinWH && srcBitmap.getHeight() <= dstMaxWH) {
//如果第一轮拿到的srcBitmap尺寸都符合要求,不需要再做缩放
} else {
if (srcBitmap.getWidth() != size.width || srcBitmap.getHeight() != size.height) {
float widthScale = (float) size.width / (float) srcBitmap.getWidth();
float heightScale = (float) size.height / (float) srcBitmap.getHeight();
if (widthScale >= heightScale) {
size.width = srcBitmap.getWidth();
size.height /= widthScale;//必定小于srcBitmap.getHeight()
inSampleSize = widthScale;
} else {
size.width /= heightScale;//必定小于srcBitmap.getWidth()
size.height = srcBitmap.getHeight();
inSampleSize = heightScale;
}
}
}
matrix.postScale(inSampleSize, inSampleSize);
if (rotate == 0 && inSampleSize == 1) {
dstBitmap = srcBitmap;
} else {
dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, size.width, size.height, matrix, true);
}
bos = new BufferedOutputStream(new FileOutputStream(dstFile));
dstBitmap.compress(compressFormat, quality, bos);
bos.flush();
bRet = true;
} catch (OutOfMemoryError e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (srcBitmap != null && !srcBitmap.isRecycled()) {
srcBitmap.recycle();
srcBitmap = null;
}
if (dstBitmap != null && !dstBitmap.isRecycled()) {
dstBitmap.recycle();
dstBitmap = null;
}
}
return bRet;
}
public static ImageSize getThumbnailDisplaySize(float srcWidth, float srcHeight, float dstMaxWH, float dstMinWH) {
if (srcWidth <= 0 || srcHeight <= 0) { // bounds check
return new ImageSize((int) dstMinWH, (int) dstMinWH);
}
float shorter;
float longer;
boolean widthIsShorter;
//store
if (srcHeight < srcWidth) {
shorter = srcHeight;
longer = srcWidth;
widthIsShorter = false;
} else {
shorter = srcWidth;
longer = srcHeight;
widthIsShorter = true;
}
if (shorter < dstMinWH) {
float scale = dstMinWH / shorter;
shorter = dstMinWH;
if (longer * scale > dstMaxWH) {
longer = dstMaxWH;
} else {
longer *= scale;
}
} else if (longer > dstMaxWH) {
float scale = dstMaxWH / longer;
longer = dstMaxWH;
if (shorter * scale < dstMinWH) {
shorter = dstMinWH;
} else {
shorter *= scale;
}
}
//restore
if (widthIsShorter) {
srcWidth = shorter;
srcHeight = longer;
} else {
srcWidth = longer;
srcHeight = shorter;
}
return new ImageSize((int) srcWidth, (int) srcHeight);
}
public static File getScaledImageFileWithMD5(File imageFile, String mimeType) {
String filePath = imageFile.getPath();
if (!isInvalidPictureFile(mimeType)) {
LogUtil.i("ImageUtil", "is invalid picture file");
return null;
}
String tempFilePath = getTempFilePath(FileUtil.getExtensionName(filePath));
File tempImageFile = AttachmentStore.create(tempFilePath);
if (tempImageFile == null) {
return null;
}
CompressFormat compressFormat = CompressFormat.JPEG;
// 压缩数值由第三方开发者自行决定
int maxWidth = 720;
int quality = 60;
if (ImageUtil.scaleImage(imageFile, tempImageFile, maxWidth, compressFormat, quality)) {
return tempImageFile;
} else {
return null;
}
}
private static String getTempFilePath(String extension) {
return StorageUtil.getWritePath(
BaseApplication.Companion.getApp(),
"temp_image_" + StringUtils.get36UUID() + "." + extension,
StorageType.TYPE_TEMP);
}
public static Boolean scaleImage(File srcFile, File dstFile, int dstMaxWH, CompressFormat compressFormat, int quality) {
Boolean success = false;
try {
int inSampleSize = SampleSizeUtil.calculateSampleSize(srcFile.getAbsolutePath(), dstMaxWH * dstMaxWH);
Bitmap srcBitmap = BitmapDecoder.decodeSampled(srcFile.getPath(), inSampleSize);
if (srcBitmap == null) {
return success;
}
float rotate;
String mimeType = getImageType(srcFile.getAbsolutePath());
if (!TextUtils.isEmpty(mimeType) && mimeType.equals("image/png")) {
// png格式不能使用ExifInterface
rotate = 0;
} else {
// 旋转
ExifInterface localExifInterface = new ExifInterface(srcFile.getAbsolutePath());
int rotateInt = localExifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
rotate = getImageRotate(rotateInt);
}
Bitmap dstBitmap;
float scale = (float) Math.sqrt(((float) dstMaxWH * (float) dstMaxWH) / ((float) srcBitmap.getWidth() * (float) srcBitmap.getHeight()));
if (rotate == 0f && scale >= 1) {
dstBitmap = srcBitmap;
} else {
try {
Matrix matrix = new Matrix();
if (rotate != 0) {
matrix.postRotate(rotate);
}
if (scale < 1) {
matrix.postScale(scale, scale);
}
dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dstFile));
srcBitmap.compress(compressFormat, quality, bos);
bos.flush();
bos.close();
success = true;
if (!srcBitmap.isRecycled())
srcBitmap.recycle();
srcBitmap = null;
return success;
}
}
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dstFile));
dstBitmap.compress(compressFormat, quality, bos);
bos.flush();
bos.close();
success = true;
if (!srcBitmap.isRecycled())
srcBitmap.recycle();
srcBitmap = null;
if (!dstBitmap.isRecycled())
dstBitmap.recycle();
dstBitmap = null;
} catch (Exception e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
return success;
}
public static ImageSize getThumbnailDisplaySize(int maxSide, int minSide, String imagePath) {
int[] bound = BitmapDecoder.decodeBound(imagePath);
ImageSize imageSize = getThumbnailDisplaySize(bound[0], bound[1], maxSide, minSide);
return imageSize;
}
public static int[] getBoundWithLength(int maxSide, Object imageObject, boolean resizeToDefault) {
int width = -1;
int height = -1;
int[] bound;
if (String.class.isInstance(imageObject)) {
bound = BitmapDecoder.decodeBound((String) imageObject);
width = bound[0];
height = bound[1];
} else if (Integer.class.isInstance(imageObject)) {
bound = BitmapDecoder.decodeBound(BaseApplication.Companion.getApp().getResources(), (Integer) imageObject);
width = bound[0];
height = bound[1];
} else if (InputStream.class.isInstance(imageObject)) {
bound = BitmapDecoder.decodeBound((InputStream) imageObject);
width = bound[0];
height = bound[1];
}
int defaultWidth = maxSide;
int defaultHeight = maxSide;
if (width <= 0 || height <= 0) {
width = defaultWidth;
height = defaultHeight;
} else if (resizeToDefault) {
if (width > height) {
height = (int) (defaultWidth * ((float) height / (float) width));
width = defaultWidth;
} else {
width = (int) (defaultHeight * ((float) width / (float) height));
height = defaultHeight;
}
}
return new int[]{width, height};
}
/**
* 下载失败与获取失败时都统一显示默认下载失败图片
*
* @return
*/
public static Bitmap getBitmapFromDrawableRes(int res) {
try {
return getBitmapImmutableCopy(BaseApplication.Companion.getApp().getResources(), res);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean isInvalidPictureFile(String mimeType) {
String lowerCaseFilepath = mimeType.toLowerCase();
return (lowerCaseFilepath.contains("jpg") || lowerCaseFilepath.contains("jpeg")
|| lowerCaseFilepath.toLowerCase().contains("png") || lowerCaseFilepath.toLowerCase().contains("bmp") || lowerCaseFilepath
.toLowerCase().contains("gif"));
}
public static boolean savePicture(Context context, String base64DataStr) {
// 去掉base64中的前缀
// String base64Str = base64DataStr.substring(base64DataStr.indexOf(",")+1, base64DataStr.length());
File appDir = new File(Environment.getExternalStorageDirectory(), "Camera");// 图片保存的文件夹的名称
if (!appDir.exists()) {
appDir.mkdir();
}
String imgName = System.currentTimeMillis() + ".png";
File fileTest = new File(appDir, imgName);
byte[] data = Base64.decode(base64DataStr, Base64.DEFAULT);
for (int i = 0; i < data.length; i++) {
if (data[i] < 0) {
data[i] += 256;//调整异常数据
}
}
OutputStream os = null;
try {
os = new FileOutputStream(fileTest);
os.write(data);
os.flush();
os.close();
// 通知系统刷新图库
updateAlbum(context, fileTest);
ToastUtil.toastShort("图片已保存至相册");
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
ToastUtil.toastShort("保存失败");
return false;
} catch (IOException e) {
e.printStackTrace();
ToastUtil.toastShort("保存失败");
return false;
}
}
/**
*
* @param bytes
* @param opts
* @return
*/
public static Bitmap getPicFromBytes(byte[] bytes, BitmapFactory.Options opts) {
if (null == bytes){
return null;
}
if (null == opts){
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
}
/**
* 通知图库更新数据
* context
* fileName
* file
*/
private static void updateAlbum(Context context, File file) {
// 最后通知图库更新
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
}
}
package com.yidianling.ydlcommon.custom.picker.util.file;
import android.graphics.Bitmap;
import android.text.TextUtils;
import com.yidianling.common.tools.LogUtil;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 用于把附件保存到文件系统中
*/
public class AttachmentStore {
public static long copy(String srcPath, String dstPath) {
if (TextUtils.isEmpty(srcPath) || TextUtils.isEmpty(dstPath)) {
return -1;
}
File source = new File(srcPath);
if (!source.exists()) {
return -1;
}
if (srcPath.equals(dstPath)) {
return source.length();
}
FileChannel fcin = null;
FileChannel fcout = null;
try {
fcin = new FileInputStream(source).getChannel();
fcout = new FileOutputStream(create(dstPath)).getChannel();
ByteBuffer tmpBuffer = ByteBuffer.allocateDirect(4096);
while (fcin.read(tmpBuffer) != -1) {
tmpBuffer.flip();
fcout.write(tmpBuffer);
tmpBuffer.clear();
}
return source.length();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fcin != null) {
fcin.close();
}
if (fcout != null) {
fcout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return -1;
}
public static long getFileLength(String srcPath) {
if (TextUtils.isEmpty(srcPath)) {
return -1;
}
File srcFile = new File(srcPath);
if (!srcFile.exists()) {
return -1;
}
return srcFile.length();
}
public static long save(String path, String content) {
return save(content.getBytes(), path);
}
/**
* 把数据保存到文件系统中,并且返回其大小
*
* @param data
* @param filePath
* @return 如果保存失败,则返回-1
*/
public static long save(byte[] data, String filePath) {
if (TextUtils.isEmpty(filePath)) {
return -1;
}
File f = new File(filePath);
if(f.getParentFile() == null) {
return -1;
}
if (!f.getParentFile().exists()) {// 如果不存在上级文件夹
f.getParentFile().mkdirs();
}
try {
f.createNewFile();
FileOutputStream fout = new FileOutputStream(f);
fout.write(data);
fout.close();
} catch (IOException e) {
e.printStackTrace();
return -1;
}
return f.length();
}
public static boolean move(String srcFilePath, String dstFilePath) {
if (TextUtils.isEmpty(srcFilePath) || TextUtils.isEmpty(dstFilePath)) {
return false;
}
File srcFile = new File(srcFilePath);
if (!srcFile.exists() || !srcFile.isFile()) {
return false;
}
File dstFile = new File(dstFilePath);
if(dstFile.getParentFile() == null) {
return false;
}
if (!dstFile.getParentFile().exists()) {// 如果不存在上级文件夹
dstFile.getParentFile().mkdirs();
}
return srcFile.renameTo(dstFile);
}
public static File create(String filePath) {
if (TextUtils.isEmpty(filePath)) {
return null;
}
File f = new File(filePath);
if (!f.getParentFile().exists()) {// 如果不存在上级文件夹
f.getParentFile().mkdirs();
}
try {
f.createNewFile();
return f;
} catch (IOException e) {
if(f!=null && f.exists()){
f.delete();
}
return null;
}
}
/**
* @param is
* @param filePath
* @return 保存失败,返回-1
*/
public static long save(InputStream is, String filePath) {
File f = new File(filePath);
if (!f.getParentFile().exists()) {// 如果不存在上级文件夹
f.getParentFile().mkdirs();
}
FileOutputStream fos = null;
try {
f.createNewFile();
fos = new FileOutputStream(f);
int read = 0;
byte[] bytes = new byte[8091];
while ((read = is.read(bytes)) != -1) {
fos.write(bytes, 0, read);
}
return f.length();
} catch (IOException e) {
if(f!=null && f.exists()){
f.delete();
}
LogUtil.e("file", "save is to " + filePath + " failed: " + e.getMessage());
return -1;
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 把文件从文件系统中读取出来
*
* @param path
* @return 如果无法读取,则返回null
*/
public static byte[] load(String path) {
try {
File f = new File(path);
int unread = (int) f.length();
int read = 0;
byte[] buf = new byte[unread]; // 读取文件长度
FileInputStream fin = new FileInputStream(f);
do {
int count = fin.read(buf, read, unread);
read += count;
unread -= count;
} while (unread != 0);
fin.close();
return buf;
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
}
public static String loadAsString(String path) {
if (isFileExist(path)) {
byte[] content = load(path);
return new String(content);
} else {
return null;
}
}
/**
* 删除指定路径文件
*
* @param path
*/
public static boolean delete(String path) {
if(TextUtils.isEmpty(path)){
return false;
}
File f = new File(path);
if (f.exists()) {
f = renameOnDelete(f);
return f.delete();
} else {
return false;
}
}
public static void deleteOnExit(String path) {
if(TextUtils.isEmpty(path)){
return;
}
File f = new File(path);
if (f.exists()) {
f.deleteOnExit();
}
}
public static boolean deleteDir(String path) {
return deleteDir(path, true);
}
private static boolean deleteDir(String path, boolean rename) {
boolean success = true;
File file = new File(path);
if (file.exists()) {
if (rename) {
file = renameOnDelete(file);
}
File[] list = file.listFiles();
if (list != null) {
int len = list.length;
for (int i = 0; i < len; ++i) {
if (list[i].isDirectory()) {
deleteDir(list[i].getPath(), false);
} else {
boolean ret = list[i].delete();
if (!ret) {
success = false;
}
}
}
}
} else {
success = false;
}
if (success) {
file.delete();
}
return success;
}
// rename before delete to avoid lingering filesystem lock of android
private static File renameOnDelete(File file) {
String tmpPath = file.getParent() + "/" + System.currentTimeMillis() + "_tmp";
File tmpFile = new File(tmpPath);
if (file.renameTo(tmpFile)) {
return tmpFile;
} else {
return file;
}
}
public static boolean isFileExist(String path) {
if (!TextUtils.isEmpty(path) && new File(path).exists()) {
return true;
}
else {
return false;
}
}
public static boolean saveBitmap(Bitmap bitmap, String path, boolean recyle) {
if (bitmap == null || TextUtils.isEmpty(path)) {
return false;
}
BufferedOutputStream bos = null;
try {
FileOutputStream fos = new FileOutputStream(path);
bos = new BufferedOutputStream(fos);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);
return true;
} catch (FileNotFoundException e) {
return false;
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
}
}
if (recyle) {
bitmap.recycle();
}
}
}
}
package com.yidianling.ydlcommon.custom.picker.util.file;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.ydlcommon.R;
import java.util.Locale;
public class FileUtil {
private static final String TAG = "FileUtil";
public static boolean hasExtentsion(String filename) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return true;
} else {
return false;
}
}
// 获取文件扩展名
public static String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return "";
}
// 获取文件名
public static String getFileNameFromPath(String filepath) {
if ((filepath != null) && (filepath.length() > 0)) {
int sep = filepath.lastIndexOf('/');
if ((sep > -1) && (sep < filepath.length() - 1)) {
return filepath.substring(sep + 1);
}
}
return filepath;
}
// 获取不带扩展名的文件名
public static String getFileNameNoEx(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot > -1) && (dot < (filename.length()))) {
return filename.substring(0, dot);
}
}
return filename;
}
public static String getMimeType(String filePath) {
if (TextUtils.isEmpty(filePath)) {
return "";
}
String type = null;
String extension = getExtensionName(filePath.toLowerCase());
if (!TextUtils.isEmpty(extension)) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
type = mime.getMimeTypeFromExtension(extension);
}
Log.i(TAG, "url:" + filePath + " " + "type:" + type);
if (TextUtils.isEmpty(type) && filePath.endsWith("aac")) {
type = "audio/aac";
}
return type;
}
public enum SizeUnit {
Byte,
KB,
MB,
GB,
TB,
Auto,
}
public static String formatFileSize(long size) {
return formatFileSize(size, SizeUnit.Auto);
}
public static String formatFileSize(long size, SizeUnit unit) {
if (size < 0) {
return BaseApplication.Companion.getApp().getString(R.string.unknow_size);
}
final double KB = 1024;
final double MB = KB * 1024;
final double GB = MB * 1024;
final double TB = GB * 1024;
if (unit == SizeUnit.Auto) {
if (size < KB) {
unit = SizeUnit.Byte;
} else if (size < MB) {
unit = SizeUnit.KB;
} else if (size < GB) {
unit = SizeUnit.MB;
} else if (size < TB) {
unit = SizeUnit.GB;
} else {
unit = SizeUnit.TB;
}
}
switch (unit) {
case Byte:
return size + "B";
case KB:
return String.format(Locale.US, "%.2fKB", size / KB);
case MB:
return String.format(Locale.US, "%.2fMB", size / MB);
case GB:
return String.format(Locale.US, "%.2fGB", size / GB);
case TB:
return String.format(Locale.US, "%.2fPB", size / TB);
default:
return size + "B";
}
}
}
package com.yidianling.ydlcommon.custom.picker.util.media;
import android.annotation.TargetApi;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import android.os.Build;
import android.provider.MediaStore;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.RxDeviceTool;
import com.yidianling.ydlcommon.custom.picker.util.ImageUtil;
import com.yidianling.ydlcommon.custom.picker.util.file.AttachmentStore;
import java.io.*;
public class BitmapDecoder {
public static Bitmap decode(InputStream is) {
BitmapFactory.Options options = new BitmapFactory.Options();
// RGB_565
options.inPreferredConfig = Bitmap.Config.RGB_565;
/**
* 在4.4上,如果之前is标记被移动过,会导致解码失败
*/
try {
if (is.markSupported()) {
is.reset();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
return BitmapFactory.decodeStream(is, null, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
return null;
}
public static Bitmap decodeSampledForDisplay(String pathName) {
return decodeSampledForDisplay(pathName, true);
}
public static Bitmap decodeSampledForDisplay(String pathName, boolean withTextureLimit) {
float ratio = ImageUtil.MAX_IMAGE_RATIO;
int[][] reqBounds = new int[][]{
new int[]{RxDeviceTool.getScreenWidth(BaseApplication.Companion.getApp()) * 2, RxDeviceTool.getScreenHeight(BaseApplication.Companion.getApp())},
new int[]{RxDeviceTool.getScreenWidth(BaseApplication.Companion.getApp()), RxDeviceTool.getScreenHeight(BaseApplication.Companion.getApp()) * 2},
new int[]{(int) (RxDeviceTool.getScreenWidth(BaseApplication.Companion.getApp()) * 1.414), (int) (RxDeviceTool.getScreenHeight(BaseApplication.Companion.getApp()) * 1.414)},
};
// decode bound
int[] bound = decodeBound(pathName);
// pick request bound
int[] reqBound = pickReqBoundWithRatio(bound, reqBounds, ratio);
int width = bound[0];
int height = bound[1];
int reqWidth = reqBound[0];
int reqHeight = reqBound[1];
// calculate sample size
int sampleSize = SampleSizeUtil.calculateSampleSize(width, height, reqWidth, reqHeight);
if (withTextureLimit) {
// adjust sample size
sampleSize = SampleSizeUtil.adjustSampleSizeWithTexture(sampleSize, width, height);
}
int RETRY_LIMIT = 5;
Bitmap bitmap = decodeSampled(pathName, sampleSize);
while (bitmap == null && RETRY_LIMIT > 0) {
sampleSize++;
RETRY_LIMIT--;
bitmap = decodeSampled(pathName, sampleSize);
}
return bitmap;
}
public static int[] decodeBound(String pathName) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
return new int[]{options.outWidth, options.outHeight};
}
public static int[] decodeBound(Resources res, int resId) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
return new int[]{options.outWidth, options.outHeight};
}
private static int[] pickReqBoundWithRatio(int[] bound, int[][] reqBounds, float ratio) {
float hRatio = bound[1] == 0 ? 0 : (float) bound[0] / (float) bound[1];
float vRatio = bound[0] == 0 ? 0 : (float) bound[1] / (float) bound[0];
if (hRatio >= ratio) {
return reqBounds[0];
} else if (vRatio >= ratio) {
return reqBounds[1];
} else {
return reqBounds[2];
}
}
public static Bitmap decodeSampled(String pathName, int sampleSize) {
BitmapFactory.Options options = new BitmapFactory.Options();
// RGB_565
options.inPreferredConfig = Bitmap.Config.RGB_565;
// sample size
options.inSampleSize = sampleSize;
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeFile(pathName, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
return checkInBitmap(bitmap, options, pathName);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static Bitmap checkInBitmap(Bitmap bitmap,
BitmapFactory.Options options, String path) {
boolean honeycomb = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
if (honeycomb && bitmap != options.inBitmap && options.inBitmap != null) {
options.inBitmap.recycle();
options.inBitmap = null;
}
if (bitmap == null) {
try {
bitmap = BitmapFactory.decodeFile(path, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}
return bitmap;
}
public static int[] decodeBound(File file) {
InputStream is = null;
try {
is = new FileInputStream(file);
int[] bound = decodeBound(is);
return bound;
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return new int[]{0, 0};
}
public static int[] decodeBound(InputStream is) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, options);
return new int[]{options.outWidth, options.outHeight};
}
public static Bitmap decodeSampled(InputStream is, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
// RGB_565
options.inPreferredConfig = Bitmap.Config.RGB_565;
// sample size
options.inSampleSize = getSampleSize(is, reqWidth, reqHeight);
try {
return BitmapFactory.decodeStream(is, null, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
return null;
}
public static Bitmap decodeSampled(String pathName, int reqWidth, int reqHeight) {
return decodeSampled(pathName, getSampleSize(pathName, reqWidth, reqHeight));
}
public static int getSampleSize(InputStream is, int reqWidth, int reqHeight) {
// decode bound
int[] bound = decodeBound(is);
// calculate sample size
int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight);
return sampleSize;
}
public static int getSampleSize(String pathName, int reqWidth, int reqHeight) {
// decode bound
int[] bound = decodeBound(pathName);
// calculate sample size
int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight);
return sampleSize;
}
/**
* ******************************* decode resource ******************************************
*/
public static Bitmap decodeSampled(Resources resources, int resId, int reqWidth, int reqHeight) {
return decodeSampled(resources, resId, getSampleSize(resources, resId, reqWidth, reqHeight));
}
public static int getSampleSize(Resources resources, int resId, int reqWidth, int reqHeight) {
// decode bound
int[] bound = decodeBound(resources, resId);
// calculate sample size
int sampleSize = SampleSizeUtil.calculateSampleSize(bound[0], bound[1], reqWidth, reqHeight);
return sampleSize;
}
public static Bitmap decodeSampled(Resources res, int resId, int sampleSize) {
BitmapFactory.Options options = new BitmapFactory.Options();
// RGB_565
options.inPreferredConfig = Bitmap.Config.RGB_565;
// sample size
options.inSampleSize = sampleSize;
try {
return BitmapFactory.decodeResource(res, resId, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
return null;
}
public static boolean extractThumbnail(String videoPath, String thumbPath) {
if (!AttachmentStore.isFileExist(thumbPath)) {
Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.MINI_KIND);
if (thumbnail != null) {
AttachmentStore.saveBitmap(thumbnail, thumbPath, true);
return true;
}
}
return false;
}
}
package com.yidianling.ydlcommon.custom.picker.util.media;
import android.opengl.GLES10;
public class SampleSizeUtil {
public static int calculateSampleSize(String imagePath, int totalPixel) {
int[] bound = BitmapDecoder.decodeBound(imagePath);
return calculateSampleSize(bound[0], bound[1], totalPixel);
}
public static int calculateSampleSize(int width, int height, int totalPixel) {
int ratio = 1;
if (width > 0 && height > 0) {
ratio = (int) Math.sqrt((float) (width * height) / totalPixel);
if (ratio < 1) {
ratio = 1;
}
}
return ratio;
}
/**
* Calculate an inSampleSize for use in a {@link android.graphics.BitmapFactory.Options}
* object when decoding bitmaps using the decode* methods from
* {@link android.graphics.BitmapFactory}. This implementation calculates the closest
* inSampleSize that will result in the final decoded bitmap having a width
* and height equal to or larger than the requested width and height. This
* implementation does not ensure a power of 2 is returned for inSampleSize
* which can be faster when decoding but results in a larger bitmap which
* isn't as useful for caching purposes.
*
* @param width
* @param height
* @param reqWidth
* @param reqHeight
* @return
*/
public static int calculateSampleSize(int width, int height, int reqWidth, int reqHeight) {
// can't proceed
if (width <= 0 || height <= 0) {
return 1;
}
// can't proceed
if (reqWidth <= 0 && reqHeight <= 0) {
return 1;
} else if (reqWidth <= 0) {
reqWidth = (int) (width * reqHeight / (float)height + 0.5f) ;
} else if (reqHeight <= 0) {
reqHeight = (int) (height * reqWidth / (float)width + 0.5f);
}
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee a final image
// with both dimensions larger than or equal to the requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
if (inSampleSize == 0) {
inSampleSize = 1;
}
// This offers some additional logic in case the image has a strange
// aspect ratio. For example, a panorama may have a much larger
// width than height. In these cases the total pixels might still
// end up being too large to fit comfortably in memory, so we should
// be more aggressive with sample down the image (=larger
// inSampleSize).
final float totalPixels = width * height;
// Anything more than 2x the requested pixels we'll sample down
// further
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
}
return inSampleSize;
}
public static final int adjustSampleSizeWithTexture(int sampleSize, int width, int height) {
int textureSize = getTextureSize();
if ((textureSize > 0) && ((width > sampleSize) || (height > sampleSize))) {
while ((width / (float)sampleSize) > textureSize || (height / (float)sampleSize) > textureSize) {
sampleSize++;
}
// 2的指数对齐
sampleSize = SampleSizeUtil.roundup2n(sampleSize);
}
return sampleSize;
}
private static int textureSize = 0;
//存在第二次拿拿不到的情况,所以把拿到的数据用一个static变量保存下来
public static final int getTextureSize() {
if (textureSize > 0) {
return textureSize;
}
int[] params = new int[1];
GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, params, 0);
textureSize = params[0];
return textureSize;
}
// 将x向上对齐到2的幂指数
private static final int roundup2n(int x) {
if ((x & (x - 1)) == 0) {
return x;
}
int pos = 0;
while (x > 0) {
x >>= 1;
++pos;
}
return 1 << pos;
}
}
package com.yidianling.ydlcommon.custom.picker.util.storage;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.io.IOException;
/** package */
class ExternalStorage {
/**
* 外部存储根目录
*/
private String sdkStorageRoot = null;
private static ExternalStorage instance;
private static final String TAG = "ExternalStorage";
private boolean hasPermission = true; // 是否拥有存储卡权限
private Context context;
private ExternalStorage() {
}
synchronized public static ExternalStorage getInstance() {
if (instance == null) {
instance = new ExternalStorage();
}
return instance;
}
public void init(Context context, String sdkStorageRoot) {
this.context = context;
// 判断权限
hasPermission = checkPermission(context);
if (!TextUtils.isEmpty(sdkStorageRoot)) {
File dir = new File(sdkStorageRoot);
if (!dir.exists()) {
dir.mkdirs();
}
if (dir.exists() && !dir.isFile()) {
this.sdkStorageRoot = sdkStorageRoot;
if (!sdkStorageRoot.endsWith("/")) {
this.sdkStorageRoot = sdkStorageRoot + "/";
}
}
}
if (TextUtils.isEmpty(this.sdkStorageRoot)) {
loadStorageState(context);
}
createSubFolders();
}
private void loadStorageState(Context context) {
String externalPath = Environment.getExternalStorageDirectory().getPath();
this.sdkStorageRoot = externalPath + "/" + context.getPackageName() + "/";
}
private void createSubFolders() {
boolean result = true;
File root = new File(sdkStorageRoot);
if (root.exists() && !root.isDirectory()) {
root.delete();
}
for (StorageType storageType : StorageType.values()) {
result &= makeDirectory(sdkStorageRoot + storageType.getStoragePath());
}
if (result) {
createNoMediaFile(sdkStorageRoot);
}
}
/**
* 创建目录
*
* @param path
* @return
*/
private boolean makeDirectory(String path) {
File file = new File(path);
boolean exist = file.exists();
if (!exist) {
exist = file.mkdirs();
}
return exist;
}
protected static String NO_MEDIA_FILE_NAME = ".nomedia";
private void createNoMediaFile(String path) {
File noMediaFile = new File(path + "/" + NO_MEDIA_FILE_NAME);
try {
if (!noMediaFile.exists()) {
noMediaFile.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 文件全名转绝对路径(写)
*
* @param fileName
* 文件全名(文件名.扩展名)
* @return 返回绝对路径信息
*/
public String getWritePath(String fileName, StorageType fileType) {
return pathForName(fileName, fileType, false, false);
}
private String pathForName(String fileName, StorageType type, boolean dir,
boolean check) {
String directory = getDirectoryByDirType(type);
StringBuilder path = new StringBuilder(directory);
if (!dir) {
path.append(fileName);
}
String pathString = path.toString();
File file = new File(pathString);
if (check) {
if (file.exists()) {
if ((dir && file.isDirectory())
|| (!dir && !file.isDirectory())) {
return pathString;
}
}
return "";
} else {
return pathString;
}
}
/**
* 返回指定类型的文件夹路径
*
* @param fileType
* @return
*/
public String getDirectoryByDirType(StorageType fileType) {
return sdkStorageRoot + fileType.getStoragePath();
}
/**
* 根据输入的文件名和类型,找到该文件的全路径。
* @param fileName
* @param fileType
* @return 如果存在该文件,返回路径,否则返回空
*/
public String getReadPath(String fileName, StorageType fileType) {
if (TextUtils.isEmpty(fileName)) {
return "";
}
return pathForName(fileName, fileType, false, true);
}
public boolean isSdkStorageReady() {
String externalRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
if (this.sdkStorageRoot.startsWith(externalRoot)) {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
} else {
return true;
}
}
/**
* 获取外置存储卡剩余空间
* @return
*/
public long getAvailableExternalSize() {
return getResidualSpace(sdkStorageRoot);
}
/**
* 获取目录剩余空间
* @param directoryPath
* @return
*/
private long getResidualSpace(String directoryPath) {
try {
StatFs sf = new StatFs(directoryPath);
long blockSize = sf.getBlockSize();
long availCount = sf.getAvailableBlocks();
long availCountByte = availCount * blockSize;
return availCountByte;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* SD卡存储权限检查
*/
private boolean checkPermission(Context context) {
if (context == null) {
Log.e(TAG, "checkMPermission context null");
return false;
}
// M permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String p1 = Manifest.permission.WRITE_EXTERNAL_STORAGE;
String p2 = Manifest.permission.READ_EXTERNAL_STORAGE;
// M 先看看有没有读写权限
if (context.checkSelfPermission(p1) != PackageManager.PERMISSION_GRANTED ||
context.checkSelfPermission(p2) != PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "without permission to access storage");
return false;
}
}
return true;
}
/**
* 有效性检查
*/
public void checkStorageValid() {
if (hasPermission) {
return; // M以下版本&授权过的M版本不需要检查
}
hasPermission = checkPermission(context); // 检查是否已经获取权限了
if (hasPermission) {
Log.i(TAG, "get permission to access storage");
// 已经重新获得权限,那么重新检查一遍初始化过程
createSubFolders();
}
}
}
package com.yidianling.ydlcommon.custom.picker.util.storage;
public enum StorageType {
TYPE_LOG(DirectoryName.LOG_DIRECTORY_NAME),
TYPE_TEMP(DirectoryName.TEMP_DIRECTORY_NAME),
TYPE_FILE(DirectoryName.FILE_DIRECTORY_NAME),
TYPE_AUDIO(DirectoryName.AUDIO_DIRECTORY_NAME),
TYPE_IMAGE(DirectoryName.IMAGE_DIRECTORY_NAME),
TYPE_VIDEO(DirectoryName.VIDEO_DIRECTORY_NAME),
TYPE_THUMB_IMAGE(DirectoryName.THUMB_DIRECTORY_NAME),
TYPE_THUMB_VIDEO(DirectoryName.THUMB_DIRECTORY_NAME),
;
private DirectoryName storageDirectoryName;
private long storageMinSize;
public String getStoragePath() {
return storageDirectoryName.getPath();
}
public long getStorageMinSize() {
return storageMinSize;
}
StorageType(DirectoryName dirName) {
this(dirName, StorageUtil.THRESHOLD_MIN_SPCAE);
}
StorageType(DirectoryName dirName, long storageMinSize) {
this.storageDirectoryName = dirName;
this.storageMinSize = storageMinSize;
}
enum DirectoryName {
AUDIO_DIRECTORY_NAME("audio/"),
DATA_DIRECTORY_NAME("data/"),
FILE_DIRECTORY_NAME("file/"),
LOG_DIRECTORY_NAME("log/"),
TEMP_DIRECTORY_NAME("temp/"),
IMAGE_DIRECTORY_NAME("image/"),
THUMB_DIRECTORY_NAME("thumb/"),
VIDEO_DIRECTORY_NAME("video/"),
;
private String path;
public String getPath() {
return path;
}
private DirectoryName(String path) {
this.path = path;
}
}
}
package com.yidianling.ydlcommon.custom.picker.util.storage;
import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;
import java.io.File;
public class StorageUtil {
public final static long K = 1024;
public final static long M = 1024 * 1024;
// 外置存储卡默认预警临界值
private static final long THRESHOLD_WARNING_SPACE = 100 * M;
// 保存文件时所需的最小空间的默认值
public static final long THRESHOLD_MIN_SPCAE = 20 * M;
public static void init(Context context, String rootPath) {
ExternalStorage.getInstance().init(context, rootPath);
}
/**
* 获取文件保存路径,没有toast提示
*
* @param fileName
* @param fileType
* @return 可用的保存路径或者null
*/
public static String getWritePath(String fileName, StorageType fileType) {
return getWritePath(null, fileName, fileType, false);
}
/**
* 获取文件保存路径
*
* @param fileName 文件全名
* @param tip 空间不足时是否给出默认的toast提示
* @return 可用的保存路径或者null
*/
private static String getWritePath(Context context, String fileName, StorageType fileType, boolean tip) {
String path = ExternalStorage.getInstance().getWritePath(fileName, fileType);
if (TextUtils.isEmpty(path)) {
return null;
}
File dir = new File(path).getParentFile();
if (dir != null && !dir.exists()) {
dir.mkdirs();
}
return path;
}
/**
* 判断能否使用外置存储
*/
public static boolean isExternalStorageExist() {
return ExternalStorage.getInstance().isSdkStorageReady();
}
/**
* 判断外部存储是否存在,以及是否有足够空间保存指定类型的文件
*
* @param context
* @param fileType
* @param tip 是否需要toast提示
* @return false: 无存储卡或无空间可写, true: 表示ok
*/
public static boolean hasEnoughSpaceForWrite(Context context, StorageType fileType, boolean tip) {
if (!ExternalStorage.getInstance().isSdkStorageReady()) {
return false;
}
long residual = ExternalStorage.getInstance().getAvailableExternalSize();
if (residual < fileType.getStorageMinSize()) {
return false;
} else if (residual < THRESHOLD_WARNING_SPACE) {
}
return true;
}
/**
* 根据输入的文件名和类型,找到该文件的全路径。
*
* @param fileName
* @param fileType
* @return 如果存在该文件,返回路径,否则返回空
*/
public static String getReadPath(String fileName, StorageType fileType) {
return ExternalStorage.getInstance().getReadPath(fileName, fileType);
}
/**
* 获取文件保存路径,空间不足时有toast提示
*
* @param context
* @param fileName
* @param fileType
* @return 可用的保存路径或者null
*/
public static String getWritePath(Context context, String fileName, StorageType fileType) {
return getWritePath(context, fileName, fileType, true);
}
public static String getDirectoryByDirType(StorageType fileType) {
return ExternalStorage.getInstance().getDirectoryByDirType(fileType);
}
public static String getSystemImagePath() {
String picturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath();
return picturePath + "/";
}
public static boolean isInvalidVideoFile(String filePath) {
return filePath.toLowerCase().endsWith(".3gp")
|| filePath.toLowerCase().endsWith(".mp4");
}
public static void checkValid() {
ExternalStorage.getInstance().checkStorageValid();
}
}
...@@ -6,14 +6,12 @@ import android.support.annotation.StringRes ...@@ -6,14 +6,12 @@ import android.support.annotation.StringRes
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import com.yidianling.ydlcommon.core.base.BaseApplication import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.ydlcommon.custom.GlobalInfo import com.yidianling.ydlcommon.custom.GlobalInfo
import com.yidianling.ydlcommon.custom.constant.YdlConstants import com.yidianling.ydlcommon.custom.data.PlatformDataManager
import com.yidianling.ydlcommon.custom.data.YdlDataManager import com.yidianling.ydlcommon.custom.actions.imagepicker.PickerCallback
import com.yidianling.ydlcommon.custom.imagepicker.PickerCallback import com.yidianling.ydlcommon.custom.actions.imagepicker.YdlImagePicker
import com.yidianling.ydlcommon.custom.imagepicker.YdlImagePicker
import com.yidianling.ydlcommon.custom.pay.PayActivity import com.yidianling.ydlcommon.custom.pay.PayActivity
import com.yidianling.ydlcommon.custom.pay.PayParams import com.yidianling.ydlcommon.custom.pay.PayParams
import com.yidianling.ydlcommon.custom.pay.redpacket.jump.JumpPayActivity import com.yidianling.ydlcommon.custom.utils.remind.ToastHelper
import com.yidianling.ydlcommon.custom.remind.ToastHelper
/** /**
* author : Zhangwenchao * author : Zhangwenchao
...@@ -25,19 +23,6 @@ import com.yidianling.ydlcommon.custom.remind.ToastHelper ...@@ -25,19 +23,6 @@ import com.yidianling.ydlcommon.custom.remind.ToastHelper
class YdlCommonOut { class YdlCommonOut {
companion object { companion object {
const val HOLDER_PARAM = YdlConstants.HOLDER_PARAM
const val BUNDLE = YdlConstants.BUNDLE
const val API_HOST = YdlConstants.API_HOST
var API_HOST_H5 = YdlConstants.API_HOST_H5
var API_HOST_WEB = YdlConstants.API_HOST_WEB
const val SHAREZJ = YdlConstants.SHAREZJ
const val BIND_PHONE_ACTION = YdlConstants.BIND_PHONE_ACTION
const val HELP_URL = YdlConstants.HELP_URL
var ZJZHUYE = YdlConstants.ZJZHUYE
const val SILENCED_CODE = YdlConstants.SILENCED_CODE
var YUYDETAIL = YdlConstants.YUYDETAIL
const val PUBLISH_TYPE = YdlConstants.PUBLISH_TYPE
fun showToast(content: String) { fun showToast(content: String) {
ToastHelper.show(content) ToastHelper.show(content)
...@@ -51,49 +36,43 @@ class YdlCommonOut { ...@@ -51,49 +36,43 @@ class YdlCommonOut {
return BaseApplication.getApp() return BaseApplication.getApp()
} }
//打开支付跳转中间页
fun startJumpPayActivity(activity: Activity, payParams: PayParams, requestCode: Int){
activity.startActivityForResult(JumpPayActivity.newIntent(activity,payParams),requestCode)
activity.overridePendingTransition(0, 0)
}
// 打开支付页面 // 打开支付页面
fun startPayActivity(activity: Activity, payParams: PayParams, requestCode: Int) { fun startPayActivity(activity: Activity, payParams: PayParams, requestCode: Int) {
activity.startActivityForResult(PayActivity.newIntent(activity, payParams), requestCode) activity.startActivityForResult(PayActivity.newIntent(activity, payParams), requestCode)
} }
// 是否开启了声音 // 是否开启了声音
fun isVoice(): Boolean = YdlDataManager.getLocal().isVoice() fun isVoice(): Boolean = PlatformDataManager.getLocal().isVoice()
fun putVoice(voice: Boolean) { fun putVoice(voice: Boolean) {
YdlDataManager.getLocal().putVoice(voice) PlatformDataManager.getLocal().putVoice(voice)
} }
// 是否开启了震动 // 是否开启了震动
fun isShake(): Boolean = YdlDataManager.getLocal().isShake() fun isShake(): Boolean = PlatformDataManager.getLocal().isShake()
fun putShake(shake: Boolean) { fun putShake(shake: Boolean) {
YdlDataManager.getLocal().putShake(shake) PlatformDataManager.getLocal().putShake(shake)
} }
fun getGlobalInfo(): GlobalInfo? { fun getGlobalInfo(): GlobalInfo? {
return YdlDataManager.getRam().getGlobalInfo() return PlatformDataManager.getRam().getGlobalInfo()
} }
fun setGlobalInfo(globalInfo: GlobalInfo) { fun setGlobalInfo(globalInfo: GlobalInfo) {
YdlDataManager.getRam().setGlobalInfo(globalInfo) PlatformDataManager.getRam().setGlobalInfo(globalInfo)
} }
fun putNewYearKeyword(key: String, value: GlobalInfo.GlobalData.NewYearKeyword?) { fun putNewYearKeyword(key: String, value: GlobalInfo.GlobalData.NewYearKeyword?) {
YdlDataManager.getRam().putNewYearKeyword(key, value) PlatformDataManager.getRam().putNewYearKeyword(key, value)
} }
fun getNewYearKeyword(key: String): GlobalInfo.GlobalData.NewYearKeyword? { fun getNewYearKeyword(key: String): GlobalInfo.GlobalData.NewYearKeyword? {
return YdlDataManager.getRam().getNewYearKeyword(key) return PlatformDataManager.getRam().getNewYearKeyword(key)
} }
fun getNewYearKeyWordByContent(content: String?): GlobalInfo.GlobalData.NewYearKeyword? { fun getNewYearKeyWordByContent(content: String?): GlobalInfo.GlobalData.NewYearKeyword? {
return YdlDataManager.getRam().getGlobalInfo()?.info?.getNewYearKeyWordByContent(content) return PlatformDataManager.getRam().getGlobalInfo()?.info?.getNewYearKeyWordByContent(content)
} }
fun startPicker(activity: AppCompatActivity, openCamera: Boolean, callback: PickerCallback) { fun startPicker(activity: AppCompatActivity, openCamera: Boolean, callback: PickerCallback) {
...@@ -101,7 +80,7 @@ class YdlCommonOut { ...@@ -101,7 +80,7 @@ class YdlCommonOut {
} }
fun getChannelName(): String { fun getChannelName(): String {
return YdlDataManager.getRam().getChannelName() return PlatformDataManager.getRam().getChannelName()
} }
} }
} }
\ No newline at end of file
package com.yidianling.ydlcommon.custom.rxbus
import io.reactivex.Observable
import io.reactivex.subjects.PublishSubject
import io.reactivex.subjects.Subject
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/04/18
*/
class RxBus private constructor(){
companion object {
fun getInstance(): RxBus {
return Holder.INSTANCE
}
}
private val mBus: Subject<Any>
init {
mBus = PublishSubject.create()
}
fun <T>toObservable(tClass: Class<T>): Observable<T> {
return mBus.ofType(tClass)
}
fun post(any: Any) {
mBus.onNext(any)
}
private object Holder {
val INSTANCE = RxBus()
}
}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.tool;
import android.app.Activity;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
/**
* Created by haorui on 2019/6/6.
* Des: 解决全屏模式下,“adjustResize”失效问题(Android系统Bug)
* 链接地址:https://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible/19494006#19494006
*/
public class AndroidBug5497Workaround {
public static void assistActivity(Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private int contentHeight;
private boolean isfirst = true;
private Activity activity;
private int statusBarHeight;
private AndroidBug5497Workaround(Activity activity) {
//获取状态栏的高度
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
this.activity = activity;
FrameLayout content = (FrameLayout)activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
//界面出现变动都会调用这个监听事件
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
if (isfirst) {
contentHeight = mChildOfContent.getHeight();//兼容华为等机型
isfirst = false;
}
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams)
mChildOfContent.getLayoutParams();
}
//重新调整跟布局的高度
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
//当前可见高度和上一次可见高度不一致 布局变动
if (usableHeightNow != usableHeightPrevious) {
//int usableHeightSansKeyboard2 = mChildOfContent.getHeight();//兼容华为等机型
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard / 4)) {
// keyboard probably just became visible
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
//frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight;
} else {
frameLayoutParams.height = usableHeightSansKeyboard -heightDifference;
}
} else {
frameLayoutParams.height = contentHeight;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
/** * 计算mChildOfContent可见高度 ** @return */
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);
}
}
package com.yidianling.ydlcommon.custom.tool
import android.app.Activity
import android.content.pm.ActivityInfo
import android.content.res.TypedArray
import android.os.Build
import android.util.Log
/**
* Created by haorui on 2019/6/11.
* Des:Android系统帮助类
*/
object AndroidSystemHelper {
/**
* 修复Android 8.0 崩溃,Only fullscreen activities can request orientation
*/
fun fixAndroidOrientationBug(activity: Activity) {
if (!isAllowSetOrientation(activity)) {
val result = resetOrientation(activity)
Log.i(this.javaClass.simpleName, "onCreate resetOrientation when Oreo, result = " + result);
}
}
/**
* 反射调用ActivityInfo#isTranslucentOrFloating()
* 判断当前Activity是否透明or悬浮
*/
fun isTranslucentOrFloating(activity: Activity): Boolean {
var isTranslucentOrFloating = false
try {
val styleableRes = Class.forName("com.android.internal.R\$styleable").getField("Window").get(null) as IntArray
val ta = activity.obtainStyledAttributes(styleableRes)
val m = ActivityInfo::class.java.getMethod("isTranslucentOrFloating", TypedArray::class.java)
m.isAccessible = true
isTranslucentOrFloating = m.invoke(null, ta) as Boolean
m.isAccessible = false
} catch (e: Exception) {
e.printStackTrace()
}
return isTranslucentOrFloating
}
/**
* 重置屏幕方向
*/
fun resetOrientation(activity: Activity): Boolean {
try {
//设置方向为改为SCREEN_ORIENTATION_UNSPECIFIED:未指定类型
val field = Activity::class.java.getDeclaredField("mActivityInfo")
field.isAccessible = true
val o = field.get(activity) as ActivityInfo
o.screenOrientation = -1
field.isAccessible = false
return true
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
/**
* 是否允许设置屏幕方向
*/
fun isAllowSetOrientation(activity: Activity): Boolean {
return if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating(
activity
)
) {
Log.i(this.javaClass.simpleName, "avoid calling setRequestedOrientation when Oreo.")
false;
} else {
true
}
}
}
//package com.yidianling.ydlcommon.tool;
//
//import android.content.Context;
//import android.graphics.Bitmap;
//import android.graphics.BitmapShader;
//import android.graphics.Canvas;
//import android.graphics.Paint;
//
//import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
//import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
//
//import java.security.MessageDigest;
//
///**
// * Created by xiongyu on 2017/3/20.
// */
//
//public class GlideCircleTransform extends BitmapTransformation {
//
// public GlideCircleTransform(Context context) {
// super(context);
// }
//
// @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
// return circleCrop(pool, toTransform);
// }
//
// private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
// if (source == null) return null;
//
// int size = Math.min(source.getWidth(), source.getHeight());
// int x = (source.getWidth() - size) / 2;
// int y = (source.getHeight() - size) / 2;
//
// Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
//
// Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
// if (result == null) {
// result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
// }
//
// Canvas canvas = new Canvas(result);
// Paint paint = new Paint();
// paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
// paint.setAntiAlias(true);
// float r = size / 2f;
// canvas.drawCircle(r, r, r, paint);
// return result;
// }
//
// @Override
// public void updateDiskCacheKey(MessageDigest messageDigest) {
//
// }
//}
\ No newline at end of file
package com.yidianling.ydlcommon.custom.tool
import android.app.Activity
import android.content.Context
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
/**
* 输入法工具类
* Created by harvie on 2017/6/23 0023.
*/
class InputMethonUtils{
companion object{
/**
* EditText获取焦点并显示软键盘
*/
fun showSoftInputFromWindow(context : Context,editText: EditText?) {
editText?.isFocusable = true
editText?.isFocusableInTouchMode = true
editText?.requestFocus()
var input : InputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
input.showSoftInput(editText,0)
}
}
}
package com.yidianling.ydlcommon.custom.tool
import android.annotation.TargetApi
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.os.Build
import android.support.annotation.ColorInt
import android.support.annotation.IntRange
import android.support.design.widget.CoordinatorLayout
import android.support.v4.content.ContextCompat
import android.support.v4.widget.DrawerLayout
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.LinearLayout
import com.yidianling.ydlcommon.R
/**
* 状态栏相关工具类
* Created by hg
* w on 2017/7/2.
*/
object StatusBarUtils {
fun setWindowStatusBarColor(activity: Activity, colorResId: Int) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val window = activity.window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = ContextCompat.getColor(activity, colorResId)
//底部导航栏
//window.setNavigationBarColor(activity.getResources().getColor(colorResId));
}
} catch (e: Exception) {
e.printStackTrace()
}
}
fun setWindowStatusBarColor(dialog: Dialog, colorResId: Int) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val window = dialog.window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = ContextCompat.getColor(dialog.context, colorResId)
//底部导航栏
//window.setNavigationBarColor(activity.getResources().getColor(colorResId));
}
} catch (e: Exception) {
e.printStackTrace()
}
}
//====================添加其他状态栏处理方法 2019/3/3 haorui ====================
//====================来源 GitHub: https://github.com/laobie/StatusBarUtil====================
val DEFAULT_STATUS_BAR_ALPHA = 112
private val FAKE_STATUS_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view
private val FAKE_TRANSLUCENT_VIEW_ID = R.id.statusbarutil_translucent_view
private val TAG_KEY_HAVE_SET_OFFSET = -123
/**
* 设置状态栏颜色
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
fun setColor(activity: Activity, @ColorInt color: Int) {
setColor(
activity,
color,
DEFAULT_STATUS_BAR_ALPHA
)
}
/**
* 设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
fun setColor(activity: Activity, @ColorInt color: Int, @IntRange(from = 0, to = 255) statusBarAlpha: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.statusBarColor =
calculateStatusColor(color, statusBarAlpha)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
val decorView = activity.window.decorView as ViewGroup
val fakeStatusBarView = decorView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null) {
if (fakeStatusBarView.visibility == View.GONE) {
fakeStatusBarView.visibility = View.VISIBLE
}
fakeStatusBarView.setBackgroundColor(
calculateStatusColor(
color,
statusBarAlpha
)
)
} else {
decorView.addView(
createStatusBarView(
activity,
color,
statusBarAlpha
)
)
}
setRootView(activity)
}
}
/**
* 为滑动返回界面设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
*/
fun setColorForSwipeBack(activity: Activity, color: Int) {
setColorForSwipeBack(
activity,
color,
DEFAULT_STATUS_BAR_ALPHA
)
}
/**
* 为滑动返回界面设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
fun setColorForSwipeBack(activity: Activity, @ColorInt color: Int,
@IntRange(from = 0, to = 255) statusBarAlpha: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val contentView = activity.findViewById<View>(android.R.id.content) as ViewGroup
val rootView = contentView.getChildAt(0)
val statusBarHeight = getStatusBarHeight(activity)
if (rootView != null && rootView is CoordinatorLayout) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
rootView.fitsSystemWindows = false
contentView.setBackgroundColor(
calculateStatusColor(
color,
statusBarAlpha
)
)
val isNeedRequestLayout = contentView.paddingTop < statusBarHeight
if (isNeedRequestLayout) {
contentView.setPadding(0, statusBarHeight, 0, 0)
rootView.post { rootView.requestLayout() }
}
} else {
rootView.setStatusBarBackgroundColor(
calculateStatusColor(
color,
statusBarAlpha
)
)
}
} else {
contentView.setPadding(0, statusBarHeight, 0, 0)
contentView.setBackgroundColor(
calculateStatusColor(
color,
statusBarAlpha
)
)
}
setTransparentForWindow(activity)
}
}
/**
* 设置状态栏纯色 不加半透明效果
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
fun setColorNoTranslucent(activity: Activity, @ColorInt color: Int) {
setColor(activity, color, 0)
}
/**
* 设置状态栏颜色(5.0以下无半透明效果,不建议使用)
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
@Deprecated("")
fun setColorDiff(activity: Activity, @ColorInt color: Int) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
transparentStatusBar(activity)
val contentView = activity.findViewById<View>(android.R.id.content) as ViewGroup
// 移除半透明矩形,以免叠加
val fakeStatusBarView = contentView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null) {
if (fakeStatusBarView.visibility == View.GONE) {
fakeStatusBarView.visibility = View.VISIBLE
}
fakeStatusBarView.setBackgroundColor(color)
} else {
contentView.addView(
createStatusBarView(
activity,
color
)
)
}
setRootView(activity)
}
/**
* 使状态栏半透明
*
*
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
*/
fun setTranslucent(activity: Activity) {
setTranslucent(
activity,
DEFAULT_STATUS_BAR_ALPHA
)
}
/**
* 使状态栏半透明
*
*
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
*/
fun setTranslucent(activity: Activity, @IntRange(from = 0, to = 255) statusBarAlpha: Int) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
setTransparent(activity)
addTranslucentView(activity, statusBarAlpha)
}
/**
* 针对根布局是 CoordinatorLayout, 使状态栏半透明
*
*
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
*/
fun setTranslucentForCoordinatorLayout(activity: Activity, @IntRange(from = 0, to = 255) statusBarAlpha: Int) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
transparentStatusBar(activity)
addTranslucentView(activity, statusBarAlpha)
}
/**
* 设置状态栏全透明
*
* @param activity 需要设置的activity
*/
fun setTransparent(activity: Activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
transparentStatusBar(activity)
setRootView(activity)
}
/**
* 使状态栏透明(5.0以上半透明效果,不建议使用)
*
*
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
*/
@Deprecated("")
fun setTranslucentDiff(activity: Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
setRootView(activity)
}
}
/**
* 为DrawerLayout 布局设置状态栏变色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
fun setColorForDrawerLayout(activity: Activity, drawerLayout: DrawerLayout, @ColorInt color: Int) {
setColorForDrawerLayout(
activity,
drawerLayout,
color,
DEFAULT_STATUS_BAR_ALPHA
)
}
/**
* 为DrawerLayout 布局设置状态栏颜色,纯色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
fun setColorNoTranslucentForDrawerLayout(activity: Activity, drawerLayout: DrawerLayout, @ColorInt color: Int) {
setColorForDrawerLayout(activity, drawerLayout, color, 0)
}
/**
* 为DrawerLayout 布局设置状态栏变色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
fun setColorForDrawerLayout(activity: Activity, drawerLayout: DrawerLayout, @ColorInt color: Int,
@IntRange(from = 0, to = 255) statusBarAlpha: Int) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.statusBarColor = Color.TRANSPARENT
} else {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
// 生成一个状态栏大小的矩形
// 添加 statusBarView 到布局中
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
val fakeStatusBarView = contentLayout.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null) {
if (fakeStatusBarView.visibility == View.GONE) {
fakeStatusBarView.visibility = View.VISIBLE
}
fakeStatusBarView.setBackgroundColor(color)
} else {
contentLayout.addView(
createStatusBarView(
activity,
color
), 0)
}
// 内容布局不是 LinearLayout 时,设置padding top
if (contentLayout !is LinearLayout && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1)
.setPadding(contentLayout.paddingLeft, getStatusBarHeight(
activity
) + contentLayout.paddingTop,
contentLayout.paddingRight, contentLayout.paddingBottom)
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout)
addTranslucentView(activity, statusBarAlpha)
}
/**
* 设置 DrawerLayout 属性
*
* @param drawerLayout DrawerLayout
* @param drawerLayoutContentLayout DrawerLayout 的内容布局
*/
private fun setDrawerLayoutProperty(drawerLayout: DrawerLayout, drawerLayoutContentLayout: ViewGroup) {
val drawer = drawerLayout.getChildAt(1) as ViewGroup
drawerLayout.fitsSystemWindows = false
drawerLayoutContentLayout.fitsSystemWindows = false
drawerLayoutContentLayout.clipToPadding = true
drawer.fitsSystemWindows = false
}
/**
* 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用)
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
@Deprecated("")
fun setColorForDrawerLayoutDiff(activity: Activity, drawerLayout: DrawerLayout, @ColorInt color: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
// 生成一个状态栏大小的矩形
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
val fakeStatusBarView = contentLayout.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null) {
if (fakeStatusBarView.visibility == View.GONE) {
fakeStatusBarView.visibility = View.VISIBLE
}
fakeStatusBarView.setBackgroundColor(
calculateStatusColor(
color,
DEFAULT_STATUS_BAR_ALPHA
)
)
} else {
// 添加 statusBarView 到布局中
contentLayout.addView(
createStatusBarView(
activity,
color
), 0)
}
// 内容布局不是 LinearLayout 时,设置padding top
if (contentLayout !is LinearLayout && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1).setPadding(0,
getStatusBarHeight(activity), 0, 0)
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout)
}
}
/**
* 为 DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
fun setTranslucentForDrawerLayout(activity: Activity, drawerLayout: DrawerLayout) {
setTranslucentForDrawerLayout(
activity,
drawerLayout,
DEFAULT_STATUS_BAR_ALPHA
)
}
/**
* 为 DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
fun setTranslucentForDrawerLayout(activity: Activity, drawerLayout: DrawerLayout,
@IntRange(from = 0, to = 255) statusBarAlpha: Int) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
setTransparentForDrawerLayout(activity, drawerLayout)
addTranslucentView(activity, statusBarAlpha)
}
/**
* 为 DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
fun setTransparentForDrawerLayout(activity: Activity, drawerLayout: DrawerLayout) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.statusBarColor = Color.TRANSPARENT
} else {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
// 内容布局不是 LinearLayout 时,设置padding top
if (contentLayout !is LinearLayout && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1).setPadding(0,
getStatusBarHeight(activity), 0, 0)
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout)
}
/**
* 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用)
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
@Deprecated("")
fun setTranslucentForDrawerLayoutDiff(activity: Activity, drawerLayout: DrawerLayout) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
// 设置内容布局属性
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
contentLayout.fitsSystemWindows = true
contentLayout.clipToPadding = true
// 设置抽屉布局属性
val vg = drawerLayout.getChildAt(1) as ViewGroup
vg.fitsSystemWindows = false
// 设置 DrawerLayout 属性
drawerLayout.fitsSystemWindows = false
}
}
/**
* 为头部是 ImageView 的界面设置状态栏全透明
*
* @param activity 需要设置的activity
* @param needOffsetView 需要向下偏移的 View
*/
fun setTransparentForImageView(activity: Activity, needOffsetView: View?) {
setTranslucentForImageView(activity, 0, needOffsetView)
}
/**
* 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度)
*
* @param activity 需要设置的activity
* @param needOffsetView 需要向下偏移的 View
*/
fun setTranslucentForImageView(activity: Activity, needOffsetView: View) {
setTranslucentForImageView(
activity,
DEFAULT_STATUS_BAR_ALPHA,
needOffsetView
)
}
/**
* 为头部是 ImageView 的界面设置状态栏透明
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
* @param needOffsetView 需要向下偏移的 View
*/
fun setTranslucentForImageView(activity: Activity, @IntRange(from = 0, to = 255) statusBarAlpha: Int,
needOffsetView: View?) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return
}
setTransparentForWindow(activity)
addTranslucentView(activity, statusBarAlpha)
if (needOffsetView != null) {
val haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET)
if (haveSetOffset != null && haveSetOffset as Boolean) {
return
}
val layoutParams = needOffsetView.layoutParams as ViewGroup.MarginLayoutParams
layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(
activity
),
layoutParams.rightMargin, layoutParams.bottomMargin)
needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true)
}
}
/**
* 为 fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param needOffsetView 需要向下偏移的 View
*/
fun setTranslucentForImageViewInFragment(activity: Activity, needOffsetView: View) {
setTranslucentForImageViewInFragment(
activity,
DEFAULT_STATUS_BAR_ALPHA,
needOffsetView
)
}
/**
* 为 fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param needOffsetView 需要向下偏移的 View
*/
fun setTransparentForImageViewInFragment(activity: Activity, needOffsetView: View) {
setTranslucentForImageViewInFragment(
activity,
0,
needOffsetView
)
}
/**
* 为 fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param statusBarAlpha 状态栏透明度
* @param needOffsetView 需要向下偏移的 View
*/
fun setTranslucentForImageViewInFragment(activity: Activity, @IntRange(from = 0, to = 255) statusBarAlpha: Int,
needOffsetView: View) {
setTranslucentForImageView(
activity,
statusBarAlpha,
needOffsetView
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
clearPreviousSetting(activity)
}
}
/**
* 隐藏伪状态栏 View
*
* @param activity 调用的 Activity
*/
fun hideFakeStatusBarView(activity: Activity) {
val decorView = activity.window.decorView as ViewGroup
val fakeStatusBarView = decorView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null) {
fakeStatusBarView.visibility = View.GONE
}
val fakeTranslucentView = decorView.findViewById<View>(FAKE_TRANSLUCENT_VIEW_ID)
if (fakeTranslucentView != null) {
fakeTranslucentView.visibility = View.GONE
}
}
///////////////////////////////////////////////////////////////////////////////////
@TargetApi(Build.VERSION_CODES.KITKAT)
private fun clearPreviousSetting(activity: Activity) {
val decorView = activity.window.decorView as ViewGroup
val fakeStatusBarView = decorView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null) {
decorView.removeView(fakeStatusBarView)
val rootView = (activity.findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0) as ViewGroup
rootView.setPadding(0, 0, 0, 0)
}
}
/**
* 添加半透明矩形条
*
* @param activity 需要设置的 activity
* @param statusBarAlpha 透明值
*/
private fun addTranslucentView(activity: Activity, @IntRange(from = 0, to = 255) statusBarAlpha: Int) {
val contentView = activity.findViewById<View>(android.R.id.content) as ViewGroup
val fakeTranslucentView = contentView.findViewById<View>(FAKE_TRANSLUCENT_VIEW_ID)
if (fakeTranslucentView != null) {
if (fakeTranslucentView.visibility == View.GONE) {
fakeTranslucentView.visibility = View.VISIBLE
}
fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0))
} else {
contentView.addView(
createTranslucentStatusBarView(
activity,
statusBarAlpha
)
)
}
}
/**
* 生成一个和状态栏大小相同的彩色矩形条
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
* @return 状态栏矩形条
*/
private fun createStatusBarView(activity: Activity, @ColorInt color: Int): View {
return createStatusBarView(activity, color, 0)
}
/**
* 生成一个和状态栏大小相同的半透明矩形条
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param alpha 透明值
* @return 状态栏矩形条
*/
private fun createStatusBarView(activity: Activity, @ColorInt color: Int, alpha: Int): View {
// 绘制一个和状态栏一样高的矩形
val statusBarView = View(activity)
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity)
)
statusBarView.layoutParams = params
statusBarView.setBackgroundColor(
calculateStatusColor(
color,
alpha
)
)
statusBarView.id = FAKE_STATUS_BAR_VIEW_ID
return statusBarView
}
/**
* 设置根布局参数
*/
private fun setRootView(activity: Activity) {
val parent = activity.findViewById<View>(android.R.id.content) as ViewGroup
var i = 0
val count = parent.childCount
while (i < count) {
val childView = parent.getChildAt(i)
if (childView is ViewGroup) {
childView.setFitsSystemWindows(true)
childView.clipToPadding = true
}
i++
}
}
/**
* 设置透明
*/
private fun setTransparentForWindow(activity: Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.window.statusBarColor = Color.TRANSPARENT
activity.window
.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.window
.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
}
/**
* 使状态栏透明
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
private fun transparentStatusBar(activity: Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
activity.window.statusBarColor = Color.TRANSPARENT
} else {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
}
/**
* 创建半透明矩形 View
*
* @param alpha 透明值
* @return 半透明 View
*/
private fun createTranslucentStatusBarView(activity: Activity, alpha: Int): View {
// 绘制一个和状态栏一样高的矩形
val statusBarView = View(activity)
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity)
)
statusBarView.layoutParams = params
statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0))
statusBarView.id = FAKE_TRANSLUCENT_VIEW_ID
return statusBarView
}
/**
* 获取状态栏高度
*
* @param context context
* @return 状态栏高度
*/
public fun getStatusBarHeight(context: Context): Int {
// 获得状态栏高度
val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
return context.resources.getDimensionPixelSize(resourceId)
}
/**
* 计算状态栏颜色
*
* @param color color值
* @param alpha alpha值
* @return 最终的状态栏颜色
*/
private fun calculateStatusColor(@ColorInt color: Int, alpha: Int): Int {
if (alpha == 0) {
return color
}
val a = 1 - alpha / 255f
var red = color shr 16 and 0xff
var green = color shr 8 and 0xff
var blue = color and 0xff
red = (red * a + 0.5).toInt()
green = (green * a + 0.5).toInt()
blue = (blue * a + 0.5).toInt()
return 0xff shl 24 or (red shl 16) or (green shl 8) or blue
}
//====================设置状态栏黑色字体 by haorui START====================
val OTHER = -1
val MIUI = 1
val FLYME = 2
val ANDROID_M = 3
/**
* 设置状态栏黑色字体图标,
* 适配4.4以上版本MIUI、Flyme和6.0以上版本其他Android
*
* 原生方法不适配6.0的小米
* 魅族方法不适配6.0以上的魅族
*
* @return 1:MIUI 2:Flyme 3:android6.0
*/
fun statusBarLightMode(activity: Activity): Int {
var result = 0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (setStatusBarLightMode(activity, true)) {
result = ANDROID_M
}
if (setMIUIStatusBarLightMode(activity, true)) {
result = MIUI
} else if (setFlymeStatusBarLightMode(activity, true)) {
result = FLYME
}
}
return result
}
/**
* 已知系统类型时,设置状态栏黑色字体图标。
* 适配4.4以上版本MIUI6、Flyme和6.0以上版本其他Android
*
* @param type 1:MIUI 2:Flyme 3:android6.0
*/
fun statusBarLightMode(activity: Activity, type: Int) {
statusBarMode(activity, type, true)
}
/**
* 清除MIUI或flyme或6.0以上版本状态栏黑色字体
*/
fun statusBarDarkMode(activity: Activity, type: Int) {
statusBarMode(activity, type, false)
}
private fun statusBarMode(activity: Activity, type: Int, isFontColorDark: Boolean) {
if (type == MIUI) {
setMIUIStatusBarLightMode(activity, isFontColorDark)
} else if (type == FLYME) {
setFlymeStatusBarLightMode(activity, isFontColorDark)
} else if (type == ANDROID_M) {
setStatusBarLightMode(activity, isFontColorDark)
}
}
fun setStatusBarLightMode(activity: Activity, isFontColorDark: Boolean): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isFontColorDark) {
// 沉浸式
activity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
//非沉浸式
activity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
}
return true
}
return false
}
fun setMIUIStatusBarLightMode(activity: Activity, isFontColorDark: Boolean): Boolean {
val window = activity.window
var result = false
if (window != null) {
val clazz = window.javaClass
try {
var darkModeFlag = 0
val layoutParams = Class.forName("android.view.MiuiWindowManager\$LayoutParams")
val field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE")
darkModeFlag = field.getInt(layoutParams)
val extraFlagField = clazz.getMethod("setExtraFlags", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType)
if (isFontColorDark) {
extraFlagField.invoke(window, darkModeFlag, darkModeFlag)//状态栏透明且黑色字体
} else {
extraFlagField.invoke(window, 0, darkModeFlag)//清除黑色字体
}
result = true
} catch (e: Exception) {
// e.printStackTrace();
}
}
return result
}
/**
* 设置状态栏图标为深色和魅族特定的文字风格
* 可以用来判断是否为Flyme用户
*
* @param isFontColorDark 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
fun setFlymeStatusBarLightMode(activity: Activity, isFontColorDark: Boolean): Boolean {
val window = activity.window
var result = false
if (window != null) {
try {
val lp = window.attributes
val darkFlag = WindowManager.LayoutParams::class.java
.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON")
val meizuFlags = WindowManager.LayoutParams::class.java
.getDeclaredField("meizuFlags")
darkFlag.isAccessible = true
meizuFlags.isAccessible = true
val bit = darkFlag.getInt(null)
var value = meizuFlags.getInt(lp)
if (isFontColorDark) {
value = value or bit
} else {
value = value and bit.inv()
}
meizuFlags.setInt(lp, value)
window.attributes = lp
result = true
} catch (e: Exception) {
// e.printStackTrace();
result = false
}
}
return result
}
//====================设置状态栏黑色字体 by haorui END====================
}
package com.yidianling.ydlcommon.custom.ui.confideredpacket.http package com.yidianling.ydlcommon.custom.ui.confideredpacket.http
import com.yidianling.ydlcommon.custom.http.BaseAPIResponse import com.yidianling.ydlcommon.core.base.config.YDL_DOMAIN
import com.yidianling.ydlcommon.core.base.config.YDL_DOMAIN_JAVA
import io.reactivex.Observable import io.reactivex.Observable
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Url import retrofit2.http.Headers
import retrofit2.http.Query
/** /**
* @author yuanwai * @author yuanwai
...@@ -14,7 +16,7 @@ import retrofit2.http.Url ...@@ -14,7 +16,7 @@ import retrofit2.http.Url
*/ */
interface ConfideRedPacketApi{ interface ConfideRedPacketApi{
//倾诉红包接口 //倾诉红包接口
@retrofit2.http.Headers("Content-Type:application/json") @Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA,"Content-Type:application/json")
@GET @GET("auth/coupon/max")
fun getCouponMax(@Url url: String): Observable<com.yidianling.ydlcommon.custom.http.BaseAPIResponse<String>> fun getCouponMax(@Query("serviceType") serviceType :String ): Observable<com.yidianling.ydlcommon.custom.http.BaseAPIResponse<String>>
} }
\ No newline at end of file
package com.yidianling.ydlcommon.custom.ui.confideredpacket.http package com.yidianling.ydlcommon.custom.ui.confideredpacket.http
import com.ydl.ydlnet.YDLHttpUtils
import com.yidianling.ydlcommon.custom.http.RxUtils import com.yidianling.ydlcommon.custom.http.RxUtils
import com.yidianling.ydlcommon.custom.ui.confideredpacket.RedListParam import com.yidianling.ydlcommon.custom.ui.confideredpacket.RedListParam
import io.reactivex.Observable import io.reactivex.Observable
...@@ -26,19 +27,13 @@ class ConfideRedPacketHttpImpl private constructor() : ...@@ -26,19 +27,13 @@ class ConfideRedPacketHttpImpl private constructor() :
} }
private val confideHomeApi: ConfideRedPacketApi by lazy { private val confideHomeApi: ConfideRedPacketApi by lazy {
com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.getRxRetrofit().newBuilder().baseUrl(com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.SERVER_API_JAVA_URL).build().create( YDLHttpUtils.obtainApi(ConfideRedPacketApi::class.java)
ConfideRedPacketApi::class.java)
} }
override fun getCouponMax(param: RedListParam): Observable<com.yidianling.ydlcommon.custom.http.BaseAPIResponse<String>> { override fun getCouponMax(param: RedListParam): Observable<com.yidianling.ydlcommon.custom.http.BaseAPIResponse<String>> {
val sb = StringBuffer()
sb.append("serviceType").append("=").append(param.serviceType).append("&")
val confideParam = sb.toString() + com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.getCommonParam()
return RxUtils.mapObservable(param) return RxUtils.mapObservable(param)
.flatMap { .flatMap {
// confideHomeApi.getCouponMax(BuildConfig.SERVER_JAVA_API_URL + "auth/coupon/max?"+confideParam) confideHomeApi.getCouponMax(param.serviceType.toString())
confideHomeApi.getCouponMax(com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.SERVER_API_JAVA_URL + "auth/coupon/max?" + confideParam)
} }
} }
} }
\ No newline at end of file
package com.yidianling.ydlcommon.custom.ui.couponhint.http package com.yidianling.ydlcommon.custom.ui.couponhint.http
import com.yidianling.ydlcommon.custom.http.BaseAPIResponse import com.ydl.ydlnet.YDLHttpUtils
import com.yidianling.ydlcommon.custom.http.RxUtils import com.yidianling.ydlcommon.custom.http.RxUtils
import com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils
import com.yidianling.ydlcommon.custom.ui.couponhint.CouponHintParam import com.yidianling.ydlcommon.custom.ui.couponhint.CouponHintParam
import com.yidianling.ydlcommon.custom.ui.couponhint.CouponHintResponseBean import com.yidianling.ydlcommon.custom.ui.couponhint.CouponHintResponseBean
import io.reactivex.Observable import io.reactivex.Observable
...@@ -27,8 +26,7 @@ class CouponHintHttpImpl private constructor(): ICouponHintHttp { ...@@ -27,8 +26,7 @@ class CouponHintHttpImpl private constructor(): ICouponHintHttp {
} }
private val couponHintApi: CouponHintApi by lazy { private val couponHintApi: CouponHintApi by lazy {
com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.getRxRetrofit().newBuilder().baseUrl(com.yidianling.ydlcommon.custom.http.YdlRetrofitUtils.SERVER_API_JAVA_URL).build().create( YDLHttpUtils.obtainApi(CouponHintApi::class.java)
CouponHintApi::class.java)
} }
override fun getCouponHint(param: CouponHintParam): Observable<com.yidianling.ydlcommon.custom.http.BaseAPIResponse<CouponHintResponseBean>> { override fun getCouponHint(param: CouponHintParam): Observable<com.yidianling.ydlcommon.custom.http.BaseAPIResponse<CouponHintResponseBean>> {
......
...@@ -10,7 +10,7 @@ import android.provider.Settings ...@@ -10,7 +10,7 @@ import android.provider.Settings
import android.support.v4.content.FileProvider import android.support.v4.content.FileProvider
import com.tbruyelle.rxpermissions2.RxPermissions import com.tbruyelle.rxpermissions2.RxPermissions
import com.yidianling.common.tools.ToastUtil import com.yidianling.common.tools.ToastUtil
import com.yidianling.ydlcommon.custom.data.VersionData import com.yidianling.ydlcommon.custom.bean.VersionData
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
...@@ -28,11 +28,11 @@ class ApkInstallTool { ...@@ -28,11 +28,11 @@ class ApkInstallTool {
private var listener: UpdateProgressListener? = null private var listener: UpdateProgressListener? = null
private var updateData: com.yidianling.ydlcommon.custom.data.VersionData? = null private var updateData: VersionData? = null
private var isDownload = true private var isDownload = true
fun start(activity : Activity?, version: com.yidianling.ydlcommon.custom.data.VersionData?, listener: UpdateProgressListener?){ fun start(activity : Activity?, version: VersionData?, listener: UpdateProgressListener?){
this.activity = activity this.activity = activity
this.listener = listener this.listener = listener
this.updateData = version this.updateData = version
......
...@@ -7,7 +7,7 @@ import android.view.View ...@@ -7,7 +7,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.yidianling.common.tools.RxDeviceTool import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.data.VersionData import com.yidianling.ydlcommon.custom.bean.VersionData
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import kotlinx.android.synthetic.main.dialog_update_layout.* import kotlinx.android.synthetic.main.dialog_update_layout.*
...@@ -21,7 +21,7 @@ class ApkUpdateDialog : Dialog{ ...@@ -21,7 +21,7 @@ class ApkUpdateDialog : Dialog{
private var listener: ApkInstallTool.UpdateProgressListener? = null private var listener: ApkInstallTool.UpdateProgressListener? = null
private var updateData : com.yidianling.ydlcommon.custom.data.VersionData? = null private var updateData : VersionData? = null
private var activity : Activity? = null private var activity : Activity? = null
...@@ -106,7 +106,7 @@ class ApkUpdateDialog : Dialog{ ...@@ -106,7 +106,7 @@ class ApkUpdateDialog : Dialog{
setCanceledOnTouchOutside(false) setCanceledOnTouchOutside(false)
} }
fun setData(data : com.yidianling.ydlcommon.custom.data.VersionData?): ApkUpdateDialog { fun setData(data : VersionData?): ApkUpdateDialog {
updateData = data updateData = data
return this return this
} }
......
package com.yidianling.ydlcommon.custom.tool; package com.yidianling.ydlcommon.custom.utils;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
...@@ -7,7 +7,7 @@ import com.meituan.android.walle.WalleChannelReader; ...@@ -7,7 +7,7 @@ import com.meituan.android.walle.WalleChannelReader;
import com.yidianling.ydlcommon.core.base.BaseApplication; import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.LogUtil; import com.yidianling.common.tools.LogUtil;
import com.yidianling.ydlcommon.BuildConfig; import com.yidianling.ydlcommon.BuildConfig;
import com.yidianling.ydlcommon.custom.data.YdlDataManager; import com.yidianling.ydlcommon.custom.data.PlatformDataManager;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
...@@ -100,7 +100,7 @@ public class BuryPointUtils { ...@@ -100,7 +100,7 @@ public class BuryPointUtils {
} }
private static String getShareTitle() { private static String getShareTitle() {
String ffrom = YdlDataManager.INSTANCE.getRam().getChannelName(); String ffrom = PlatformDataManager.INSTANCE.getRam().getChannelName();
if (ffrom.startsWith("ATK_3")) { if (ffrom.startsWith("ATK_3")) {
return "秘密倾诉"; return "秘密倾诉";
} else if (ffrom.startsWith("ATK_4")) { } else if (ffrom.startsWith("ATK_4")) {
......
package com.yidianling.ydlcommon.custom.utils;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.util.Base64;
import com.yidianling.common.tools.ToastUtil;
import java.io.*;
public class ImageUtil {
public static boolean savePicture(Context context, String base64DataStr) {
// 去掉base64中的前缀
// String base64Str = base64DataStr.substring(base64DataStr.indexOf(",")+1, base64DataStr.length());
File appDir = new File(Environment.getExternalStorageDirectory(), "Camera");// 图片保存的文件夹的名称
if (!appDir.exists()) {
appDir.mkdir();
}
String imgName = System.currentTimeMillis() + ".png";
File fileTest = new File(appDir, imgName);
byte[] data = Base64.decode(base64DataStr, Base64.DEFAULT);
for (int i = 0; i < data.length; i++) {
if (data[i] < 0) {
data[i] += 256;//调整异常数据
}
}
OutputStream os = null;
try {
os = new FileOutputStream(fileTest);
os.write(data);
os.flush();
os.close();
// 通知系统刷新图库
updateAlbum(context, fileTest);
ToastUtil.toastShort("图片已保存至相册");
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
ToastUtil.toastShort("保存失败");
return false;
} catch (IOException e) {
e.printStackTrace();
ToastUtil.toastShort("保存失败");
return false;
}
}
/**
* 通知图库更新数据
* context
* fileName
* file
*/
private static void updateAlbum(Context context, File file) {
// 最后通知图库更新
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
}
}
package com.yidianling.ydlcommon.custom.tool package com.yidianling.ydlcommon.custom.utils
//import cn.jpush.android.api.JPushInterface //import cn.jpush.android.api.JPushInterface
......
...@@ -17,8 +17,8 @@ import android.widget.EditText; ...@@ -17,8 +17,8 @@ import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import com.yidianling.ydlcommon.R; import com.yidianling.ydlcommon.R;
import com.yidianling.ydlcommon.custom.emoji.EmojiManager; import com.yidianling.ydlcommon.custom.utils.emoji.EmojiManager;
import com.yidianling.ydlcommon.custom.emoji.ImageSpanAlignCenter; import com.yidianling.ydlcommon.custom.utils.emoji.ImageSpanAlignCenter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Matcher; import java.util.regex.Matcher;
......
package com.yidianling.ydlcommon.custom.utils;
import com.yidianling.ydlcommon.custom.http.BaseCommand;
import com.yidianling.ydlcommon.custom.http.FormatText;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by haorui on 2019-09-19.
* Des:
*/
public class NetworkParamsUtils {
public static List<FormatText> getPostList(BaseCommand crq) {
List<FormatText> formTextList = new ArrayList<>();
Field[] fields = crq.getClass().getFields();
for (Field field : fields) {
try {
boolean accessFlag = field.isAccessible();
field.setAccessible(true);
Object o = field.get(crq);
if (o != null) {
FormatText formatText;
formatText = new FormatText(field.getName(), String.valueOf(o));
formTextList.add(formatText);
}
field.setAccessible(accessFlag);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return formTextList;
}
//获取网络请求表
public static Map<String, String> getMaps(List<FormatText> list) {
Map<String, String> map = new HashMap<>();
int size = list.size();
for (int i = 0; i < size; i++) {
FormatText formatText = list.get(i);
map.put(formatText.getmKey(), String.valueOf(formatText.getmValue()));
}
return map;
}
}
...@@ -9,7 +9,7 @@ import android.view.Gravity ...@@ -9,7 +9,7 @@ import android.view.Gravity
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import com.yidianling.common.tools.RxImageTool import com.yidianling.common.tools.RxImageTool
import com.yidianling.ydlcommon.custom.player.YDLMusicHelper import com.yidianling.ydlcommon.custom.actions.player.YDLMusicHelper
import com.yidianling.ydlcommon.custom.view.PlayerFloatView import com.yidianling.ydlcommon.custom.view.PlayerFloatView
/** /**
......
package com.yidianling.ydlcommon.custom.tool; package com.yidianling.ydlcommon.custom.utils;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
......
package com.yidianling.ydlcommon.custom.tool; package com.yidianling.ydlcommon.custom.utils;
import android.text.TextUtils; import android.text.TextUtils;
......
package com.yidianling.ydlcommon.custom.tool; package com.yidianling.ydlcommon.custom.utils;
import java.util.HashMap; import java.util.HashMap;
......
...@@ -4,7 +4,6 @@ import android.net.Uri; ...@@ -4,7 +4,6 @@ import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import com.yidianling.ydlcommon.custom.http.GsonProvider; import com.yidianling.ydlcommon.custom.http.GsonProvider;
import com.yidianling.ydlcommon.custom.tool.StringUtils;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI; import java.net.URI;
......
...@@ -19,7 +19,6 @@ import android.view.WindowManager; ...@@ -19,7 +19,6 @@ import android.view.WindowManager;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.yidianling.ydlcommon.core.base.BaseApplication; import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.ydlcommon.custom.tool.StringUtils;
import com.yidianling.ydlcommon.custom.view.CenterAlignImageSpan; import com.yidianling.ydlcommon.custom.view.CenterAlignImageSpan;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
......
...@@ -5,7 +5,7 @@ import android.util.Base64; ...@@ -5,7 +5,7 @@ import android.util.Base64;
import android.util.Log; import android.util.Log;
import com.yidianling.ydlcommon.core.base.BaseApplication; import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.protector.AppProtectorLib; import com.yidianling.protector.AppProtectorLib;
import com.yidianling.ydlcommon.custom.remind.ToastHelper; import com.yidianling.ydlcommon.custom.utils.remind.ToastHelper;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
......
package com.yidianling.ydlcommon.custom.emoji package com.yidianling.ydlcommon.custom.utils.emoji
import android.content.Context import android.content.Context
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.widget.EditText import android.widget.EditText
import com.yidianling.ydlcommon.custom.tool.StringUtils import com.yidianling.ydlcommon.custom.utils.StringUtils
import com.yidianling.ydlcommon.custom.utils.MoonUtil
/** /**
* editText 过滤emoji工具 * editText 过滤emoji工具
...@@ -23,7 +22,7 @@ object EmojiFilterUtil{ ...@@ -23,7 +22,7 @@ object EmojiFilterUtil{
this.start = start this.start = start
this.count = count this.count = count
val editable = editContent.getText().toString() val editable = editContent.getText().toString()
val str = com.yidianling.ydlcommon.custom.tool.StringUtils.StringFilter(editable.toString()) val str = StringUtils.StringFilter(editable.toString())
if (editable != str) { if (editable != str) {
editContent.setText(str) editContent.setText(str)
editContent.setSelection(str.length) //光标置后 editContent.setSelection(str.length) //光标置后
...@@ -39,7 +38,7 @@ object EmojiFilterUtil{ ...@@ -39,7 +38,7 @@ object EmojiFilterUtil{
com.yidianling.ydlcommon.custom.utils.MoonUtil.replaceEmoticons(context, arg0, start, count) com.yidianling.ydlcommon.custom.utils.MoonUtil.replaceEmoticons(context, arg0, start, count)
var editEnd = editContent.getSelectionEnd() var editEnd = editContent.getSelectionEnd()
editContent.removeTextChangedListener(this) editContent.removeTextChangedListener(this)
while (com.yidianling.ydlcommon.custom.tool.StringUtils.counterChars(arg0.toString()) > 5000 && editEnd > 0) { while (StringUtils.counterChars(arg0.toString()) > 5000 && editEnd > 0) {
arg0.delete(editEnd - 1, editEnd) arg0.delete(editEnd - 1, editEnd)
editEnd-- editEnd--
} }
......
package com.yidianling.ydlcommon.custom.emoji; package com.yidianling.ydlcommon.custom.utils.emoji;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
......
package com.yidianling.ydlcommon.custom.emoji; package com.yidianling.ydlcommon.custom.utils.emoji;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
......
package com.yidianling.ydlcommon.custom.log package com.yidianling.ydlcommon.custom.utils.log
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.common.tools.* import com.yidianling.common.tools.*
import com.yidianling.ydlcommon.custom.data.YdlDataManager import com.yidianling.ydlcommon.core.base.BaseApplication
import com.yidianling.ydlcommon.custom.data.PlatformDataManager
import com.yidianling.ydlcommon.custom.http.LogParam import com.yidianling.ydlcommon.custom.http.LogParam
import com.yidianling.ydlcommon.custom.http.ThrowableConsumer import com.yidianling.ydlcommon.custom.http.ThrowableConsumer
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager
...@@ -111,7 +111,7 @@ class LogHelper private constructor() { ...@@ -111,7 +111,7 @@ class LogHelper private constructor() {
it.onNext(zip()) it.onNext(zip())
it.onComplete() it.onComplete()
}.subscribeOn(Schedulers.io()) }.subscribeOn(Schedulers.io())
.flatMap { YdlDataManager.getHttp().uploadLog( .flatMap { PlatformDataManager.getHttp().uploadLog(
LogParam( LogParam(
it it
) )
......
package com.yidianling.ydlcommon.custom.receiver; package com.yidianling.ydlcommon.custom.utils.receiver;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
......
package com.yidianling.ydlcommon.custom.remind package com.yidianling.ydlcommon.custom.utils.remind
import android.support.annotation.StringRes import android.support.annotation.StringRes
import android.text.TextUtils import android.text.TextUtils
......
package com.yidianling.ydlcommon.custom.view
import android.content.Context
import android.text.Spannable
import android.text.SpannableString
import android.text.TextUtils
import android.text.style.AbsoluteSizeSpan
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.yidianling.common.tools.RxImageTool
import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.bean.CourseButtonBean
import kotlinx.android.synthetic.main.view_course_detail_bottom.view.*
/**
* @author jiucheng
* @描述: 课程详情页底部view
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/7/10
*/
class CourseDetailBottomView : LinearLayout {
private var mContext: Context? = null
private var listener: OnBottomClickListener? = null
constructor(context: Context) : super(context) {
mContext = context
initView()
}
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) {
mContext = context
initView()
}
init {
orientation = VERTICAL
}
private fun initView() {
var parmas = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, RxImageTool.dp2px(56f))
parmas.gravity = Gravity.CENTER_VERTICAL
layoutParams = parmas
View.inflate(mContext, R.layout.view_course_detail_bottom, this)
}
fun setData(bean: CourseButtonBean?) {
if (bean == null) {
visibility = View.GONE
return
}
visibility = View.VISIBLE
tv_button.isEnabled = bean.type
var text = if (!TextUtils.isEmpty(bean.signUpTime)) {
bean.desc + "\n" + bean.signUpTime
} else {
bean.desc
}
val sp = SpannableString(text)
sp.setSpan(AbsoluteSizeSpan(12, true), bean.desc.length, text.length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
tv_button.text = text
tv_share_back.visibility = if (bean.isRebate == "0") View.GONE else View.VISIBLE
tv_to_top.setOnClickListener {
if (listener != null) {
listener!!.goTopClick()
}
}
tv_share_back.setOnClickListener {
if (listener != null) {
listener!!.shareClick()
}
}
tv_button.setOnClickListener {
if (listener != null) {
listener!!.enterButtonClick()
}
}
}
fun setListener(listener: OnBottomClickListener) {
this.listener = listener
}
interface OnBottomClickListener {
fun goTopClick()
fun shareClick()
fun enterButtonClick()
}
}
\ No newline at end of file
...@@ -9,8 +9,7 @@ import android.view.View ...@@ -9,8 +9,7 @@ import android.view.View
import android.widget.PopupWindow import android.widget.PopupWindow
import android.widget.RelativeLayout import android.widget.RelativeLayout
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.data.YdlDataManager import com.yidianling.ydlcommon.custom.data.PlatformDataManager
import com.yidianling.ydlcommon.custom.dialog.CommonDialog
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager
import kotlinx.android.synthetic.main.ui_new_more.view.* import kotlinx.android.synthetic.main.ui_new_more.view.*
...@@ -22,8 +21,8 @@ class MoreClickView @JvmOverloads constructor(private val mContext: Context, att ...@@ -22,8 +21,8 @@ class MoreClickView @JvmOverloads constructor(private val mContext: Context, att
private var mPopupWindow: PopupWindow? = null private var mPopupWindow: PopupWindow? = null
private val work_time = if (YdlDataManager.getRam().getGlobalInfo() == null) "早8:30-凌晨2:00" else YdlDataManager.getRam().getGlobalInfo()?.info?.work_time private val work_time = if (PlatformDataManager.getRam().getGlobalInfo() == null) "早8:30-凌晨2:00" else PlatformDataManager.getRam().getGlobalInfo()?.info?.work_time
private val tel = if (YdlDataManager.getRam().getGlobalInfo() == null) "400-114-1010'" else YdlDataManager.getRam().getGlobalInfo()?.info?.tel private val tel = if (PlatformDataManager.getRam().getGlobalInfo() == null) "400-114-1010'" else PlatformDataManager.getRam().getGlobalInfo()?.info?.tel
init { init {
View.inflate(mContext, R.layout.ui_new_more, this) View.inflate(mContext, R.layout.ui_new_more, this)
...@@ -63,7 +62,7 @@ class MoreClickView @JvmOverloads constructor(private val mContext: Context, att ...@@ -63,7 +62,7 @@ class MoreClickView @JvmOverloads constructor(private val mContext: Context, att
} }
private fun setMoreMsg() { private fun setMoreMsg() {
if (YdlDataManager.getRam().getChannelName().startsWith("ATK_3")) { if (PlatformDataManager.getRam().getChannelName().startsWith("ATK_3")) {
YdlCommonRouterManager.getYdlCommonRoute()?.startMain(context, 2, null) YdlCommonRouterManager.getYdlCommonRoute()?.startMain(context, 2, null)
} else { } else {
YdlCommonRouterManager.getYdlCommonRoute()?.startMain(context, 3, null) YdlCommonRouterManager.getYdlCommonRoute()?.startMain(context, 3, null)
...@@ -89,8 +88,8 @@ class MoreClickView @JvmOverloads constructor(private val mContext: Context, att ...@@ -89,8 +88,8 @@ class MoreClickView @JvmOverloads constructor(private val mContext: Context, att
} }
private fun setMoreRay() { private fun setMoreRay() {
com.yidianling.ydlcommon.custom.dialog.CommonDialog(context) com.yidianling.ydlcommon.custom.view.dialog.CommonDialog(context)
.setMessage("欢迎致电壹点灵客服热线\n" + YdlDataManager.getRam().getGlobalInfo()?.info?.tel + "\n服务时间:" + work_time) .setMessage("欢迎致电壹点灵客服热线\n" + PlatformDataManager.getRam().getGlobalInfo()?.info?.tel + "\n服务时间:" + work_time)
.setLeftOnclick("取消", null) .setLeftOnclick("取消", null)
.setRightClick("拨打") { .setRightClick("拨打") {
if (null != tel && !TextUtils.isEmpty(tel)) { if (null != tel && !TextUtils.isEmpty(tel)) {
......
...@@ -17,9 +17,9 @@ import com.dou361.ijkplayer.widget.PlayerView ...@@ -17,9 +17,9 @@ import com.dou361.ijkplayer.widget.PlayerView
import com.ydl.ydl_image.module.GlideApp import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydl_image.transform.GlideRoundTransform import com.ydl.ydl_image.transform.GlideRoundTransform
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.player.YDLMusicHelper import com.yidianling.ydlcommon.custom.actions.player.YDLMusicHelper
import com.yidianling.ydlcommon.custom.player.YDLMusicPlayer import com.yidianling.ydlcommon.custom.actions.player.YDLMusicPlayer
import com.yidianling.ydlcommon.custom.player.util.UtilH import com.yidianling.ydlcommon.custom.actions.player.util.UtilH
import tv.danmaku.ijk.media.player.IMediaPlayer import tv.danmaku.ijk.media.player.IMediaPlayer
import java.util.* import java.util.*
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
......
package com.yidianling.ydlcommon.custom.dialog; package com.yidianling.ydlcommon.custom.view.dialog;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
......
package com.yidianling.ydlcommon.custom.dialog package com.yidianling.ydlcommon.custom.view.dialog
import android.app.Activity import android.app.Activity
import android.app.Dialog import android.app.Dialog
...@@ -9,10 +9,8 @@ import android.widget.AdapterView ...@@ -9,10 +9,8 @@ import android.widget.AdapterView
import android.widget.ImageView import android.widget.ImageView
import com.umeng.socialize.bean.SHARE_MEDIA import com.umeng.socialize.bean.SHARE_MEDIA
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.adapter.CommonAdapter import com.yidianling.ydlcommon.custom.actions.share.ShareMoreBean
import com.yidianling.ydlcommon.custom.share.ShareMoreBean import com.yidianling.ydlcommon.custom.actions.share.ShareUtils
import com.yidianling.ydlcommon.custom.share.ShareUtils
import com.yidianling.ydlcommon.custom.view.BaseViewHolder
import kotlinx.android.synthetic.main.share_custom_ui.* import kotlinx.android.synthetic.main.share_custom_ui.*
/** /**
......
package com.yidianling.ydlcommon.custom.dialog; package com.yidianling.ydlcommon.custom.view.dialog;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
......
package com.yidianling.ydlcommon.custom.dialog; package com.yidianling.ydlcommon.custom.view.dialog;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
......
package com.yidianling.ydlcommon.custom.dialog; package com.yidianling.ydlcommon.custom.view.dialog;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
......
package com.yidianling.ydlcommon.custom.dialog package com.yidianling.ydlcommon.custom.view.dialog
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
...@@ -14,10 +14,9 @@ import com.umeng.socialize.bean.SHARE_MEDIA ...@@ -14,10 +14,9 @@ import com.umeng.socialize.bean.SHARE_MEDIA
import com.ydl.ydl_image.module.GlideApp import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.RxImageTool import com.yidianling.common.tools.RxImageTool
import com.yidianling.ydlcommon.R import com.yidianling.ydlcommon.R
import com.yidianling.ydlcommon.custom.picker.util.ImageUtil import com.yidianling.ydlcommon.custom.actions.share.ShareActionCallBack
import com.yidianling.ydlcommon.custom.share.ShareActionCallBack import com.yidianling.ydlcommon.custom.actions.share.ShareUtils
import com.yidianling.ydlcommon.custom.share.ShareUtils import com.yidianling.ydlcommon.custom.utils.ImageUtil
import com.yidianling.ydlcommon.custom.utils.ScreenUtil
import kotlinx.android.synthetic.main.dialog_share.* import kotlinx.android.synthetic.main.dialog_share.*
import java.util.concurrent.Executors import java.util.concurrent.Executors
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment