├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── person.jpg
│ │ │ │ ├── waiting.png
│ │ │ │ ├── welcome.jpg
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── waiting_bg.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable
│ │ │ │ ├── cursor_bg.xml
│ │ │ │ ├── image_progress.xml
│ │ │ │ ├── shape_edit_bg.xml
│ │ │ │ ├── shape_grey_pressed.xml
│ │ │ │ ├── shape_grey_normal.xml
│ │ │ │ ├── btn_grey_selector.xml
│ │ │ │ └── ic_launcher_background.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ ├── activity_about2.xml
│ │ │ │ ├── viewpager_indicator_tab.xml
│ │ │ │ ├── activity_welcome.xml
│ │ │ │ ├── dialog_waiting.xml
│ │ │ │ ├── viewpager_indicator_layout.xml
│ │ │ │ ├── fragment_left_menu.xml
│ │ │ │ ├── activity_about.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── fragment_index_layout.xml
│ │ │ │ ├── fragment_work_layout.xml
│ │ │ │ └── fragment_sorry_layout.xml
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ └── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── oyy
│ │ │ │ └── strong
│ │ │ │ ├── entity
│ │ │ │ ├── GifBean.kt
│ │ │ │ └── Subtitles.kt
│ │ │ │ ├── view
│ │ │ │ ├── drawer
│ │ │ │ │ ├── DrawerLayoutImpl.java
│ │ │ │ │ └── DrawerLayoutCompatApi21.java
│ │ │ │ ├── CustomViewPager.java
│ │ │ │ ├── WaitingDialog.java
│ │ │ │ └── ViewPagerIndicator.java
│ │ │ │ ├── utils
│ │ │ │ ├── Constant.java
│ │ │ │ ├── NetWorkUtil.kt
│ │ │ │ ├── Utils.java
│ │ │ │ ├── ShareUtils.java
│ │ │ │ ├── DensityUtil.java
│ │ │ │ ├── ImageHandlerUtils.java
│ │ │ │ ├── DataCleanManagerUtils.java
│ │ │ │ └── PermissionUtil.java
│ │ │ │ ├── http
│ │ │ │ ├── APIService.kt
│ │ │ │ └── RetrofitManager.kt
│ │ │ │ ├── ui
│ │ │ │ ├── AboutActivity.kt
│ │ │ │ ├── WelcomeActivity.kt
│ │ │ │ ├── fragment
│ │ │ │ │ ├── BaseV4Fragment.java
│ │ │ │ │ ├── LeftMenuFragment.kt
│ │ │ │ │ ├── IndexFragment.kt
│ │ │ │ │ ├── WorkFragment.kt
│ │ │ │ │ └── SorryFragment.kt
│ │ │ │ └── MainActivity.kt
│ │ │ │ ├── BaseApplication.java
│ │ │ │ └── adapter
│ │ │ │ └── TabAdapter.kt
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── oyy
│ │ │ └── strong
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── oyy
│ │ └── strong
│ │ └── ExampleInstrumentedTest.kt
├── release
│ └── output.json
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── screenshots
├── clear.jpg
├── gifShow.gif
├── index.jpg
├── start.gif
├── welcome.jpg
└── left_menu.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── README.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/screenshots/clear.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/screenshots/clear.jpg
--------------------------------------------------------------------------------
/screenshots/gifShow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/screenshots/gifShow.gif
--------------------------------------------------------------------------------
/screenshots/index.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/screenshots/index.jpg
--------------------------------------------------------------------------------
/screenshots/start.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/screenshots/start.gif
--------------------------------------------------------------------------------
/screenshots/welcome.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/screenshots/welcome.jpg
--------------------------------------------------------------------------------
/screenshots/left_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/screenshots/left_menu.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/person.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-xhdpi/person.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/waiting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-xhdpi/waiting.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/welcome.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-xhdpi/welcome.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/waiting_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-xhdpi/waiting_bg.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niyige/StrongApp/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/app/release/output.json:
--------------------------------------------------------------------------------
1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1},"path":"app-release.apk","properties":{"packageId":"com.oyy.strong","split":"","minSdkVersion":"19"}}]
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/entity/GifBean.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.entity
2 |
3 | /**
4 | * 返回gif动态图对象实体
5 | * Created by
6 | * ouyangyi on 18/5/22.
7 | */
8 | data class GifBean(var code: String, var result: String)
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/entity/Subtitles.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.entity
2 |
3 | /**
4 | * Created by
5 | * ouyangyi on 18/4/26.
6 | */
7 | data class Subtitles(var templateName: String, var sentence: String, var mode: String)
--------------------------------------------------------------------------------
/app/src/main/res/drawable/cursor_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/image_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_edit_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Apr 24 10:26:33 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_grey_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/view/drawer/DrawerLayoutImpl.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.view.drawer;
2 |
3 | /**
4 | * Interface used to communicate from the v21-specific code for configuring a DrawerLayout
5 | * to the DrawerLayout itself.
6 | */
7 | interface DrawerLayoutImpl {
8 | void setChildInsets(Object insets, boolean drawStatusBar);
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_grey_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/Constant.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils;
2 |
3 | import android.os.Environment;
4 |
5 | import java.io.File;
6 |
7 | public class Constant {
8 |
9 | public static final String BASE_PATH = Environment.getExternalStorageDirectory()
10 | + File.separator + "com.oyy.strong" + File.separator + "imageFile";
11 |
12 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_grey_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/test/java/com/oyy/strong/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_about2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/viewpager_indicator_tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/http/APIService.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.http
2 |
3 | import com.oyy.strong.entity.GifBean
4 | import com.oyy.strong.entity.Subtitles
5 | import retrofit2.http.Body
6 | import retrofit2.http.Headers
7 | import retrofit2.http.POST
8 | import rx.Observable
9 |
10 | /**
11 | * Created by
12 | * ouyangyi on 18/5/22.
13 | */
14 | interface APIService {
15 | @Headers("Cache-Control: public, max-age=60 * 60 * 24 * 7")
16 | @POST("/app/gifCreate/filePath")
17 | fun getGifPath(@Body subtitles: Subtitles): Observable
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/AboutActivity.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.ui
2 |
3 | import android.os.Bundle
4 | import android.support.v7.app.AppCompatActivity
5 | import com.oyy.strong.R
6 | import kotlinx.android.synthetic.main.activity_about.*
7 | import org.jetbrains.anko.onClick
8 |
9 | class AboutActivity : AppCompatActivity() {
10 |
11 | override fun onCreate(savedInstanceState: Bundle?) {
12 | super.onCreate(savedInstanceState)
13 | setContentView(R.layout.activity_about)
14 |
15 | backText.onClick {
16 | finish()
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/BaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong;
2 |
3 | import android.app.Application;
4 |
5 | /**
6 | * Created by
7 | * ouyangyi on 18/4/26.
8 | */
9 |
10 | public class BaseApplication extends Application{
11 |
12 | private static BaseApplication instance;
13 |
14 | @Override
15 | public void onCreate() {
16 | super.onCreate();
17 | instance = this;
18 | }
19 |
20 | public static synchronized BaseApplication getInstance() {
21 | if (instance == null)
22 | instance = new BaseApplication();
23 | return instance;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/NetWorkUtil.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils
2 |
3 | import com.oyy.strong.BaseApplication
4 | import android.content.Context
5 | import android.net.ConnectivityManager
6 |
7 | /**
8 | * Created by
9 | * ouyangyi on 18/4/26.
10 | */
11 | class NetWorkUtil {
12 | companion object {
13 | fun isNetWorkConnected(): Boolean {
14 | val cm = BaseApplication.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
15 | val currentNet = cm.activeNetworkInfo ?: return false
16 | return currentNet.isAvailable
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/WelcomeActivity.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.ui
2 |
3 | import android.os.Bundle
4 | import android.os.Handler
5 | import android.support.v7.app.AppCompatActivity
6 | import com.oyy.strong.R
7 | import org.jetbrains.anko.startActivity
8 |
9 | class WelcomeActivity : AppCompatActivity() {
10 |
11 |
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | setContentView(R.layout.activity_welcome)
15 |
16 | Handler().postDelayed({
17 | startActivity()
18 | finish()
19 | }, 2000)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/adapter/TabAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.manqian.crm.adapter
2 |
3 | import android.support.v4.app.Fragment
4 | import android.support.v4.app.FragmentManager
5 | import android.support.v4.app.FragmentPagerAdapter
6 | import java.util.*
7 |
8 | /**
9 | * Created by
10 | * ouyangyi on 18/5/23.
11 | */
12 |
13 | class TabAdapter(fm: FragmentManager, private var fragments: ArrayList) : FragmentPagerAdapter(fm) {
14 | internal var fm: FragmentManager? = null
15 |
16 | override fun getItem(position: Int): Fragment {
17 | return fragments[position]
18 | }
19 |
20 | override fun getCount(): Int {
21 | return fragments.size
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_welcome.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/oyy/strong/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.oyy.strong", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 | #999999
8 | #666666
9 |
10 | #d4d4d4
11 | #dadada
12 |
13 | #333333
14 |
15 | #cccccc
16 |
17 | #ff3254
18 |
19 | #ffffff
20 | #00ffffff
21 |
22 |
23 | #f2f2f2
24 |
25 | #EEF5F7
26 |
27 | #DB3ba134
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_waiting.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 逗斗
2 | 为斗图而生,斗图不断,装逼不止。
3 | app体验: https://www.pgyer.com/5VoD
4 |
5 | #技术要点
6 | 1. android原生跟kotlin混合开发
7 | 2. gif图生成需要后台配合,关键技术:ffmpeg
8 | 3. app内部加载gif图,使用的 glide
9 | 4. 网络请求用的retrofit + rx.java
10 | 5. 思路是参考sorry(https://github.com/xtyxtyx/sorry), java后台参考的是sorryJava(https://github.com/li24361/sorryJava)
11 | 6. 完成该内容需要:app + 管理后台 +文件存储(本人用的是腾讯云的存储桶)
12 |
13 | #版本1.0
14 | 目前只提供王境泽,为所欲为,打工 三类,文字可以自己输入配合图片生成一张gif
15 | 图,拿去装逼吧~
16 |
17 | #部分页面预览
18 | 这是欢迎页面:
19 | 
20 |
21 | 首页在这:
22 | 
23 |
24 | #操作:
25 |
26 | 
27 |
28 | #开图:
29 | 
30 |
31 | #tips:
32 | 这个时候QQ里面长按点击转发,就成了正常的表情包了
33 |
34 | 清除缓存(android手机你懂的):
35 | 
36 |
37 |
38 | #部分代码
39 | 
40 |
41 | #联系我
42 | 如果有其他搞笑的需求,可以联系我:QQ:893007592.
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/fragment/BaseV4Fragment.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.ui.fragment;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.support.v4.app.Fragment;
6 |
7 | import com.oyy.strong.view.WaitingDialog;
8 |
9 | /**
10 | * 所有Fragment请继承此类
11 | *
12 | * @author stanleyding
13 | */
14 | public class BaseV4Fragment extends Fragment{
15 |
16 | public Activity mContext;
17 | private WaitingDialog mDialog;
18 |
19 | @Override
20 | public void onActivityCreated(Bundle savedInstanceState) {
21 | super.onActivityCreated(savedInstanceState);
22 | mContext = getActivity();
23 |
24 | }
25 |
26 | public void showWaitingDialog() {
27 | if (mDialog == null) {
28 | mDialog = new WaitingDialog(mContext);
29 | }
30 | if (mDialog.isShowing()) {
31 | mDialog.cancel();
32 | }
33 | mDialog.show();
34 | }
35 |
36 | protected void showWaitingDialog(String dialogContent) {
37 | if (mDialog == null) {
38 | mDialog = new WaitingDialog(mContext);
39 | }
40 | if (mDialog.isShowing()) {
41 | mDialog.cancel();
42 | }
43 | mDialog.setDialogContent(dialogContent);
44 | mDialog.show();
45 | }
46 |
47 | public void cancelWaitingDialog() {
48 | if (mDialog == null) {
49 | return;
50 | }
51 | if (mDialog.isShowing()) {
52 | mDialog.cancel();
53 | }
54 | }
55 |
56 |
57 |
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/fragment/LeftMenuFragment.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.ui.fragment
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import com.oyy.strong.R
8 | import com.oyy.strong.ui.AboutActivity
9 | import com.oyy.strong.utils.Constant
10 | import com.oyy.strong.utils.DataCleanManagerUtils
11 | import kotlinx.android.synthetic.main.fragment_left_menu.*
12 | import org.jetbrains.anko.onClick
13 | import org.jetbrains.anko.startActivity
14 | import org.jetbrains.anko.toast
15 |
16 | /**
17 | * 侧边栏
18 | * Created by
19 | * ouyangyi on 18/5/3.
20 | */
21 |
22 | class LeftMenuFragment: BaseV4Fragment() {
23 |
24 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | var view: View? = null
26 | if(inflater != null) {
27 | view = inflater.inflate(R.layout.fragment_left_menu, null)
28 |
29 | }
30 |
31 | return view
32 | }
33 |
34 | override fun onActivityCreated(savedInstanceState: Bundle?) {
35 | super.onActivityCreated(savedInstanceState)
36 | initClick()
37 | }
38 |
39 | private fun initClick() {
40 |
41 | clearTxt.onClick {
42 | showWaitingDialog()
43 | DataCleanManagerUtils.cleanApplicationData(mContext, Constant.BASE_PATH)
44 | cancelWaitingDialog()
45 | activity.toast("清理完成")
46 | }
47 |
48 | aboutTxt.onClick {
49 | activity.startActivity()
50 | }
51 |
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils;
2 |
3 |
4 | import android.annotation.TargetApi;
5 | import android.content.Context;
6 | import android.os.Build;
7 | import android.util.DisplayMetrics;
8 | import android.view.View;
9 | import android.widget.ScrollView;
10 |
11 | /**
12 | * Created by
13 | * ouyangyi on 18/05/22.
14 | */
15 | public class Utils {
16 |
17 | private static Utils instance;
18 |
19 |
20 | public static Utils getInstance() {
21 | if (instance == null) {
22 | instance = new Utils();
23 | }
24 |
25 | return instance;
26 | }
27 |
28 | /**
29 | * 获取手机设备宽度
30 | */
31 | public int getWidth(Context context) {
32 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
33 | if (dm.widthPixels > dm.heightPixels) {
34 | return dm.heightPixels;
35 | } else {
36 | return dm.widthPixels;
37 | }
38 | }
39 |
40 | /**
41 | * 获取手机设备高度
42 | */
43 | public int getHeight(Context context) {
44 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
45 | if (dm.widthPixels > dm.heightPixels) {
46 | return dm.widthPixels;
47 | } else {
48 | return dm.heightPixels;
49 | }
50 | }
51 |
52 | /**
53 | * 去掉ScrollView 滑动到底部的阴影
54 | *
55 | * @param view
56 | */
57 | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
58 | public void setOverScrollMode(ScrollView view) {
59 | if (Build.VERSION.SDK_INT > 8 && null != view) {
60 | view.setOverScrollMode(View.OVER_SCROLL_NEVER);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
36 |
37 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/viewpager_indicator_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
17 |
18 |
22 |
23 |
24 |
31 |
32 |
37 |
38 |
39 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/ShareUtils.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.media.MediaMetadataRetriever;
6 | import android.net.Uri;
7 | import android.widget.Toast;
8 |
9 | import java.io.File;
10 |
11 | public class ShareUtils {
12 |
13 | // 調用系統方法分享文件
14 | public static void shareFile(Activity context, File file) {
15 | if (null != file && file.exists()) {
16 | Intent share = new Intent(Intent.ACTION_SEND);
17 | share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
18 | share.setType(getMimeType(file.getAbsolutePath()));//此处可发送多种文件
19 | share.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
20 | share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
21 | context.startActivity(Intent.createChooser(share, "分享文件"));
22 | } else {
23 | Toast.makeText(context, "gif图不存在,请点击上面的生成按钮", Toast.LENGTH_LONG).show();
24 | }
25 | }
26 |
27 | // 根据文件后缀名获得对应的MIME类型。
28 | private static String getMimeType(String filePath) {
29 | MediaMetadataRetriever mmr = new MediaMetadataRetriever();
30 | String mime = "*/*";
31 | if (filePath != null) {
32 | try {
33 | mmr.setDataSource(filePath);
34 | mime = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
35 | } catch (IllegalStateException e) {
36 | return mime;
37 | } catch (IllegalArgumentException e) {
38 | return mime;
39 | } catch (RuntimeException e) {
40 | return mime;
41 | }
42 | }
43 | return mime;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/view/CustomViewPager.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.view;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 |
8 | public class CustomViewPager extends ViewPager {
9 |
10 | private boolean scroll = true;
11 |
12 | public CustomViewPager(Context context) {
13 | super(context);
14 | }
15 |
16 | public CustomViewPager(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public void setScroll(boolean scroll) {
21 | this.scroll = scroll;
22 | }
23 |
24 | @Override
25 | public void scrollTo(int x, int y) {
26 | super.scrollTo(x, y);
27 | }
28 |
29 | @Override
30 | public boolean onTouchEvent(MotionEvent arg0) {
31 | /* return false;//super.onTouchEvent(arg0); */
32 | if (!scroll)
33 | return false;
34 | else
35 | return super.onTouchEvent(arg0);
36 | }
37 |
38 | @Override
39 | public boolean onInterceptTouchEvent(MotionEvent arg0) {
40 | if (!scroll)
41 | return false;
42 | else
43 | return super.onInterceptTouchEvent(arg0);
44 | }
45 |
46 | @Override
47 | public void setCurrentItem(int item, boolean smoothScroll) {
48 | super.setCurrentItem(item, smoothScroll);
49 | }
50 |
51 | @Override
52 | public void setCurrentItem(int item) {
53 | super.setCurrentItem(item);
54 | }
55 |
56 | /**
57 | * 让ViewPager不响应滑动的切换事件,如让嵌套的子ViewPager不响应滑动切换事件,
58 | * 只是响应点击切换事件,将滑动事件交给父ViewPager处理。 (只对嵌套的子ViewPager有效)
59 | */
60 | @Override
61 | public boolean canScrollHorizontally(int direction) {
62 | return false;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion 26
9 | defaultConfig {
10 | applicationId "com.oyy.strong"
11 | minSdkVersion 19
12 | targetSdkVersion 26
13 | versionCode 1
14 | versionName "1.0"
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
28 | implementation 'com.android.support:appcompat-v7:26.1.0'
29 | implementation 'com.android.support.constraint:constraint-layout:1.1.0'
30 | testImplementation 'junit:junit:4.12'
31 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
32 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
33 |
34 | /*网络依赖*/
35 | implementation 'com.squareup.retrofit2:retrofit:2.1.0'
36 | implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
37 | implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
38 | implementation 'com.squareup.okhttp3:okhttp:3.2.0'
39 | implementation 'com.squareup.okhttp3:logging-interceptor:3.2.0'
40 |
41 | // rx.java
42 | implementation 'io.reactivex:rxandroid:1.1.0'
43 | implementation 'io.reactivex:rxjava:1.1.0'
44 | /*图片处理*/
45 | implementation 'com.github.bumptech.glide:glide:3.7.0'
46 |
47 | implementation 'org.jetbrains.anko:anko-sdk15:0.8.3'
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 逗斗
3 |
4 |
5 | 确定
6 | 取消
7 |
8 |
9 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_GET_ACCOUNTS
10 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_PHONE_STATE
11 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_CALL_PHONE
12 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_CAMERA
13 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_FINE_LOCATION
14 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_COARSE_LOCATION
15 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_EXTERNAL_STORAGE
16 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_WRITE_EXTERNAL_STORAGE
17 | 没有此权限,无法开启这个功能,请开启权限。PERMISSION_RECORD_AUDIO
18 |
19 |
20 | - @string/permission_recode_audio_hint
21 | - @string/permission_get_accounts_hint
22 | - @string/permission_read_phone_hint
23 | - @string/permission_call_phone_hint
24 | - @string/permission_camera_hint
25 | - @string/permission_access_fine_location_hint
26 | - @string/permission_access_coarse_location_hint
27 | - @string/permission_read_external_hint
28 | - @string/permission_white_external_hint
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/DensityUtil.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.util.DisplayMetrics;
6 | import android.util.TypedValue;
7 |
8 | /**
9 | * 屏幕密度计算工具
10 | * 计算公式 pixels = dips * (density / 160)
11 | */
12 | public class DensityUtil {
13 |
14 | private static DensityUtil densityUtil;
15 |
16 | public static DensityUtil getInstance() {
17 | if (densityUtil == null) {
18 | densityUtil = new DensityUtil();
19 | }
20 | return densityUtil;
21 | }
22 |
23 | /**
24 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
25 | */
26 | public int dipTopx(Context context, float d) {
27 | DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics();
28 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, d,
29 | dm);
30 | }
31 |
32 | /**
33 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
34 | */
35 | public int pxTodip(Context context, float d) {
36 | DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics();
37 | return (int) Math.ceil(((d * 160) / dm.densityDpi));
38 | }
39 |
40 | /**
41 | * 获取屏幕宽的像素
42 | *
43 | * @param mContext
44 | * @return
45 | */
46 | public static int getDisplayWidth(Activity mContext) {
47 | DisplayMetrics metrics = new DisplayMetrics();
48 | mContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
49 | return metrics.widthPixels;
50 | }
51 |
52 | /**
53 | * 获取屏幕高的像素
54 | *
55 | * @param mContext
56 | * @return
57 | */
58 | public static int getDisplayHeight(Activity mContext) {
59 | DisplayMetrics metrics = new DisplayMetrics();
60 | mContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
61 | return metrics.heightPixels;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_left_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
20 |
27 |
28 |
37 |
38 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
18 |
19 |
27 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/view/WaitingDialog.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.view;
2 |
3 |
4 | import android.app.Dialog;
5 | import android.content.Context;
6 | import android.graphics.drawable.BitmapDrawable;
7 | import android.os.Bundle;
8 | import android.view.Gravity;
9 | import android.view.LayoutInflater;
10 | import android.view.Window;
11 | import android.view.WindowManager.LayoutParams;
12 | import android.widget.TextView;
13 |
14 | import com.oyy.strong.R;
15 |
16 |
17 | public class WaitingDialog extends Dialog {
18 |
19 | private LayoutInflater factory;
20 |
21 | private TextView mContentTextView;
22 |
23 | private String mContentString;
24 |
25 | public WaitingDialog(Context context, String contentString) {
26 | this(context, R.style.dialog_style);
27 | mContentString = contentString;
28 | }
29 | public WaitingDialog(Context context) {
30 | this(context, R.style.dialog_style);
31 | }
32 |
33 | public WaitingDialog(Context context, int theme) {
34 | super(context, theme);
35 | factory = LayoutInflater.from(context);
36 | windowAttr();
37 | }
38 |
39 | private void windowAttr() {
40 | Window win = this.getWindow();
41 | LayoutParams params = new LayoutParams();
42 | params.x = 0;// 设置x坐标
43 | params.y = 0;// 设置y坐标
44 | params.horizontalMargin = 0;
45 | win.setAttributes(params);
46 | this.setCanceledOnTouchOutside(false);
47 | win.setGravity(Gravity.CENTER);
48 | getWindow().setBackgroundDrawable(new BitmapDrawable());
49 | //win.setWindowAnimations(R.style.dialog_anim);
50 | }
51 |
52 | @Override
53 | protected void onCreate(Bundle savedInstanceState) {
54 | super.onCreate(savedInstanceState);
55 | this.setContentView(factory.inflate(R.layout.dialog_waiting, null));
56 | mContentTextView = (TextView) this.findViewById(R.id.tip);
57 |
58 | if (mContentString != null) {
59 | mContentTextView.setText(mContentString);
60 | }
61 |
62 | }
63 |
64 | public void doCancel() {
65 | if (this.isShowing())
66 | this.dismiss();
67 | }
68 |
69 | public void setDialogContent(String content) {
70 | mContentString = content;
71 | if(mContentTextView!=null) {
72 | mContentTextView.setText(content);
73 | }
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
25 |
26 |
36 |
37 |
42 |
43 |
44 |
56 |
57 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
17 |
22 |
23 |
33 |
34 |
45 |
46 |
47 |
52 |
53 |
59 |
60 |
61 |
62 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/ImageHandlerUtils.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils;
2 |
3 | import android.os.Environment;
4 |
5 | import java.io.File;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 | import java.net.HttpURLConnection;
11 | import java.net.URL;
12 |
13 | public class ImageHandlerUtils {
14 |
15 | /**
16 | * 保存bitmap到SD卡
17 | *
18 | * @param bitmap
19 | * @param imageName
20 | */
21 | // public static String saveBitmapToSDCard(Bitmap bitmap, String imageName) {
22 | //
23 | // String path = Environment.getExternalStorageDirectory()
24 | // + File.separator + "com.oyy.strong" + File.separator + "imageFile" + File.separator + imageName + ".gif";
25 | // FileOutputStream fos = null;
26 | // try {
27 | // fos = new FileOutputStream(path);
28 | // if (fos != null) {
29 | // bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
30 | // fos.close();
31 | // }
32 | //
33 | // return path;
34 | // } catch (Exception e) {
35 | // e.printStackTrace();
36 | // }
37 | // return null;
38 | // }
39 |
40 | /**
41 | * 下载保存图片
42 | *
43 | * @param url
44 | */
45 | public static String downLoadImgSaveFile(String url, String type) {
46 |
47 | File filename = null;
48 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
49 | File fileSD = new File(Constant.BASE_PATH);
50 |
51 | if (!fileSD.exists()) {
52 | fileSD.mkdirs();
53 | }
54 | //文件的路径
55 | filename = new File(fileSD, type + "_douTu.gif");
56 | if (!filename.exists()) {
57 |
58 | try {
59 | filename.createNewFile();
60 | } catch (Exception e) {
61 | e.printStackTrace();
62 | }
63 | }
64 | }
65 |
66 | HttpURLConnection conn = null;
67 |
68 | try {
69 | conn = (HttpURLConnection) new URL(url).openConnection();
70 | conn.setRequestMethod("GET");
71 | conn.setDoInput(true);
72 | conn.connect();
73 | InputStream content = conn.getInputStream();
74 | byte[] buffer = new byte[1024]; //创建一个中转站
75 | int len = 0; //用来装每次读到的字节数
76 | OutputStream outputStream = null;
77 | outputStream = new FileOutputStream(filename);
78 | while ((len = content.read(buffer)) != -1) {
79 | outputStream.write(buffer, 0, len);
80 | outputStream.flush();
81 | }
82 |
83 | } catch (IOException e) {
84 | e.printStackTrace();
85 | }
86 |
87 | return filename.getAbsolutePath();
88 |
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.ui
2 |
3 | import android.os.Bundle
4 | import android.support.v4.app.Fragment
5 | import android.support.v4.view.GravityCompat
6 | import android.support.v7.app.AppCompatActivity
7 | import android.view.View.OVER_SCROLL_NEVER
8 | import com.manqian.crm.adapter.TabAdapter
9 | import com.manqian.crm.ui.fragment.IndexFragment
10 | import com.manqian.crm.ui.fragment.SorryFragment
11 | import com.manqian.crm.ui.fragment.WorkFragment
12 | import com.oyy.strong.R
13 | import com.oyy.strong.utils.DensityUtil
14 | import com.oyy.strong.utils.PermissionUtil
15 | import kotlinx.android.synthetic.main.activity_main.*
16 | import org.jetbrains.anko.onClick
17 | import org.jetbrains.anko.toast
18 |
19 |
20 | /**
21 | * create by ouyangyi
22 | * on 18/05/22
23 | */
24 |
25 | class MainActivity : AppCompatActivity() {
26 |
27 | private val tabs = arrayOf("wjz", "为所欲为", "打工")
28 |
29 | private val fragments = ArrayList()
30 |
31 |
32 | override fun onCreate(savedInstanceState: Bundle?) {
33 | super.onCreate(savedInstanceState)
34 | setContentView(R.layout.activity_main)
35 | init()
36 | }
37 |
38 | private fun init() {
39 |
40 | pagers.overScrollMode = OVER_SCROLL_NEVER
41 |
42 | fragments.add(IndexFragment())
43 | fragments.add(SorryFragment())
44 | fragments.add(WorkFragment())
45 |
46 | val tabSpacing = DensityUtil.getInstance().dipTopx(this, 40F)
47 | val cursorPadding = DensityUtil.getInstance().dipTopx(this, 8F)
48 |
49 | val mAdapter = TabAdapter(supportFragmentManager, fragments)
50 | pagers.adapter = mAdapter
51 | pagers.offscreenPageLimit = fragments.size
52 |
53 | horizontal_scrollview.setParams(tabSpacing, cursorPadding, tabs, pagers, true)
54 |
55 | leftText.onClick {
56 | toggleMenu()
57 | }
58 | }
59 |
60 | private fun isMenuShowing(): Boolean {
61 | return drawerlayout.isDrawerOpen(GravityCompat.START)
62 | }
63 |
64 | /**
65 | * 开关侧滑菜单
66 | */
67 | private fun toggleMenu() {
68 | if (isMenuShowing()) {
69 | drawerlayout.closeDrawer(GravityCompat.START)
70 | } else {
71 | drawerlayout.openDrawer(GravityCompat.START)
72 | }
73 | }
74 |
75 |
76 | override fun onResume() {
77 | super.onResume()
78 | /**
79 | * 权限处理相关
80 | */
81 | PermissionUtil.requestMultiPermissions(this, arrayOf(PermissionUtil.PERMISSION_READ_EXTERNAL_STORAGE, PermissionUtil.PERMISSION_WRITE_EXTERNAL_STORAGE), mPermissionGrant)
82 | }
83 |
84 | private val mPermissionGrant = PermissionUtil.PermissionGrant {
85 | if (it == PermissionUtil.CODE_MULTI_PERMISSION) {
86 |
87 | } else {
88 | toast("权限被取消!将会无法正常使用!")
89 | }
90 | }
91 |
92 | override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
93 | super.onRequestPermissionsResult(requestCode, permissions, grantResults)
94 | PermissionUtil.requestPermissionsResult(this, requestCode, permissions, grantResults, mPermissionGrant)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/view/drawer/DrawerLayoutCompatApi21.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.view.drawer;
2 |
3 |
4 | import android.annotation.TargetApi;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.drawable.Drawable;
8 | import android.os.Build;
9 | import android.view.Gravity;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.view.WindowInsets;
13 |
14 | /**
15 | * Provides functionality for DrawerLayout unique to API 21
16 | */
17 | class DrawerLayoutCompatApi21 {
18 |
19 | private static final int[] THEME_ATTRS = {
20 | android.R.attr.colorPrimaryDark
21 | };
22 |
23 | @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
24 | public static void configureApplyInsets(View drawerLayout) {
25 | if (drawerLayout instanceof DrawerLayoutImpl) {
26 | drawerLayout.setOnApplyWindowInsetsListener(new InsetsListener());
27 | drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
28 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
29 | }
30 | }
31 |
32 | @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
33 | public static void dispatchChildInsets(View child, Object insets, int gravity) {
34 | WindowInsets wi = (WindowInsets) insets;
35 | if (gravity == Gravity.LEFT) {
36 | wi = wi.replaceSystemWindowInsets(wi.getSystemWindowInsetLeft(),
37 | wi.getSystemWindowInsetTop(), 0, wi.getSystemWindowInsetBottom());
38 | } else if (gravity == Gravity.RIGHT) {
39 | wi = wi.replaceSystemWindowInsets(0, wi.getSystemWindowInsetTop(),
40 | wi.getSystemWindowInsetRight(), wi.getSystemWindowInsetBottom());
41 | }
42 | child.dispatchApplyWindowInsets(wi);
43 | }
44 |
45 | @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
46 | public static void applyMarginInsets(ViewGroup.MarginLayoutParams lp, Object insets,
47 | int gravity) {
48 | WindowInsets wi = (WindowInsets) insets;
49 | if (gravity == Gravity.LEFT) {
50 | wi = wi.replaceSystemWindowInsets(wi.getSystemWindowInsetLeft(),
51 | wi.getSystemWindowInsetTop(), 0, wi.getSystemWindowInsetBottom());
52 | } else if (gravity == Gravity.RIGHT) {
53 | wi = wi.replaceSystemWindowInsets(0, wi.getSystemWindowInsetTop(),
54 | wi.getSystemWindowInsetRight(), wi.getSystemWindowInsetBottom());
55 | }
56 | lp.leftMargin = wi.getSystemWindowInsetLeft();
57 | lp.topMargin = wi.getSystemWindowInsetTop();
58 | lp.rightMargin = wi.getSystemWindowInsetRight();
59 | lp.bottomMargin = wi.getSystemWindowInsetBottom();
60 | }
61 |
62 | @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
63 | public static int getTopInset(Object insets) {
64 | return insets != null ? ((WindowInsets) insets).getSystemWindowInsetTop() : 0;
65 | }
66 |
67 | public static Drawable getDefaultStatusBarBackground(Context context) {
68 | final TypedArray a = context.obtainStyledAttributes(THEME_ATTRS);
69 | try {
70 | return a.getDrawable(0);
71 | } finally {
72 | a.recycle();
73 | }
74 | }
75 |
76 | @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
77 | static class InsetsListener implements View.OnApplyWindowInsetsListener {
78 | @Override
79 | public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
80 | final DrawerLayoutImpl drawerLayout = (DrawerLayoutImpl) v;
81 | drawerLayout.setChildInsets(insets, insets.getSystemWindowInsetTop() > 0);
82 | return insets.consumeSystemWindowInsets();
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/http/RetrofitManager.kt:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.http
2 |
3 | import com.oyy.strong.BaseApplication
4 | import com.oyy.strong.entity.GifBean
5 | import com.oyy.strong.entity.Subtitles
6 | import com.oyy.strong.utils.NetWorkUtil
7 | import okhttp3.*
8 | import okhttp3.logging.HttpLoggingInterceptor
9 | import retrofit2.Retrofit
10 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
11 | import retrofit2.converter.gson.GsonConverterFactory
12 | import rx.Observable
13 | import java.io.File
14 | import java.util.concurrent.TimeUnit
15 |
16 | /**
17 | * Created by
18 | * ouyangyi on 18/5/22.
19 | */
20 | class RetrofitManager private constructor(url: String) : Interceptor {
21 |
22 | //短缓存有效期为10分钟
23 | private val CACHE_STALE_SHORT = 60 * 10
24 |
25 | //长缓存有效期为7天
26 | private val CACHE_STALE_LONG = "60 * 60 * 24 * 7"
27 |
28 | //查询缓存的Cache-Control设置,为if-only-cache时只查询缓存而不会请求服务器,max-stale可以配合设置缓存失效时间
29 | private val CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_LONG
30 |
31 | //查询网络的Cache-Control设置,头部Cache-Control设为max-age=0时则不会使用缓存而请求服务器
32 | private val CACHE_CONTROL_NETWORK = "max-age=0"
33 |
34 | private var mOkHttpClient: OkHttpClient? = null
35 |
36 | private var service: APIService? = null
37 |
38 | init {
39 | initOkHttpclient()
40 | var retrofit = Retrofit.Builder()
41 | .baseUrl(url)
42 | .client(mOkHttpClient)
43 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
44 | .addConverterFactory(GsonConverterFactory.create())
45 | .build()
46 | service = retrofit.create(APIService ::class.java)
47 | }
48 |
49 | companion object {
50 | //写法一: 锁在方法上
51 | // private var instance: RetrofitManager? = null
52 | //
53 | // private @Synchronized fun getInstances( url: String): RetrofitManager {
54 | // if (instance == null) {
55 | // instance = RetrofitManager(url)
56 | // }
57 | // return instance as RetrofitManager
58 | // }
59 |
60 | fun builder(url: String):RetrofitManager {
61 | //双重锁
62 | val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { RetrofitManager(url) }
63 |
64 | return instance
65 | }
66 | }
67 |
68 | /**
69 | * 初始化okHttp相关
70 | */
71 | private fun initOkHttpclient() {
72 | var interceptor = HttpLoggingInterceptor()
73 | interceptor.level = HttpLoggingInterceptor.Level.BODY
74 |
75 | if (mOkHttpClient == null) {
76 | val cache = Cache(File(BaseApplication.getInstance().cacheDir, "File_Kotlin"), 14 * 1024 * 100)
77 | mOkHttpClient = OkHttpClient.Builder()
78 | .cache(cache)
79 | .retryOnConnectionFailure(true)
80 | .addNetworkInterceptor(this)
81 | .addInterceptor(this)
82 | .connectTimeout(15, TimeUnit.SECONDS)
83 | .build()
84 | }
85 | }
86 |
87 | override fun intercept(chain: Interceptor.Chain?): Response {
88 | var request = chain!!.request()
89 | if (!NetWorkUtil.isNetWorkConnected()) {
90 | request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build()
91 | }
92 | var response = chain.proceed(request)
93 | return if (NetWorkUtil.isNetWorkConnected()) {
94 | var cacheControl: String = request.cacheControl().toString()
95 | response.newBuilder().header("Cache-Control", cacheControl)
96 | .removeHeader("Pragma").build()
97 | } else {
98 | response.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_LONG)
99 | .removeHeader("Pragma").build()
100 | }
101 | }
102 |
103 | fun getGif(subtitles: Subtitles): Observable = service!!.getGifPath(subtitles)
104 |
105 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/user/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
27 | # glide 的混淆代码
28 | -keep public class * implements com.bumptech.glide.module.GlideModule
29 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
30 | **[] $VALUES;
31 | public *;
32 | }
33 | # for DexGuard only
34 | -keepresourcexmlelements manifest/application/meta-data@value=GlideModule
35 |
36 | # 保持哪些类不被混淆
37 | -keep public class * extends android.app.Fragment
38 | -keep public class * extends android.app.Activity
39 | -keep public class * extends android.app.Application
40 | -keep public class * extends android.app.Service
41 | -keep public class * extends android.content.BroadcastReceiver
42 | -keep public class * extends android.content.ContentProvider
43 | -keep public class * extends android.app.backup.BackupAgentHelper
44 | -keep public class * extends android.preference.Preference
45 | -keep public class com.android.vending.licensing.ILicensingService
46 | -keep public class * extends MQBaseActivity
47 |
48 | #如果有引用v4包可以添加下面这行
49 | -keep public class * extends android.support.v4.app.Fragment
50 |
51 |
52 | #保持 native 方法不被混淆
53 | -keepclasseswithmembernames class * {
54 | native ;
55 | }
56 |
57 | #保持自定义控件类不被混淆
58 | -keepclasseswithmembers class * {
59 | public (android.content.Context, android.util.AttributeSet);
60 | }
61 |
62 | #保持自定义控件类不被混淆
63 | -keepclasseswithmembers class * {
64 | public (android.content.Context, android.util.AttributeSet, int);
65 | }
66 | #保持自定义控件类不被混淆
67 | -keepclassmembers class * extends android.app.Activity {
68 | public void *(android.view.View);
69 | }
70 |
71 | #保持 Parcelable 不被混淆
72 | -keep class * implements android.os.Parcelable {
73 | public static final android.os.Parcelable$Creator *;
74 | }
75 |
76 | #保持 Serializable 不被混淆
77 | -keepnames class * implements java.io.Serializable
78 |
79 | #保持 Serializable 不被混淆并且enum 类也不被混淆
80 | -keepclassmembers class * implements java.io.Serializable {
81 | static final long serialVersionUID;
82 | private static final java.io.ObjectStreamField[] serialPersistentFields;
83 | !static !transient ;
84 | !private ;
85 | !private ;
86 | private void writeObject(java.io.ObjectOutputStream);
87 | private void readObject(java.io.ObjectInputStream);
88 | java.lang.Object writeReplace();
89 | java.lang.Object readResolve();
90 | }
91 |
92 | #保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
93 | -keepclassmembers enum * {
94 | public static **[] values();
95 | public static ** valueOf(java.lang.String);
96 | }
97 |
98 | -keepclassmembers class * {
99 | public void *ButtonClicked(android.view.View);
100 | }
101 |
102 | #不混淆资源类
103 |
104 | -keepclassmembers class **.R$* {
105 | public static ;
106 | }
107 |
108 | #如果你的项目中用到了webview的复杂操作 ,最好加入
109 | -keepclassmembers class * extends android.webkit.WebViewClient {
110 | public void *(android.webkit.WebView,java.lang.String,android.graphics.Bitmap);
111 | public boolean *(android.webkit.WebView,java.lang.String);
112 | }
113 |
114 | #如果你的项目中用到了webview的复杂操作 ,最好加入
115 | -keepclassmembers class * extends android.webkit.WebChromeClient {
116 | public void *(android.webkit.WebView,java.lang.String);
117 | }
118 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/fragment/IndexFragment.kt:
--------------------------------------------------------------------------------
1 | package com.manqian.crm.ui.fragment
2 |
3 | import android.os.Bundle
4 | import android.os.Handler
5 | import android.os.Message
6 | import android.text.TextUtils
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.Toast
11 | import com.bumptech.glide.Glide
12 | import com.bumptech.glide.load.engine.DiskCacheStrategy
13 | import com.oyy.strong.R
14 | import com.oyy.strong.entity.Subtitles
15 | import com.oyy.strong.http.RetrofitManager
16 | import com.oyy.strong.ui.fragment.BaseV4Fragment
17 | import com.oyy.strong.utils.*
18 | import kotlinx.android.synthetic.main.fragment_index_layout.*
19 | import org.jetbrains.anko.onClick
20 | import rx.android.schedulers.AndroidSchedulers
21 | import rx.schedulers.Schedulers
22 | import java.io.File
23 | import java.util.*
24 |
25 | /**
26 | * 首页fragment
27 | * Created by
28 | * ouyangyi on 18/5/23.
29 | */
30 |
31 | class IndexFragment : BaseV4Fragment() {
32 |
33 | private var path = Constant.BASE_PATH + "/wjz_douTu.gif"
34 |
35 | private val handler = object : Handler() {
36 | override fun handleMessage(msg: Message) {
37 | when (msg.what) {
38 | 1 -> {
39 | cancelWaitingDialog()
40 | Glide.with(activity)
41 | .load(path)
42 | .asGif()
43 | .diskCacheStrategy(DiskCacheStrategy.SOURCE)
44 | .into(showGif)
45 | }
46 | }
47 | }
48 | }
49 |
50 |
51 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
52 | var view: View? = null
53 | if (inflater != null) {
54 | view = inflater.inflate(R.layout.fragment_index_layout, null)
55 |
56 | }
57 | return view
58 | }
59 |
60 | override fun onActivityCreated(savedInstanceState: Bundle?) {
61 | super.onActivityCreated(savedInstanceState)
62 | initView()
63 | initClick()
64 | }
65 |
66 | private fun initView() {
67 | //去除阴影
68 | Utils.getInstance().setOverScrollMode(scrollView)
69 | }
70 |
71 | /**
72 | * 初始化监听事件
73 | */
74 | private fun initClick() {
75 |
76 | submitBtn.onClick {
77 | var a1 = edit_1.text
78 | var a2 = edit_2.text
79 | var a3 = edit_3.text
80 | var a4 = edit_4.text
81 |
82 | if (TextUtils.isEmpty(a1) || TextUtils.isEmpty(a2)
83 | || TextUtils.isEmpty(a3) || TextUtils.isEmpty(a4)) {
84 |
85 | Toast.makeText(activity, "请输入完整", Toast.LENGTH_SHORT)
86 | } else {
87 | var sentence = "$a1,$a2,$a3,$a4"
88 | var subtitles = Subtitles("wangjingze", sentence, "simple")
89 | RetrofitManager.builder("http://193.112.131.84:8081")
90 | .getGif(subtitles)
91 | .subscribeOn(Schedulers.io())
92 | .observeOn(AndroidSchedulers.mainThread())
93 | .doOnSubscribe {
94 | showWaitingDialog()
95 | println("call………………………执行前调用…")
96 | }
97 | .subscribe({ ban ->
98 | Thread {
99 | var type = "wjz" + Date().time
100 | path = Constant.BASE_PATH + "/" + type + "_douTu.gif"
101 | DataCleanManagerUtils.cleanApplicationData(mContext, Constant.BASE_PATH)
102 | ImageHandlerUtils.downLoadImgSaveFile(ban.result, type)
103 | val message = Message.obtain()
104 | message.what = 1
105 | handler.sendMessage(message)
106 | }.start()
107 |
108 | })
109 | { throwable ->
110 | println(throwable.message)
111 | }
112 | }
113 |
114 | }
115 |
116 | shareBtn.onClick {
117 | ShareUtils.shareFile(activity, File(path))
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/fragment/WorkFragment.kt:
--------------------------------------------------------------------------------
1 | package com.manqian.crm.ui.fragment
2 |
3 | import android.os.Bundle
4 | import android.os.Handler
5 | import android.os.Message
6 | import android.text.TextUtils
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.Toast
11 | import com.bumptech.glide.Glide
12 | import com.bumptech.glide.load.engine.DiskCacheStrategy
13 | import com.oyy.strong.R
14 | import com.oyy.strong.entity.Subtitles
15 | import com.oyy.strong.http.RetrofitManager
16 | import com.oyy.strong.ui.fragment.BaseV4Fragment
17 | import com.oyy.strong.utils.*
18 | import kotlinx.android.synthetic.main.fragment_work_layout.*
19 | import org.jetbrains.anko.onClick
20 | import rx.android.schedulers.AndroidSchedulers
21 | import rx.schedulers.Schedulers
22 | import java.io.File
23 | import java.util.*
24 |
25 | /**
26 | * 打工fragment
27 | * Created by
28 | * ouyangyi on 18/5/23.
29 | */
30 |
31 | class WorkFragment : BaseV4Fragment() {
32 |
33 | private var path = ""
34 |
35 | private val handler = object : Handler() {
36 | override fun handleMessage(msg: Message) {
37 | when (msg.what) {
38 | 1 -> {
39 | cancelWaitingDialog()
40 | Glide.with(activity)
41 | .load(path)
42 | .asGif()
43 | .diskCacheStrategy(DiskCacheStrategy.SOURCE)
44 | .into(showWorkGif)
45 | }
46 | }
47 | }
48 | }
49 |
50 |
51 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
52 | var view: View? = null
53 | if (inflater != null) {
54 | view = inflater.inflate(R.layout.fragment_work_layout, null)
55 |
56 | }
57 | return view
58 | }
59 |
60 | override fun onActivityCreated(savedInstanceState: Bundle?) {
61 | super.onActivityCreated(savedInstanceState)
62 | initView()
63 | initClick()
64 | }
65 |
66 | private fun initView() {
67 | //去除阴影
68 | Utils.getInstance().setOverScrollMode(scrollView)
69 | }
70 |
71 | /**
72 | * 初始化监听事件
73 | */
74 | private fun initClick() {
75 |
76 | submitBtn.onClick {
77 | var a1 = edit_1.text
78 | var a2 = edit_2.text
79 | var a3 = edit_3.text
80 | var a4 = edit_4.text
81 | var a5 = edit_5.text
82 | var a6 = edit_6.text
83 |
84 | if (TextUtils.isEmpty(a1) || TextUtils.isEmpty(a2)
85 | || TextUtils.isEmpty(a3) || TextUtils.isEmpty(a4) || TextUtils.isEmpty(a5) || TextUtils.isEmpty(a6)) {
86 |
87 | Toast.makeText(activity, "请输入完整", Toast.LENGTH_SHORT)
88 | } else {
89 | var sentence = "$a1,$a2,$a3,$a4,$a5,$a6"
90 | var subtitles = Subtitles("dagong", sentence, "simple")
91 | RetrofitManager.builder("http://193.112.131.84:8081")
92 | .getGif(subtitles)
93 | .subscribeOn(Schedulers.io())
94 | .observeOn(AndroidSchedulers.mainThread())
95 | .doOnSubscribe {
96 | showWaitingDialog()
97 | println("call………………………执行前调用…")
98 | }
99 | .subscribe({ ban ->
100 | Thread {
101 | var type = "dagong" + Date().time
102 | path = Constant.BASE_PATH + "/" + type + "_douTu.gif"
103 | DataCleanManagerUtils.cleanApplicationData(mContext, Constant.BASE_PATH)
104 | ImageHandlerUtils.downLoadImgSaveFile(ban.result, type)
105 | val message = Message.obtain()
106 | message.what = 1
107 | handler.sendMessage(message)
108 | }.start()
109 |
110 | })
111 | { throwable ->
112 | println(throwable.message)
113 | }
114 | }
115 |
116 | }
117 |
118 | shareBtn.onClick {
119 | ShareUtils.shareFile(activity, File(path))
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/ui/fragment/SorryFragment.kt:
--------------------------------------------------------------------------------
1 | package com.manqian.crm.ui.fragment
2 |
3 | import android.os.Bundle
4 | import android.os.Handler
5 | import android.os.Message
6 | import android.text.TextUtils
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.Toast
11 | import com.bumptech.glide.Glide
12 | import com.bumptech.glide.load.engine.DiskCacheStrategy
13 | import com.oyy.strong.R
14 | import com.oyy.strong.entity.Subtitles
15 | import com.oyy.strong.http.RetrofitManager
16 | import com.oyy.strong.ui.fragment.BaseV4Fragment
17 | import com.oyy.strong.utils.*
18 | import kotlinx.android.synthetic.main.fragment_sorry_layout.*
19 | import org.jetbrains.anko.onClick
20 | import rx.android.schedulers.AndroidSchedulers
21 | import rx.schedulers.Schedulers
22 | import java.io.File
23 | import java.util.*
24 |
25 | /**
26 | * sorry fragment
27 | * Created by
28 | * ouyangyi on 18/5/23.
29 | */
30 |
31 | class SorryFragment : BaseV4Fragment() {
32 |
33 | private var path = Constant.BASE_PATH + "/sorry_douTu.gif"
34 |
35 | private val handler = object : Handler() {
36 | override fun handleMessage(msg: Message) {
37 | when (msg.what) {
38 | 1 -> {
39 | cancelWaitingDialog()
40 | Glide.with(activity)
41 | .load(path)
42 | .asGif()
43 | .diskCacheStrategy(DiskCacheStrategy.SOURCE)
44 | .into(showSorryGif)
45 | }
46 | }
47 | }
48 | }
49 |
50 |
51 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
52 | var view: View? = null
53 | if (inflater != null) {
54 | view = inflater.inflate(R.layout.fragment_sorry_layout, null)
55 |
56 | }
57 | return view
58 | }
59 |
60 | override fun onActivityCreated(savedInstanceState: Bundle?) {
61 | super.onActivityCreated(savedInstanceState)
62 | initView()
63 | initClick()
64 | }
65 |
66 | private fun initView() {
67 | //去除阴影
68 | Utils.getInstance().setOverScrollMode(scrollView)
69 | }
70 |
71 | /**
72 | * 初始化监听事件
73 | */
74 | private fun initClick() {
75 |
76 | submitBtn.onClick {
77 | var a1 = edit_1.text
78 | var a2 = edit_2.text
79 | var a3 = edit_3.text
80 | var a4 = edit_4.text
81 | var a5 = edit_5.text
82 | var a6 = edit_6.text
83 | var a7 = edit_7.text
84 | var a8 = edit_8.text
85 | var a9 = edit_9.text
86 |
87 | if (TextUtils.isEmpty(a1) || TextUtils.isEmpty(a2)
88 | || TextUtils.isEmpty(a3) || TextUtils.isEmpty(a4) ||
89 | TextUtils.isEmpty(a5) || TextUtils.isEmpty(a6) ||
90 | TextUtils.isEmpty(a7) || TextUtils.isEmpty(a8) || TextUtils.isEmpty(a9)) {
91 |
92 | Toast.makeText(activity, "请输入完整", Toast.LENGTH_SHORT)
93 | } else {
94 | var sentence = "$a1,$a2,$a3,$a4,$a5,$a6,$a7,$a8,$a9"
95 | var subtitles = Subtitles("sorry", sentence, "simple")
96 | RetrofitManager.builder("http://193.112.131.84:8081")
97 | .getGif(subtitles)
98 | .subscribeOn(Schedulers.io())
99 | .observeOn(AndroidSchedulers.mainThread())
100 | .doOnSubscribe {
101 | showWaitingDialog()
102 | println("call………………………执行前调用…")
103 | }
104 | .subscribe({ ban ->
105 | Thread {
106 | var type = "sorry" + Date().time
107 | path = Constant.BASE_PATH + "/" + type + "_douTu.gif"
108 | DataCleanManagerUtils.cleanApplicationData(mContext, Constant.BASE_PATH)
109 | ImageHandlerUtils.downLoadImgSaveFile(ban.result, type)
110 | val message = Message.obtain()
111 | message.what = 1
112 | handler.sendMessage(message)
113 | }.start()
114 |
115 | })
116 | { throwable ->
117 | println(throwable.message)
118 | }
119 | }
120 |
121 | }
122 |
123 | shareBtn.onClick {
124 | ShareUtils.shareFile(activity, File(path))
125 | }
126 | }
127 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/DataCleanManagerUtils.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils;
2 |
3 | import android.content.Context;
4 | import android.os.Environment;
5 |
6 | import java.io.File;
7 | import java.math.BigDecimal;
8 | import java.text.DecimalFormat;
9 |
10 | /**
11 | * 清除文件
12 | */
13 | public class DataCleanManagerUtils {
14 |
15 | /**
16 | * 清除本应用内部缓存(/data/data/com.xxx.xxx/cache) * * @param context
17 | */
18 | public static void cleanInternalCache(Context context) {
19 | deleteFilesByDirectory(context.getCacheDir());
20 | }
21 |
22 |
23 | /**
24 | * 清除本应用所有数据库(/data/data/com.xxx.xxx/databases) * * @param context
25 | */
26 | public static void cleanDatabases(Context context) {
27 | deleteFilesByDirectory(new File("/data/data/"
28 | + context.getPackageName() + "/databases"));
29 | }
30 |
31 | /**
32 | * * 清除本应用SharedPreference(/data/data/com.xxx.xxx/shared_prefs) * * @param
33 | * context
34 | */
35 | public static void cleanSharedPreference(Context context) {
36 | deleteFilesByDirectory(new File("/data/data/"
37 | + context.getPackageName() + "/shared_prefs"));
38 | }
39 |
40 | /**
41 | * 按名字清除本应用数据库 * * @param context * @param dbName
42 | */
43 | public static void cleanDatabaseByName(Context context, String dbName) {
44 | context.deleteDatabase(dbName);
45 | }
46 |
47 | /**
48 | * 清除/data/data/com.xxx.xxx/files下的内容 * * @param context
49 | */
50 | public static void cleanFiles(Context context) {
51 | deleteFilesByDirectory(context.getFilesDir());
52 | }
53 |
54 | /**
55 | * * 清除外部cache下的内容(/mnt/sdcard/android/data/com.xxx.xxx/cache) * * @param
56 | * context
57 | */
58 | public static void cleanExternalCache(Context context) {
59 | if (Environment.getExternalStorageState().equals(
60 | Environment.MEDIA_MOUNTED)) {
61 | deleteFilesByDirectory(context.getExternalCacheDir());
62 | }
63 | }
64 |
65 | /**
66 | * 清除自定义路径下的文件,使用需小心,请不要误删。而且只支持目录下的文件删除 * * @param filePath
67 | */
68 | public static void cleanCustomCache(String filePath) {
69 | deleteFilesByDirectory(new File(filePath));
70 | }
71 |
72 | /**
73 | * 清除本应用所有的数据 * * @param context * @param filepath
74 | */
75 | public static void cleanApplicationData(Context context, String... filepath) {
76 | cleanInternalCache(context);
77 | cleanExternalCache(context);
78 | // cleanDatabases(context);
79 | // cleanSharedPreference(context);//登录信息存储在SharedPreference中的,所以不要清除
80 | cleanFiles(context);
81 | for (String filePath : filepath) {
82 | cleanCustomCache(filePath);
83 | }
84 | }
85 |
86 | /**
87 | * 删除方法 这里只会删除某个文件夹下的文件,如果传入的directory是个文件,将不做处理 * * @param directory
88 | */
89 | private static void deleteFilesByDirectory(File directory) {
90 | if (directory != null && directory.exists() && directory.isDirectory()) {
91 | for (File item : directory.listFiles()) {
92 | item.delete();
93 | }
94 | }
95 | }
96 |
97 | /***
98 | * 获取应用缓存大小
99 | * @param file
100 | * @return
101 | * @throws Exception
102 | */
103 | public static String getCacheSize(File file) throws Exception {
104 | return getFormatSize(getFolderSize(file));
105 | }
106 |
107 | // 获取文件
108 | //Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
109 | //Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
110 | public static long getFolderSize(File file) throws Exception {
111 | long size = 0;
112 | try {
113 | File[] fileList = file.listFiles();
114 | for (int i = 0; i < fileList.length; i++) {
115 | // 如果下面还有文件
116 | if (fileList[i].isDirectory()) {
117 | size = size + getFolderSize(fileList[i]);
118 | } else {
119 | size = size + fileList[i].length();
120 | }
121 | }
122 | } catch (Exception e) {
123 | e.printStackTrace();
124 | }
125 | return size;
126 | }
127 |
128 | /**
129 | * 格式化单位
130 | *
131 | * @param size
132 | * @return
133 | */
134 | public static String getFormatSize(double size) {
135 | //保留两位小数
136 | DecimalFormat df = new DecimalFormat("0.00");
137 | double kiloByte = size / 1024;
138 | String format = df.format(size);
139 | if (kiloByte < 1) {
140 | return format + "B";
141 | }
142 |
143 | double megaByte = kiloByte / 1024;
144 | if (megaByte < 1) {
145 | BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
146 | return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
147 | .toPlainString() + "KB";
148 | }
149 |
150 | double gigaByte = megaByte / 1024;
151 | if (gigaByte < 1) {
152 | BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
153 | return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
154 | .toPlainString() + "MB";
155 | }
156 |
157 | double teraBytes = gigaByte / 1024;
158 | if (teraBytes < 1) {
159 | BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
160 | return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
161 | .toPlainString() + "GB";
162 | }
163 | BigDecimal result4 = new BigDecimal(teraBytes);
164 | return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()
165 | + "T";
166 | }
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_index_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
26 |
27 |
34 |
35 |
48 |
49 |
50 |
51 |
59 |
60 |
67 |
68 |
81 |
82 |
83 |
84 |
92 |
93 |
100 |
101 |
114 |
115 |
116 |
117 |
118 |
126 |
127 |
134 |
135 |
148 |
149 |
150 |
151 |
166 |
167 |
181 |
182 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_work_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
26 |
27 |
34 |
35 |
48 |
49 |
50 |
51 |
59 |
60 |
67 |
68 |
81 |
82 |
83 |
84 |
92 |
93 |
100 |
101 |
114 |
115 |
116 |
117 |
118 |
126 |
127 |
134 |
135 |
148 |
149 |
150 |
151 |
159 |
160 |
167 |
168 |
181 |
182 |
183 |
184 |
192 |
193 |
200 |
201 |
214 |
215 |
216 |
217 |
232 |
233 |
247 |
248 |
254 |
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/view/ViewPagerIndicator.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.view;
2 |
3 | import android.content.Context;
4 | import android.os.Handler;
5 | import android.support.v4.view.ViewPager;
6 | import android.support.v4.view.ViewPager.OnPageChangeListener;
7 | import android.util.AttributeSet;
8 | import android.view.View;
9 | import android.view.View.OnClickListener;
10 | import android.view.animation.Animation;
11 | import android.view.animation.AnimationSet;
12 | import android.view.animation.ScaleAnimation;
13 | import android.view.animation.TranslateAnimation;
14 | import android.widget.HorizontalScrollView;
15 | import android.widget.ImageView;
16 | import android.widget.LinearLayout;
17 | import android.widget.RelativeLayout;
18 | import android.widget.TextView;
19 |
20 | import com.oyy.strong.R;
21 | import com.oyy.strong.utils.Utils;
22 |
23 |
24 | /**
25 | * ViewPager +tab栏
26 | * Created by ouyangyi
27 | * on 2016/5/13.
28 | */
29 | public class ViewPagerIndicator extends HorizontalScrollView implements
30 | OnPageChangeListener, OnClickListener {
31 |
32 | private RelativeLayout[] tabArr;// tab数组
33 | private String[] tabTexts;// tab标题数组
34 | private int[] tabTextWidthArr;// tab标题宽度数组
35 |
36 | private int currTabPosition;// 当前选中的tab
37 | private float fromTransX;// 游标在启动动画之前的X轴坐标
38 | private int tabSpacing;// tab之间的间距
39 | private int cursorPadding;// tab默认和cursor长度一样
40 | private int mTextColor = getResources().getColor(R.color.gray_666666);
41 | private float mTextSize = 15;
42 | private int tabLength;// tab个数
43 | private int diviceWidth;// 设备宽度px
44 | private float fromScaleX = 1.0f;
45 | private int baseCursorWidth;// 初始化的游标宽度, 缩放动画每次以此为标准
46 | private Boolean autoArrange = true;
47 | private Boolean isPageFirstScrolled = true;
48 | private int unSelectTextColor = getResources().getColor(R.color.gray_999999); //设置未选中字体的颜色
49 | private int selectTextColor = getResources().getColor(R.color.red_ff3254); //设置选中字体的颜色
50 |
51 |
52 | private Context mContext;
53 | private ViewPager mViewPager;
54 | private LinearLayout tabLy;// tab的横向线性布局
55 | private ImageView cursor;// 游标
56 | private Handler handler = new Handler();
57 | private View line, bottomLine;
58 | private RelativeLayout mainLayout;
59 |
60 | private int txtColor = -1; //tab文字颜色
61 |
62 |
63 | public ViewPagerIndicator(Context context) {
64 | super(context);
65 | // TODO Auto-generated constructor stub
66 | init();
67 | }
68 |
69 | public ViewPagerIndicator(Context context, AttributeSet attrs) {
70 | super(context, attrs);
71 | // TODO Auto-generated constructor stub
72 | init();
73 | }
74 |
75 | public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyle) {
76 | super(context, attrs, defStyle);
77 | // TODO Auto-generated constructor stub
78 | init();
79 | }
80 |
81 | /**
82 | * 初始化基本布局
83 | */
84 | private void init() {
85 | // TODO Auto-generated method stub
86 | mContext = getContext();
87 | diviceWidth = Utils.getInstance().getWidth(mContext);
88 | // 设置属性
89 | this.setBackgroundColor(getResources().getColor(R.color.white));
90 | this.setHorizontalScrollBarEnabled(false);// 去掉滚动条
91 | this.setVisibility(View.GONE);
92 | // 加载ScrollView的内容布局
93 | View v = View.inflate(mContext, R.layout.viewpager_indicator_layout, null);
94 | tabLy = (LinearLayout) v.findViewById(R.id.main_tab);// Tab布局
95 | cursor = (ImageView) v.findViewById(R.id.main_cursor);// 游标
96 | mainLayout = (RelativeLayout) v.findViewById(R.id.mainLayout);
97 | line = v.findViewById(R.id.line); //获得中间那条线
98 | bottomLine = v.findViewById(R.id.bottom_Line); //底部那条线
99 | // bottomLine.setLayoutParams(new LinearLayout.LayoutParams(diviceWidth, Utils.getInstance().dipTopx(mContext, 1)));
100 | this.addView(v);
101 | }
102 |
103 |
104 | public void setLinevisibility(boolean isShow) {
105 | bottomLine.setVisibility(isShow ? View.VISIBLE : View.GONE);
106 | }
107 |
108 | /**
109 | * 修改字体样式
110 | *
111 | * @param tabBg
112 | * @param unSelectTextColor * @param selectTextColor
113 | */
114 | public void setStyle(int tabBg, int unSelectTextColor, int selectTextColor, int cursorBg) {
115 | mainLayout.setBackgroundResource(tabBg);
116 | cursor.setBackgroundResource(cursorBg);
117 | bottomLine.setBackgroundColor(selectTextColor);
118 | this.unSelectTextColor = unSelectTextColor;
119 | this.selectTextColor = selectTextColor;
120 | }
121 |
122 | /**
123 | * 设置参数.
124 | *
125 | * @param tabSpacing tab间距
126 | * @param cursorPadding 游标向左右延伸的距离, 默认为0, 也即和tab文本一样长
127 | * @param viewPager 设置ViewPager
128 | * @param tabTexts tab内容数组
129 | * @param autoArrange 当tab长度不足屏幕宽度时, 是否自动进行摆列, 默认为true
130 | */
131 | public void setParams(int tabSpacing, int cursorPadding, String[] tabTexts,
132 | ViewPager viewPager, Boolean autoArrange) {
133 | if (tabTexts == null || tabTexts.length < 1) {
134 | return;
135 | }
136 | this.tabSpacing = tabSpacing;
137 | this.cursorPadding = cursorPadding;
138 | this.tabTexts = tabTexts;
139 | this.mViewPager = viewPager;
140 | this.autoArrange = autoArrange;
141 |
142 | this.setVisibility(View.VISIBLE);
143 | initTabSpacing();
144 | initTabs();
145 | initCursor();
146 | onPageSelected(currTabPosition);// 初始化tab样式和动画
147 | if (mViewPager != null) {
148 | mViewPager.addOnPageChangeListener(this);
149 | }
150 | }
151 |
152 | /**
153 | * 确定tab间隙长度
154 | */
155 | private void initTabSpacing() {
156 | // TODO Auto-generated method stub
157 | tabLength = tabTexts.length;
158 | int tabTextsWidth = 0;// tab文本总长度
159 | TextView tv = new TextView(mContext);
160 | tabTextWidthArr = new int[tabLength];
161 | for (int i = 0; i < tabLength; i++) {
162 | tv.setTextSize(mTextSize);
163 | tabTextWidthArr[i] = (int) tv.getPaint().measureText(tabTexts[i]);
164 | tabTextsWidth += tabTextWidthArr[i];
165 | }
166 | int scrollViewWidth = tabTextsWidth + tabLength * tabSpacing;
167 | // 默认, tab(包括间隙)总长度小于屏幕宽度时, 重新计算间距, 让各个tab均匀填满scrollview
168 | if (autoArrange && scrollViewWidth < diviceWidth) {
169 | tabSpacing = (diviceWidth - tabTextsWidth) / tabLength;
170 | }
171 | }
172 |
173 | /**
174 | * 初始化Tab
175 | */
176 | private void initTabs() {
177 | tabLy.removeAllViews();
178 | tabArr = new RelativeLayout[tabLength];
179 | TextView tabTextView = null;
180 | for (int i = 0; i < tabLength; i++) {
181 | // 初始化tabArr
182 | LinearLayout.LayoutParams tabParam = new LinearLayout.LayoutParams(
183 | tabTextWidthArr[i] + tabSpacing, LayoutParams.MATCH_PARENT);
184 | tabArr[i] = (RelativeLayout) View.inflate(mContext,
185 | R.layout.viewpager_indicator_tab, null);
186 | tabArr[i].setLayoutParams(tabParam);
187 | tabArr[i].setTag(i);
188 | tabArr[i].setOnClickListener(this);
189 | // 初始化tabTextViewArr
190 | tabTextView = (TextView) tabArr[i].findViewById(R.id.tab_tv);
191 | tabTextView.setTextSize(mTextSize);
192 | tabTextView.setTextColor(mTextColor);
193 | tabTextView.setText(tabTexts[i]);
194 | // 添加子tab
195 | tabLy.addView(tabArr[i], i);
196 | }
197 | }
198 |
199 | @Override
200 | public void onClick(View v) {
201 | int i = (Integer) v.getTag();
202 | setTabClick(i);
203 | }
204 |
205 | /**
206 | * 设置当前Tab点击时事件
207 | *
208 | * @param position
209 | */
210 | private void setTabClick(int position) {
211 | // 如果点击的为当前的Tab,则滚回到顶部, 否则切换
212 | if (position == currTabPosition) {
213 |
214 | } else {
215 | mViewPager.setCurrentItem(position);
216 | }
217 | }
218 |
219 | /**
220 | * 初始化cursor长度
221 | */
222 | private void initCursor() {
223 | // TODO Auto-generated method stub
224 | baseCursorWidth = tabTextWidthArr[currTabPosition] + cursorPadding;
225 | RelativeLayout.LayoutParams cursorLp = (RelativeLayout.LayoutParams) cursor
226 | .getLayoutParams();
227 | cursorLp.width = baseCursorWidth;
228 | cursor.setLayoutParams(cursorLp);
229 | }
230 |
231 | @Override
232 | public void onPageScrollStateChanged(int arg0) {
233 | }
234 |
235 | @Override
236 | public void onPageScrolled(int arg0, float arg1, int arg2) {
237 | }
238 |
239 | @Override
240 | public void onPageSelected(final int position) {
241 | // TODO Auto-generated method stub
242 | currTabPosition = position;
243 | setTabStyle(position);// 改变tab字体颜色
244 | handler.post(new Runnable() {
245 |
246 | @Override
247 | public void run() {
248 | setTabAnimation(position);
249 | }
250 | });
251 |
252 | if (onPageChangeListener != null) {
253 | onPageChangeListener.onPageSelected(currTabPosition);
254 | }
255 |
256 | if (onPageBackHandlerListener != null) {
257 | onPageBackHandlerListener.pageSelectHandler(currTabPosition);
258 | }
259 | }
260 |
261 |
262 | /**
263 | * 设置未选中tab字体的颜色
264 | */
265 | public void setUnSelectTextColor(int UnSelectTextColor) {
266 | this.unSelectTextColor = UnSelectTextColor;
267 | }
268 |
269 | /**
270 | * 设置选中tab字体的颜色
271 | */
272 | public void setSelectTextColor(int selectTextColor) {
273 | this.selectTextColor = selectTextColor;
274 | }
275 |
276 | /**
277 | * 设置tab字体的大小
278 | */
279 | public void setTextSize(int textSize) {
280 | this.mTextSize = textSize;
281 | }
282 |
283 |
284 | /**
285 | * 设置选中项背景和字体颜色
286 | *
287 | * @param position
288 | */
289 | private void setTabStyle(int position) {
290 | // 还原Tab的背景和字体颜色
291 | for (int i = 0; i < tabLength; i++) {
292 | ((TextView) tabArr[i].getChildAt(0)).setTextColor(unSelectTextColor);
293 | }
294 | // 改变 选中文本的颜色, 同时红点消失
295 | ((TextView) tabArr[position].getChildAt(0)).setTextColor(selectTextColor);
296 | }
297 |
298 | /**
299 | * 设置tab的动画
300 | *
301 | * @param position
302 | */
303 | private void setTabAnimation(final int position) {
304 | // 选中的tab中心位置到scrollview最左边位置的距离
305 | int offset = 0;
306 | for (int i = 0; i < position; i++) {
307 | offset += tabTextWidthArr[i] + tabSpacing;
308 | }
309 | offset += (tabTextWidthArr[position] + tabSpacing) / 2;
310 | // tab滚动到居中位置
311 | int scrollOffset = offset - diviceWidth / 2 <= 0 ? 0 : offset
312 | - diviceWidth / 2;
313 | smoothScrollTo(scrollOffset, 0);
314 |
315 | // 移动动画
316 | offset -= (tabTextWidthArr[0] / 2 + cursorPadding / 2);
317 |
318 | Animation translateAnim = new TranslateAnimation(isPageFirstScrolled ? offset : fromTransX, offset, 0,
319 | 0);
320 | fromTransX = offset;
321 | isPageFirstScrolled = false;
322 |
323 | // 缩放动画, 以初始化的cursor为缩放参考
324 | offset = tabTextWidthArr[currTabPosition] + cursorPadding;
325 | float toScaleX = (float) offset / (float) baseCursorWidth;
326 | Animation scaleAnim = new ScaleAnimation(fromScaleX, toScaleX, 1.0f,
327 | 1.0f, Animation.RELATIVE_TO_SELF, 0.5f,
328 | Animation.RELATIVE_TO_SELF, 0.5f);// 中间为缩放中心
329 | fromScaleX = toScaleX;
330 |
331 | // 将两个动画添加进集合, 同时执行
332 | AnimationSet anim = new AnimationSet(true);
333 | anim.addAnimation(scaleAnim); // 注意: 先添加缩放动画, 否则会出问题, 原因不知
334 | anim.addAnimation(translateAnim);
335 | anim.setDuration(300);
336 | anim.setFillAfter(true);
337 | cursor.startAnimation(anim); // 开始动画
338 | }
339 |
340 |
341 | private OnPageChangeListener onPageChangeListener;
342 |
343 | public void setOnPageChangeListener(
344 | OnPageChangeListener onPageChangeListener) {
345 | this.onPageChangeListener = onPageChangeListener;
346 | }
347 |
348 | //处理返回跟viewpager滑动冲突问题
349 | public interface OnPageBackHandlerListener {
350 | void pageSelectHandler(int position);
351 | }
352 |
353 | private OnPageBackHandlerListener onPageBackHandlerListener;
354 |
355 |
356 | public void setOnPageBackHandlerListener(OnPageBackHandlerListener onPageBackHandlerListener) {
357 | this.onPageBackHandlerListener = onPageBackHandlerListener;
358 | }
359 | }
360 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_sorry_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
26 |
27 |
34 |
35 |
48 |
49 |
50 |
51 |
59 |
60 |
67 |
68 |
81 |
82 |
83 |
84 |
92 |
93 |
100 |
101 |
114 |
115 |
116 |
117 |
118 |
126 |
127 |
134 |
135 |
148 |
149 |
150 |
151 |
159 |
160 |
167 |
168 |
181 |
182 |
183 |
184 |
192 |
193 |
200 |
201 |
214 |
215 |
216 |
217 |
225 |
226 |
233 |
234 |
247 |
248 |
249 |
250 |
258 |
259 |
266 |
267 |
280 |
281 |
282 |
283 |
291 |
292 |
299 |
300 |
313 |
314 |
315 |
316 |
331 |
332 |
346 |
347 |
353 |
354 |
355 |
356 |
357 |
--------------------------------------------------------------------------------
/app/src/main/java/com/oyy/strong/utils/PermissionUtil.java:
--------------------------------------------------------------------------------
1 | package com.oyy.strong.utils;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.content.Intent;
8 | import android.content.pm.PackageInfo;
9 | import android.content.pm.PackageManager;
10 | import android.net.Uri;
11 | import android.os.Build;
12 | import android.provider.Settings;
13 | import android.support.annotation.NonNull;
14 | import android.support.v4.app.ActivityCompat;
15 | import android.support.v4.app.Fragment;
16 | import android.support.v4.content.PermissionChecker;
17 | import android.support.v7.app.AlertDialog;
18 | import android.util.Log;
19 |
20 | import com.oyy.strong.R;
21 |
22 | import java.util.ArrayList;
23 | import java.util.HashMap;
24 | import java.util.List;
25 | import java.util.Map;
26 |
27 | /**
28 | * Created by
29 | * Administrator on 2017/4/24.
30 | */
31 |
32 | public class PermissionUtil {
33 |
34 | private static final String TAG = PermissionUtil.class.getSimpleName();
35 | public static final int CODE_RECORD_AUDIO = 0;
36 | public static final int CODE_GET_ACCOUNTS = 1;
37 | public static final int CODE_READ_PHONE_STATE = 2;
38 | public static final int CODE_CALL_PHONE = 3;
39 | public static final int CODE_CAMERA = 4;
40 | public static final int CODE_ACCESS_FINE_LOCATION = 5;
41 | public static final int CODE_ACCESS_COARSE_LOCATION = 6;
42 | public static final int CODE_READ_EXTERNAL_STORAGE = 7;
43 | public static final int CODE_WRITE_EXTERNAL_STORAGE = 8;
44 | public static final int CODE_MULTI_PERMISSION = 100;
45 |
46 | public static final String PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
47 | public static final String PERMISSION_GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
48 | public static final String PERMISSION_READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
49 | public static final String PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE;
50 | public static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
51 | public static final String PERMISSION_ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
52 | public static final String PERMISSION_ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
53 | public static final String PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
54 | public static final String PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
55 |
56 | private static final String[] requestPermissions = {
57 | PERMISSION_RECORD_AUDIO,
58 | PERMISSION_GET_ACCOUNTS,
59 | PERMISSION_READ_PHONE_STATE,
60 | PERMISSION_CALL_PHONE,
61 | PERMISSION_CAMERA,
62 | PERMISSION_ACCESS_FINE_LOCATION,
63 | PERMISSION_ACCESS_COARSE_LOCATION,
64 | PERMISSION_READ_EXTERNAL_STORAGE,
65 | PERMISSION_WRITE_EXTERNAL_STORAGE
66 | };
67 |
68 | public interface PermissionGrant {
69 | void onPermissionGranted(int requestCode);
70 | }
71 |
72 |
73 |
74 | public static void requestPermissionFragment(Fragment fragment, final Context mContext, final int requestCode, PermissionGrant permissionGrant) {
75 | if (mContext == null) {
76 | return;
77 | }
78 | Log.i(TAG, "requestPermission requestCode:" + requestCode);
79 | if (requestCode < 0 || requestCode >= requestPermissions.length) {
80 | Log.w(TAG, "requestPermission illegal requestCode:" + requestCode);
81 | return;
82 | }
83 | final String requestPermission = requestPermissions[requestCode];
84 | //如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED,
85 | // 但是,如果用户关闭了你申请的权限,ActivityCompat.checkSelfPermission(),会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null),
86 | // 你可以使用try{}catch(){},处理异常,也可以在这个地方,低于23就什么都不做,
87 | // 个人建议try{}catch(){}单独处理,提示用户开启权限。
88 | // if (Build.VERSION.SDK_INT < 23) {
89 | // return;
90 | // }
91 | int checkSelfPermission;
92 | try {
93 | checkSelfPermission = ActivityCompat.checkSelfPermission(mContext, requestPermission);
94 | } catch (RuntimeException e) {
95 | // Toast.makeText(mContext, "please open this permission", Toast.LENGTH_SHORT)
96 | // .show();
97 | Log.e(TAG, "RuntimeException:" + e.getMessage());
98 | return;
99 | }
100 | if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
101 | Log.i(TAG, "ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED");
102 | if (fragment.shouldShowRequestPermissionRationale(requestPermission)) {
103 | Log.i(TAG, "requestPermission shouldShowRequestPermissionRationale");
104 | shouldShowRationale(mContext,fragment, requestCode, requestPermission);
105 | } else {
106 | Log.d(TAG, "requestCameraPermission else");
107 | fragment.requestPermissions( new String[]{requestPermission}, requestCode);
108 | }
109 | } else {
110 | Log.d(TAG, "ActivityCompat.checkSelfPermission ==== PackageManager.PERMISSION_GRANTED");
111 | // Toast.makeText(mContext, "opened:" + requestPermissions[requestCode], Toast.LENGTH_SHORT).show();
112 | permissionGrant.onPermissionGranted(requestCode);
113 | }
114 | }
115 |
116 | /**
117 | * Requests permission.
118 | *
119 | * @param activity
120 | * @param requestCode request code, e.g. if you need request CAMERA permission,parameters is PermissionUtils.CODE_CAMERA
121 | */
122 | public static void requestPermission(final Activity activity, final int requestCode, PermissionGrant permissionGrant) {
123 | if (activity == null) {
124 | return;
125 | }
126 |
127 | Log.i(TAG, "requestPermission requestCode:" + requestCode);
128 | if (requestCode < 0 || requestCode >= requestPermissions.length) {
129 | Log.w(TAG, "requestPermission illegal requestCode:" + requestCode);
130 | return;
131 | }
132 |
133 | final String requestPermission = requestPermissions[requestCode];
134 |
135 | //如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED,
136 | // 但是,如果用户关闭了你申请的权限,ActivityCompat.checkSelfPermission(),会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null),
137 | // 你可以使用try{}catch(){},处理异常,也可以在这个地方,低于23就什么都不做,
138 | // 个人建议try{}catch(){}单独处理,提示用户开启权限。
139 | // if (Build.VERSION.SDK_INT < 23) {
140 | // return;
141 | // }
142 |
143 | int checkSelfPermission;
144 | try {
145 | checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
146 | } catch (RuntimeException e) {
147 | // Toast.makeText(activity, "please open this permission", Toast.LENGTH_SHORT)
148 | // .show();
149 | Log.e(TAG, "RuntimeException:" + e.getMessage());
150 | return;
151 | }
152 |
153 | if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
154 | Log.i(TAG, "ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED");
155 |
156 |
157 | if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
158 | Log.i(TAG, "requestPermission shouldShowRequestPermissionRationale");
159 | shouldShowRationale(activity, requestCode, requestPermission);
160 |
161 | } else {
162 | Log.d(TAG, "requestCameraPermission else");
163 | ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode);
164 | }
165 |
166 | } else {
167 | Log.d(TAG, "ActivityCompat.checkSelfPermission ==== PackageManager.PERMISSION_GRANTED");
168 | // Toast.makeText(activity, "opened:" + requestPermissions[requestCode], Toast.LENGTH_SHORT).show();
169 | permissionGrant.onPermissionGranted(requestCode);
170 | }
171 | }
172 |
173 | private static void requestMultiResult(Activity activity, String[] permissions, int[] grantResults, PermissionGrant permissionGrant) {
174 |
175 | if (activity == null) {
176 | return;
177 | }
178 |
179 | //TODO
180 | Log.d(TAG, "onRequestPermissionsResult permissions length:" + permissions.length);
181 | Map perms = new HashMap<>();
182 |
183 | ArrayList notGranted = new ArrayList<>();
184 | for (int i = 0; i < permissions.length; i++) {
185 | Log.d(TAG, "permissions: [i]:" + i + ", permissions[i]" + permissions[i] + ",grantResults[i]:" + grantResults[i]);
186 | perms.put(permissions[i], grantResults[i]);
187 | if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
188 | notGranted.add(permissions[i]);
189 | }
190 | }
191 |
192 | if (notGranted.size() == 0) {
193 | // Toast.makeText(activity, "all permission success" + notGranted, Toast.LENGTH_SHORT)
194 | // .show();
195 | permissionGrant.onPermissionGranted(CODE_MULTI_PERMISSION);
196 | } else {
197 | openSettingActivity(activity, "请求获取权限");
198 | }
199 |
200 | }
201 | /**
202 | * 一次申请多个权限 Activity
203 | */
204 | public static void requestMultiPermissions(final Activity activity, String[] requestPermissions, PermissionGrant grant) {
205 |
206 | final List permissionsList = getNoGrantedPermission(activity,requestPermissions, false);
207 | final List shouldRationalePermissionsList = getNoGrantedPermission(activity,requestPermissions, true);
208 |
209 | //TODO checkSelfPermission
210 | if (permissionsList == null || shouldRationalePermissionsList == null) {
211 | return;
212 | }
213 | Log.d(TAG, "requestMultiPermissions permissionsList:" + permissionsList.size() + ",shouldRationalePermissionsList:" + shouldRationalePermissionsList.size());
214 |
215 | if (permissionsList.size() > 0) {
216 | ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]),
217 | CODE_MULTI_PERMISSION);
218 | Log.d(TAG, "showMessageOKCancel requestPermissions");
219 |
220 | } else if (shouldRationalePermissionsList.size() > 0) {
221 | showMessageOKCancel(activity, "请求获取权限",
222 | new DialogInterface.OnClickListener() {
223 | @Override
224 | public void onClick(DialogInterface dialog, int which) {
225 | ActivityCompat.requestPermissions(activity, shouldRationalePermissionsList.toArray(new String[shouldRationalePermissionsList.size()]),
226 | CODE_MULTI_PERMISSION);
227 | Log.d(TAG, "showMessageOKCancel requestPermissions");
228 | }
229 | });
230 | } else {
231 | grant.onPermissionGranted(CODE_MULTI_PERMISSION);
232 | }
233 |
234 | }
235 | /**
236 | * 一次申请多个权限 Fragment
237 | */
238 | public static void requestMultiPermissionsFragment(final Fragment fragment, Context mContext, String[] requestPermissions, PermissionGrant grant) {
239 |
240 | final List permissionsList = getNoGrantedPermission((Activity) mContext,requestPermissions, false);
241 | final List shouldRationalePermissionsList = getNoGrantedPermission((Activity) mContext,requestPermissions, true);
242 |
243 | //TODO checkSelfPermission
244 | if (permissionsList == null || shouldRationalePermissionsList == null) {
245 | return;
246 | }
247 | Log.d(TAG, "requestMultiPermissions permissionsList:" + permissionsList.size() + ",shouldRationalePermissionsList:" + shouldRationalePermissionsList.size());
248 |
249 | if (permissionsList.size() > 0) {
250 | fragment.requestPermissions( permissionsList.toArray(new String[permissionsList.size()]),
251 | CODE_MULTI_PERMISSION);
252 | Log.d(TAG, "showMessageOKCancel requestPermissions");
253 |
254 | } else if (shouldRationalePermissionsList.size() > 0) {
255 | showMessageOKCancel(mContext, "请求获取权限",
256 | new DialogInterface.OnClickListener() {
257 | @Override
258 | public void onClick(DialogInterface dialog, int which) {
259 | fragment.requestPermissions( shouldRationalePermissionsList.toArray(new String[shouldRationalePermissionsList.size()]),
260 | CODE_MULTI_PERMISSION);
261 | Log.d(TAG, "showMessageOKCancel requestPermissions");
262 | }
263 | });
264 | } else {
265 | grant.onPermissionGranted(CODE_MULTI_PERMISSION);
266 | }
267 |
268 | }
269 |
270 | /**
271 | * 一次申请多个权限
272 | */
273 | public static void requestMultiPermissions(final Activity activity, PermissionGrant grant) {
274 |
275 | final List permissionsList = getNoGrantedPermission(activity, false);
276 | final List shouldRationalePermissionsList = getNoGrantedPermission(activity, true);
277 |
278 | //TODO checkSelfPermission
279 | if (permissionsList == null || shouldRationalePermissionsList == null) {
280 | return;
281 | }
282 | Log.d(TAG, "requestMultiPermissions permissionsList:" + permissionsList.size() + ",shouldRationalePermissionsList:" + shouldRationalePermissionsList.size());
283 |
284 | if (permissionsList.size() > 0) {
285 | ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]),
286 | CODE_MULTI_PERMISSION);
287 | Log.d(TAG, "showMessageOKCancel requestPermissions");
288 |
289 | } else if (shouldRationalePermissionsList.size() > 0) {
290 | showMessageOKCancel(activity, "请求获取权限",
291 | new DialogInterface.OnClickListener() {
292 | @Override
293 | public void onClick(DialogInterface dialog, int which) {
294 | ActivityCompat.requestPermissions(activity, shouldRationalePermissionsList.toArray(new String[shouldRationalePermissionsList.size()]),
295 | CODE_MULTI_PERMISSION);
296 | Log.d(TAG, "showMessageOKCancel requestPermissions");
297 | }
298 | });
299 | } else {
300 | grant.onPermissionGranted(CODE_MULTI_PERMISSION);
301 | }
302 |
303 | }
304 | private static void shouldShowRationale(Context context, final Fragment activity, final int requestCode, final String requestPermission) {
305 | //TODO
306 | String[] permissionsHint = context.getResources().getStringArray(R.array.permissions);
307 | showMessageOKCancel(context, "Rationale: " + permissionsHint[requestCode], new DialogInterface.OnClickListener() {
308 | @Override
309 | public void onClick(DialogInterface dialog, int which) {
310 | activity.requestPermissions(new String[]{requestPermission}, requestCode);
311 | Log.d(TAG, "showMessageOKCancel requestPermissions:" + requestPermission);
312 | }
313 | });
314 | }
315 |
316 | private static void shouldShowRationale(final Activity activity, final int requestCode, final String requestPermission) {
317 | //TODO
318 | String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions);
319 | showMessageOKCancel(activity, "Rationale: " + permissionsHint[requestCode], new DialogInterface.OnClickListener() {
320 | @Override
321 | public void onClick(DialogInterface dialog, int which) {
322 | ActivityCompat.requestPermissions(activity,
323 | new String[]{requestPermission},
324 | requestCode);
325 | Log.d(TAG, "showMessageOKCancel requestPermissions:" + requestPermission);
326 | }
327 | });
328 | }
329 | private static void showMessageOKCancel(final Context context, String message, DialogInterface.OnClickListener okListener) {
330 | new AlertDialog.Builder(context)
331 | .setMessage(message)
332 | .setPositiveButton(context.getString(R.string.enter), okListener)
333 | .setNegativeButton(context.getString(R.string.cancel),new DialogInterface.OnClickListener() {
334 | @Override
335 | public void onClick(DialogInterface dialog, int which) {
336 | ((Activity)context).finish();
337 | }
338 | })
339 | .create()
340 | .show();
341 |
342 | }
343 |
344 | private static void showMessageOKCancel(final Activity context, String message, DialogInterface.OnClickListener okListener) {
345 | new AlertDialog.Builder(context)
346 | .setMessage(message)
347 | .setPositiveButton(context.getString(R.string.enter), okListener)
348 | .setNegativeButton(context.getString(R.string.cancel), new DialogInterface.OnClickListener() {
349 | @Override
350 | public void onClick(DialogInterface dialog, int which) {
351 | context.finish();
352 | }
353 | })
354 | .create()
355 | .show();
356 |
357 | }
358 |
359 | /**
360 | * @param activity
361 | * @param requestCode Need consistent with requestPermission
362 | * @param permissions
363 | * @param grantResults
364 | */
365 | public static void requestPermissionsResult(final Activity activity, final int requestCode, @NonNull String[] permissions,
366 | @NonNull int[] grantResults, PermissionGrant permissionGrant) {
367 |
368 | if (activity == null) {
369 | return;
370 | }
371 | Log.d(TAG, "requestPermissionsResult requestCode:" + requestCode);
372 |
373 | if (requestCode == CODE_MULTI_PERMISSION) {
374 | requestMultiResult(activity, permissions, grantResults, permissionGrant);
375 | return;
376 | }
377 |
378 | if (requestCode < 0 || requestCode >= requestPermissions.length) {
379 | Log.w(TAG, "requestPermissionsResult illegal requestCode:" + requestCode);
380 | // Toast.makeText(activity, "illegal requestCode:" + requestCode, Toast.LENGTH_SHORT).show();
381 | return;
382 | }
383 |
384 | Log.i(TAG, "onRequestPermissionsResult requestCode:" + requestCode + ",permissions:" + permissions.toString()
385 | + ",grantResults:" + grantResults.toString() + ",length:" + grantResults.length);
386 |
387 | if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
388 | Log.i(TAG, "onRequestPermissionsResult PERMISSION_GRANTED");
389 | //TODO success, do something, can use callback
390 | permissionGrant.onPermissionGranted(requestCode);
391 |
392 | } else {
393 | //TODO hint user this permission function
394 | Log.i(TAG, "onRequestPermissionsResult PERMISSION NOT GRANTED");
395 | //TODO
396 | String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions);
397 | openSettingActivity(activity, "Result" + permissionsHint[requestCode]);
398 | }
399 |
400 | }
401 |
402 | private static void openSettingActivity(final Activity activity, String message) {
403 |
404 | showMessageOKCancel(activity, message, new DialogInterface.OnClickListener() {
405 | @Override
406 | public void onClick(DialogInterface dialog, int which) {
407 | Intent intent = new Intent();
408 | intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
409 | Log.d(TAG, "getPackageName(): " + activity.getPackageName());
410 | Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
411 | intent.setData(uri);
412 | activity.startActivity(intent);
413 | }
414 | });
415 | }
416 |
417 | /**
418 | * @param activity
419 | * @param isShouldRationale true: return no granted and shouldShowRequestPermissionRationale permissions, false:return no granted and !shouldShowRequestPermissionRationale
420 | * @return
421 | */
422 | public static ArrayList getNoGrantedPermission(Activity activity, boolean isShouldRationale) {
423 |
424 | ArrayList permissions = new ArrayList<>();
425 |
426 | for (int i = 0; i < requestPermissions.length; i++) {
427 | String requestPermission = requestPermissions[i];
428 |
429 |
430 | //TODO checkSelfPermission
431 | int checkSelfPermission = -1;
432 | try {
433 | checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
434 | } catch (RuntimeException e) {
435 | // Toast.makeText(activity, "please open those permission", Toast.LENGTH_SHORT)
436 | // .show();
437 | Log.e(TAG, "RuntimeException:" + e.getMessage());
438 | return null;
439 | }
440 |
441 | if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
442 | Log.i(TAG, "getNoGrantedPermission ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED:" + requestPermission);
443 |
444 | if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
445 | Log.d(TAG, "shouldShowRequestPermissionRationale if");
446 | if (isShouldRationale) {
447 | permissions.add(requestPermission);
448 | }
449 |
450 | } else {
451 |
452 | if (!isShouldRationale) {
453 | permissions.add(requestPermission);
454 | }
455 | Log.d(TAG, "shouldShowRequestPermissionRationale else");
456 | }
457 |
458 | }
459 | }
460 |
461 | return permissions;
462 | }
463 |
464 | /**
465 | * @param activity
466 | * @param isShouldRationale true: return no granted and shouldShowRequestPermissionRationale permissions, false:return no granted and !shouldShowRequestPermissionRationale
467 | * @return
468 | */
469 | public static ArrayList getNoGrantedPermission(Activity activity, String[] requestPermissions, boolean isShouldRationale) {
470 |
471 | ArrayList permissions = new ArrayList<>();
472 |
473 | for (int i = 0; i < requestPermissions.length; i++) {
474 | String requestPermission = requestPermissions[i];
475 |
476 |
477 | //TODO checkSelfPermission
478 | int checkSelfPermission = -1;
479 | try {
480 | checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
481 | } catch (RuntimeException e) {
482 | // Toast.makeText(activity, "please open those permission", Toast.LENGTH_SHORT)
483 | // .show();
484 | Log.e(TAG, "RuntimeException:" + e.getMessage());
485 | return null;
486 | }
487 |
488 | if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
489 | Log.i(TAG, "getNoGrantedPermission ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED:" + requestPermission);
490 |
491 | if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
492 | Log.d(TAG, "shouldShowRequestPermissionRationale if");
493 | if (isShouldRationale) {
494 | permissions.add(requestPermission);
495 | }
496 |
497 | } else {
498 |
499 | if (!isShouldRationale) {
500 | permissions.add(requestPermission);
501 | }
502 | Log.d(TAG, "shouldShowRequestPermissionRationale else");
503 | }
504 |
505 | }
506 | }
507 |
508 | return permissions;
509 | }
510 |
511 |
512 | /**
513 | * 权限是否授权
514 | * @param permission
515 | * @return
516 | */
517 | public boolean selfPermissionGranted(String permission, Context mContext) {
518 | int targetSdkVersion=0;
519 | try {
520 | final PackageInfo info = mContext.getPackageManager().getPackageInfo(
521 | mContext.getPackageName(), 0);
522 | targetSdkVersion = info.applicationInfo.targetSdkVersion;
523 | } catch (PackageManager.NameNotFoundException e) {
524 | e.printStackTrace();
525 | return true;
526 | }
527 | // For Android < Android M, self permissions are always granted.
528 | boolean result = true;
529 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
530 | if (targetSdkVersion >= Build.VERSION_CODES.M) {
531 | // targetSdkVersion >= Android M, we can
532 | // use Context#checkSelfPermission
533 | result = mContext.checkSelfPermission(permission)
534 | == PackageManager.PERMISSION_GRANTED;
535 | } else {
536 | // targetSdkVersion < Android M, we have to use PermissionChecker
537 | result = PermissionChecker.checkSelfPermission(mContext, permission)
538 | == PermissionChecker.PERMISSION_GRANTED;
539 | }
540 | }
541 | return result;
542 | }
543 | }
544 |
--------------------------------------------------------------------------------