├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── assets
│ │ │ ├── xposed_init
│ │ │ └── donate_wechat.png
│ │ ├── res
│ │ │ ├── drawable
│ │ │ │ ├── ic_done.png
│ │ │ │ ├── fab_label_background.xml
│ │ │ │ ├── bg_listview_item.xml
│ │ │ │ ├── button_static_bg.xml
│ │ │ │ └── button_bg.xml
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_exit.png
│ │ │ │ ├── ic_home.png
│ │ │ │ ├── ic_info.png
│ │ │ │ ├── ic_backup.png
│ │ │ │ ├── ic_default.png
│ │ │ │ ├── ic_refresh.png
│ │ │ │ ├── ic_restore.png
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_settings.png
│ │ │ │ ├── ic_back_white_24dp.png
│ │ │ │ ├── ic_favorite_white_24dp.png
│ │ │ │ ├── ic_more_vert_white_24dp.png
│ │ │ │ ├── ic_content_cut_white_24dp.png
│ │ │ │ ├── ic_select_all_white_24dp.png
│ │ │ │ ├── ic_content_copy_white_24dp.png
│ │ │ │ └── ic_content_paste_white_24dp.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_exit.png
│ │ │ │ ├── ic_home.png
│ │ │ │ ├── ic_info.png
│ │ │ │ ├── ic_backup.png
│ │ │ │ ├── ic_default.png
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_refresh.png
│ │ │ │ ├── ic_restore.png
│ │ │ │ ├── ic_settings.png
│ │ │ │ ├── ic_back_white_24dp.png
│ │ │ │ ├── ic_user_background.jpg
│ │ │ │ ├── ic_favorite_white_24dp.png
│ │ │ │ ├── ic_more_vert_white_24dp.png
│ │ │ │ ├── ic_select_all_white_24dp.png
│ │ │ │ ├── ic_content_copy_white_24dp.png
│ │ │ │ ├── ic_content_cut_white_24dp.png
│ │ │ │ └── ic_content_paste_white_24dp.png
│ │ │ ├── values-v19
│ │ │ │ └── dimens.xml
│ │ │ ├── values
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ ├── values-v21
│ │ │ │ └── dimens.xml
│ │ │ ├── layout
│ │ │ │ ├── list_fragment.xml
│ │ │ │ ├── list_fragment_app.xml
│ │ │ │ ├── preference_category_widget.xml
│ │ │ │ ├── dialog_json_input.xml
│ │ │ │ ├── activity_app_list.xml
│ │ │ │ ├── activity_settings.xml
│ │ │ │ ├── list_item_restore.xml
│ │ │ │ ├── navigation_content.xml
│ │ │ │ ├── preference_item.xml
│ │ │ │ ├── navigation_header.xml
│ │ │ │ ├── list_item_card_app.xml
│ │ │ │ ├── activity_set_text.xml
│ │ │ │ ├── setting_item.xml
│ │ │ │ ├── activity_donate.xml
│ │ │ │ └── list_item_card_text.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── color
│ │ │ │ └── item_color.xml
│ │ │ ├── menu
│ │ │ │ ├── menu_app_list.xml
│ │ │ │ ├── menu_action_mode.xml
│ │ │ │ ├── drawer_view.xml
│ │ │ │ └── menu_set_text.xml
│ │ │ ├── xml
│ │ │ │ └── preferences.xml
│ │ │ ├── values-ru
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rHK
│ │ │ │ └── strings.xml
│ │ │ ├── values-id
│ │ │ │ └── strings.xml
│ │ │ ├── values-de
│ │ │ │ └── strings.xml
│ │ │ ├── values-zh-rCN
│ │ │ │ └── strings.xml
│ │ │ └── values-zh-rTW
│ │ │ │ └── strings.xml
│ │ ├── java
│ │ │ └── liubaoyua
│ │ │ │ └── customtext
│ │ │ │ ├── entity
│ │ │ │ ├── DataLoadedEvent.java
│ │ │ │ ├── AppInfo.java
│ │ │ │ ├── CustomText.java
│ │ │ │ └── AppPreference.java
│ │ │ │ ├── utils
│ │ │ │ ├── XposedUtil.java
│ │ │ │ ├── PicassoTools.java
│ │ │ │ ├── IconLoader.java
│ │ │ │ ├── DBHelper.java
│ │ │ │ ├── Common.java
│ │ │ │ ├── AppListFilter.java
│ │ │ │ └── DBManager.java
│ │ │ │ ├── app
│ │ │ │ ├── AppHelper.java
│ │ │ │ └── MyApplication.java
│ │ │ │ ├── fragments
│ │ │ │ ├── FragmentAdapter.java
│ │ │ │ └── AppListFragment.java
│ │ │ │ ├── ui
│ │ │ │ ├── SettingActivity.java
│ │ │ │ └── DonateActivity.java
│ │ │ │ ├── adapters
│ │ │ │ ├── AppRecyclerAdapter.java
│ │ │ │ └── TextRecyclerAdapter.java
│ │ │ │ └── HookMethod.java
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── java
│ │ └── liubaoyua
│ │ └── customtext
│ │ └── ApplicationTest.java
├── app-release.apk
├── libs
│ └── pinyin4j-2.5.0.jar
├── deps
│ └── XposedBridgeApi-52.jar
├── app.iml
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── README.md
├── .idea
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── vcs.xml
├── compiler.xml
└── misc.xml
├── .gitignore
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | liubaoyua.customtext.HookMethod
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CustomText-MD
2 | CustomText with MD
3 | 文本自定义 MD
4 |
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/app-release.apk
--------------------------------------------------------------------------------
/app/libs/pinyin4j-2.5.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/libs/pinyin4j-2.5.0.jar
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/deps/XposedBridgeApi-52.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/deps/XposedBridgeApi-52.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/app/src/main/assets/donate_wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/assets/donate_wechat.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/drawable/ic_done.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_exit.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_home.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_info.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_exit.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_home.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_info.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_backup.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_default.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_refresh.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_restore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_restore.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_backup.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_settings.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_default.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_refresh.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_restore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_restore.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_settings.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_back_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_back_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v19/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 24dp
4 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_back_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_back_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_user_background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_user_background.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_favorite_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_favorite_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_more_vert_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_more_vert_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_favorite_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_favorite_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_content_cut_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_content_cut_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_select_all_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_select_all_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_more_vert_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_more_vert_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_select_all_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_select_all_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_content_copy_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_content_copy_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_content_paste_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xhdpi/ic_content_paste_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_content_copy_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_content_copy_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_content_cut_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_content_cut_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_content_paste_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liubaoyua/CustomText-MD/HEAD/app/src/main/res/mipmap-xxhdpi/ic_content_paste_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0dp
4 | 4dp
5 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/entity/DataLoadedEvent.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.entity;
2 |
3 | /**
4 | * Created by liubaoyua on 2015/8/22 0022.
5 | */
6 | public class DataLoadedEvent {
7 | }
8 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/utils/XposedUtil.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.utils;
2 |
3 | /**
4 | * Created by liubaoyua on 2016/4/21.
5 | */
6 | public class XposedUtil {
7 |
8 | public static boolean isXposedEnable() {
9 | return false;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_fragment_app.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/fab_label_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
11 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/liubaoyua/customtext/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_listview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_static_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 200dp
4 | 16dp
5 | 40dp
6 |
7 | 16dp
8 | 16dp
9 |
10 | 0dp
11 | 0dp
12 |
--------------------------------------------------------------------------------
/app/src/main/res/color/item_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_app_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/preference_category_widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_json_input.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
21 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Fri Sep 04 16:53:31 CST 2015
16 | systemProp.http.proxyHost=127.0.0.1
17 | systemProp.http.proxyPort=1080
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_app_list.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | -
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/app/AppHelper.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.app;
2 |
3 | import android.os.Environment;
4 |
5 | import java.util.List;
6 |
7 | import liubaoyua.customtext.entity.AppInfo;
8 | import liubaoyua.customtext.utils.Utils;
9 |
10 | /**
11 | * Created by liubaoyua on 2015/9/3.
12 | */
13 | public class AppHelper {
14 |
15 | public static final String EXTERNAL_DIR = Environment
16 | .getExternalStorageDirectory().getAbsolutePath() + "/Custom Text/";
17 |
18 | public static MyApplication getApplication() {
19 | return MyApplication.getInstance();
20 | }
21 |
22 | public static List getAllList() {
23 | return getApplication().getAllList();
24 | }
25 |
26 | public static void setAllList(List allList) {
27 | getApplication().setAllList(allList);
28 | }
29 |
30 | public static List getRecentList() {
31 | return Utils.getRecentList(getAllList());
32 | }
33 |
34 | public static void terminal() {
35 | getApplication().onTerminate();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #f1f1f1
4 | #808080
5 | #B2000000
6 |
7 | #666666
8 | #216b74ff
9 |
10 |
11 |
12 |
13 | #2196F3
14 | #1976D2
15 | #FF5252
16 | #ffcdd2
17 | #CFD8DC
18 | #212121
19 | #727272
20 | #FFFFFF
21 | #B6B6B6
22 |
23 |
24 | #FFFFFFFF
25 |
26 |
27 | #EEEEEE
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
16 |
17 |
23 |
24 |
25 |
26 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_action_mode.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/utils/PicassoTools.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.utils;
2 |
3 | import android.content.Context;
4 |
5 | import com.squareup.picasso.LruCache;
6 | import com.squareup.picasso.Picasso;
7 |
8 | public abstract class PicassoTools {
9 |
10 | private static Picasso instance;
11 | private static LruCache picassoCache;
12 |
13 | public static void init(Context ctx) {
14 | if (instance == null) {
15 | Picasso.Builder builder = new Picasso.Builder(ctx);
16 | builder.addRequestHandler(new IconLoader(ctx));
17 | picassoCache = new LruCache(ctx);
18 | builder.memoryCache(picassoCache);
19 | instance = builder.build();
20 | }
21 | }
22 |
23 |
24 | public static synchronized Picasso getInstance() {
25 | /*if (instance == null) {
26 | Picasso.Builder builder = new Picasso.Builder(ctx);
27 | picassoCache = new LruCache(ctx);
28 | builder.memoryCache(picassoCache);
29 | instance = builder.build();
30 | Picasso.setSingletonInstance(instance);
31 | } */
32 | return instance;
33 | }
34 |
35 | public static void clearCache() {
36 | picassoCache.clear();
37 | }
38 |
39 | public static void destroy() {
40 | instance.shutdown();
41 | instance = null;
42 | picassoCache.clear();
43 | picassoCache = null;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | android {
3 | compileSdkVersion 23
4 | buildToolsVersion "23.0.2"
5 |
6 | defaultConfig {
7 | applicationId "liubaoyua.customtext"
8 | minSdkVersion 15
9 | targetSdkVersion 22
10 | versionCode 201605011
11 | versionName "2.3.1 ԅ(¯﹃¯ԅ)"
12 | // resConfigs "nodpi", "hdpi","xxhdpi"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled true
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 | dataBinding {
22 | enabled = true
23 | }
24 |
25 |
26 | lintOptions {
27 | checkReleaseBuilds false
28 | // Or, if you prefer, you can continue to check for errors in release builds,
29 | // but continue the build even when errors are found:
30 | abortOnError false
31 | }
32 | }
33 |
34 | dependencies {
35 | compile fileTree(dir: 'libs', include: ['*.jar'])
36 | provided fileTree(dir: 'deps', include: ['*.jar'])
37 | compile 'de.greenrobot:eventbus:2.4.0'
38 | compile 'com.android.support:appcompat-v7:23.3.0'
39 | compile 'com.android.support:design:23.3.0'
40 | compile 'com.squareup.picasso:picasso:2.5.2'
41 | compile 'com.android.support:cardview-v7:23.3.0'
42 | compile 'com.android.support:recyclerview-v7:23.3.0'
43 | compile 'com.rengwuxian.materialedittext:library:2.1.4'
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_restore.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
25 |
26 |
39 |
40 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
19 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/fragments/FragmentAdapter.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.fragments;
2 |
3 | import android.support.v4.app.FragmentManager;
4 | import android.support.v4.app.FragmentPagerAdapter;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import java.util.List;
9 |
10 | public class FragmentAdapter extends FragmentPagerAdapter {
11 | private List mFragments;
12 | private List mTitles;
13 |
14 | public FragmentAdapter(FragmentManager fm, List fragments, List titles) {
15 | super(fm);
16 | mFragments = fragments;
17 | mTitles = titles;
18 | }
19 |
20 | @Override
21 | public boolean isViewFromObject(View view, Object object) {
22 | return super.isViewFromObject(view, object);
23 | }
24 |
25 |
26 | @Override
27 | public long getItemId(int position) {
28 | return super.getItemId(position);
29 | }
30 |
31 | @Override
32 | public int getItemPosition(Object object) {
33 | return super.getItemPosition(object);
34 | }
35 |
36 | @Override
37 | public Object instantiateItem(ViewGroup container, int position) {
38 | return super.instantiateItem(container, position);
39 | }
40 |
41 | @Override
42 | public AppListFragment getItem(int position) {
43 | return mFragments.get(position);
44 | }
45 |
46 | @Override
47 | public int getCount() {
48 | return mFragments.size();
49 | }
50 |
51 | @Override
52 | public CharSequence getPageTitle(int position) {
53 | return mTitles.get(position);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/utils/IconLoader.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.utils;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageManager;
5 | import android.graphics.Bitmap;
6 | import android.graphics.drawable.Drawable;
7 |
8 | import com.squareup.picasso.Picasso;
9 | import com.squareup.picasso.Request;
10 | import com.squareup.picasso.RequestHandler;
11 |
12 | public class IconLoader extends RequestHandler {
13 |
14 | /**
15 | * Uri scheme for app icons
16 | */
17 | public static final String SCHEME_PACKAGE_NAME = "packageName";
18 | private PackageManager mPackageManager;
19 |
20 | public IconLoader(Context context) {
21 | mPackageManager = context.getPackageManager();
22 | }
23 |
24 | @Override
25 | public boolean canHandleRequest(Request data) {
26 | // only handle Uris matching our scheme
27 | return (SCHEME_PACKAGE_NAME.equals(data.uri.getScheme()));
28 | }
29 |
30 | @Override
31 | public Result load(Request request, int networkPolicy) {
32 | Drawable drawable = null;
33 | Bitmap bitmap = null;
34 | String schemeStr = request.uri.getScheme();
35 | String packageName = request.uri.getSchemeSpecificPart();
36 | if (SCHEME_PACKAGE_NAME.equals(schemeStr)) {
37 | try {
38 | drawable = mPackageManager.getApplicationIcon(packageName);
39 | } catch (Throwable e) {
40 | drawable = null;
41 | }
42 | if (drawable != null) {
43 | bitmap = Utils.drawableToBitmap(drawable);
44 | }
45 | }
46 | return new Result(bitmap, Picasso.LoadedFrom.DISK);
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/navigation_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
24 |
25 |
30 |
31 |
32 |
33 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/preference_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
27 |
28 |
36 |
37 |
38 |
39 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/navigation_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/drawer_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_card_app.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
20 |
21 |
26 |
32 |
33 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_set_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
16 |
17 |
24 |
25 |
26 |
27 |
33 |
34 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
12 |
15 |
18 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
40 |
41 |
47 |
48 |
49 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/utils/DBHelper.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.utils;
2 |
3 | import android.content.Context;
4 | import android.database.sqlite.SQLiteDatabase;
5 | import android.database.sqlite.SQLiteOpenHelper;
6 |
7 |
8 | /**
9 | * Created by liubaoyua on 2015/7/27 0027.
10 | */
11 | public class DBHelper extends SQLiteOpenHelper {
12 |
13 | public final static int DATABASE_VERSION = 2;
14 | public final static String TABLE_NAME = "APP_INFO";
15 | public final static String DATABASE_NAME = "AppList.db3";
16 | private static DBHelper mInstance;
17 |
18 | public DBHelper(Context context) {
19 | super(context, DBHelper.DATABASE_NAME, null, DATABASE_VERSION);
20 | }
21 |
22 | public synchronized static DBHelper getInstance(Context context) {
23 | if (mInstance == null) {
24 | mInstance = new DBHelper(context);
25 | }
26 | return mInstance;
27 | }
28 |
29 |
30 | @Override
31 | public void onCreate(SQLiteDatabase db) {
32 | DBManager.createDateBase(db);
33 | }
34 |
35 | @Override
36 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
37 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
38 | }
39 |
40 | public static class Properties {
41 | public final static Property packageName = new Property("packageName", true, "PACKAGE_NAME");
42 | public final static Property appName = new Property("appName", false, "APP_NAME");
43 | public final static Property appNamePinyin = new Property("appNamePinYin", false, "APP_NAME_PIN_YIN");
44 | public final static Property appNameHeadChar = new Property("appNameHeadChar", false, "APP_NAME_HEAD_CHAR");
45 | public final static Property firstInstallTime = new Property("firstInstallTime", false, "FIRST_INSTALL_TIME");
46 | public final static Property lastUpdateTime = new Property("lastUpdateTime", false, "LAST_UPDATE_TIME");
47 | public final static Property state = new Property("state", false, "STATE");
48 | }
49 |
50 | public static class Property {
51 | public final String name;
52 | public final boolean primaryKey;
53 | public final String columnName;
54 |
55 | public Property(String name, boolean primaryKey, String columnName) {
56 | this.name = name;
57 | this.primaryKey = primaryKey;
58 | this.columnName = columnName;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
22 |
23 |
24 |
30 |
31 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/entity/AppInfo.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.entity;
2 |
3 | import android.content.pm.PackageInfo;
4 |
5 | import liubaoyua.customtext.utils.Utils;
6 |
7 | /**
8 | * Created by liubaoyua on 2015/6/20 0020.
9 | * AppInfo
10 | */
11 | public class AppInfo {
12 |
13 | public final static int ENABLED = 1;
14 | public final static int UNKNOWN = 0;
15 | public final static int DISABLED = -1;
16 |
17 | public String packageName = "";
18 | public String appName = "";
19 | public String appNamePinYin = "";
20 | public String appNameHeadChar = "";
21 | public long firstInstallTime = 0L;
22 | public long lastUpdateTime = 0L;
23 | public int state = UNKNOWN;
24 |
25 | public AppInfo(PackageInfo packageInfo, String appName) {
26 | this.appName = appName;
27 | this.packageName = packageInfo.packageName;
28 | this.firstInstallTime = packageInfo.firstInstallTime;
29 | this.lastUpdateTime = packageInfo.lastUpdateTime;
30 | this.appNamePinYin = Utils.getPinYin(appName.toLowerCase());
31 | this.appNameHeadChar = Utils.getPinYinHeadChar(appName.toLowerCase());
32 | }
33 |
34 | public AppInfo(PackageInfo packageInfo, String appName, String packageName) {
35 | this.appName = appName;
36 | this.packageName = packageName;
37 | this.firstInstallTime = packageInfo.firstInstallTime;
38 | this.lastUpdateTime = packageInfo.lastUpdateTime;
39 | this.appNamePinYin = Utils.getPinYin(appName.toLowerCase());
40 | this.appNameHeadChar = Utils.getPinYinHeadChar(appName.toLowerCase());
41 | }
42 |
43 | public AppInfo(String packageName, String appName, String appNamePinYin,
44 | String appNameHeadChar, long firstInstallTime, long lastUpdateTime, int state) {
45 | this.packageName = packageName;
46 | this.appName = appName;
47 | this.appNamePinYin = appNamePinYin;
48 | this.appNameHeadChar = appNameHeadChar;
49 | this.firstInstallTime = firstInstallTime;
50 | this.lastUpdateTime = lastUpdateTime;
51 | this.state = state;
52 | }
53 |
54 | @Override
55 | public String toString() {
56 | return "AppInfoItem{" +
57 | "appName='" + appName + '\'' +
58 | ", appNamePinYin='" + appNamePinYin + '\'' +
59 | ", appNameHeadChar='" + appNameHeadChar + '\'' +
60 | ", packageName='" + packageName + '\'' +
61 | ", firstInstallTime=" + firstInstallTime +
62 | ", lastUpdateTime=" + lastUpdateTime +
63 | '}';
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/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/setting_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
24 |
25 |
33 |
34 |
35 |
36 |
37 |
43 |
44 |
53 |
54 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/utils/Common.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.utils;
2 |
3 | /**
4 | * Created by liubaoyua on 2015/6/19 0019.
5 | * constants
6 | */
7 | public class Common {
8 | public final static String POSITION_ARG = "position";
9 | public final static String PACKAGE_NAME_ARG = "packageName";
10 |
11 | public final static String PACKAGE_NAME = "liubaoyua.customtext";
12 | public final static String SYSTEM_UI_PACKAGE_NAME = "com.android.systemui";
13 | public final static String GLOBAL_SETTING_PACKAGE_NAME = "liubaoyua.customtext_preferences";
14 | public final static String SHARING_SETTING_PACKAGE_NAME = "liubaoyua.customtext_sharing_preferences";
15 |
16 | public final static String BACKUP_DIR = "/Custom Text";
17 | public final static String MAX_PAGE_OLD = "maxpage";
18 | public final static String ORI_TEXT_PREFIX = "oristr";
19 | public final static String NEW_TEXT_PREFIX = "newstr";
20 |
21 | public final static String MESSAGE = "defaultMessage";
22 | public final static String PACKAGE_VERSION_CODE = "versionCode";
23 | public final static String DEFAULT_MESSAGE = "模块可用~";
24 | public final static String DEFAULT_APP_NAME = "^文本自定义$";
25 | public final static String CHECK_UPDATE = "checkUpdate";
26 | // in the setting page
27 | public final static String SETTING_ATTENTION = "attention";
28 | public final static String SETTING_XPOSED_DEBUG_MODE = "xposedDebug";
29 | public final static String SETTING_MODULE_SWITCH = "moduleswitch";
30 |
31 | public final static String SETTING_MORE_TYPE = "ImageText";
32 | public final static String SETTING_USE_REGEX = "UseRegex";
33 | public final static String SETTING_USE_HTML = "UseHtml";
34 |
35 | public final static String SETTING_VERSION_INFO = "version";
36 | public final static String SETTING_HACK_SUCCEED_MESSAGE = "hackSucceedMessage";
37 | // in pref
38 | public final static String PREF_HEAD_VIEW = "HeadViewPicture";
39 | public final static String PREFS = "liubaoyua.customtext_preferences";
40 | public final static String PREFS_HAS_DATABASE = "hasDataBase";
41 |
42 | public static Boolean DEBUG = true;
43 | public static Boolean CRASH_LOG = false;
44 | public static Boolean FAST_DEBUG = false;
45 | public static Boolean XPOSED_DEBUG = false;
46 | public static String TAG = "liubaoyua";
47 | public static int DEFAULT_NUM = 10;
48 | public static int REQUEST_CODE_FOR_IMAGE = 123;
49 | public static int REQUEST_CODE_FOR_FILE = 682;
50 |
51 | public static String FRAG_TYPE = "type";
52 | public static String FRAG_TYPE_ALL_LIST = "AllLIst";
53 | public static String FRAG_TYPE_RECENT_LIST = "RecentList";
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/entity/CustomText.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.entity;
2 |
3 | import org.json.JSONException;
4 | import org.json.JSONObject;
5 |
6 | import java.util.regex.Pattern;
7 |
8 | /**
9 | * Created by liubaoyua on 2015/6/19 0019.
10 | * this class is for customtext.
11 | */
12 | public class CustomText {
13 | public String oriText = "";
14 | public String newText = "";
15 | public Pattern oriPattern;
16 |
17 | public boolean isCheck = false;
18 |
19 |
20 | public CustomText() {
21 | }
22 |
23 | public CustomText(String oriText, String newText) {
24 | this.oriText = oriText;
25 | this.newText = newText;
26 | }
27 |
28 | public CustomText(CustomText text) {
29 | this.oriText = text.oriText;
30 | this.newText = text.newText;
31 | this.oriPattern = text.oriPattern;
32 | }
33 |
34 | public Pattern createOriginPattern() {
35 | try {
36 | oriPattern = Pattern.compile(oriText);
37 | } catch (Exception e) {
38 | e.printStackTrace();
39 | }
40 | return oriPattern;
41 | }
42 |
43 | public Pattern getPattern() {
44 | if (oriPattern == null) {
45 | createOriginPattern();
46 | }
47 | return oriPattern;
48 | }
49 |
50 | public String getOriText() {
51 | return oriText;
52 | }
53 |
54 | public String getNewText() {
55 | return newText;
56 | }
57 |
58 | @Override
59 | public boolean equals(Object o) {
60 | if (this == o) return true;
61 | if (o == null || getClass() != o.getClass()) return false;
62 |
63 | CustomText that = (CustomText) o;
64 |
65 | if (!oriText.equals(that.oriText)) return false;
66 | return newText.equals(that.newText);
67 |
68 | }
69 |
70 | @Override
71 | public int hashCode() {
72 | int result = oriText.hashCode();
73 | result = 31 * result + newText.hashCode();
74 | return result;
75 | }
76 |
77 | @Override
78 | public String toString() {
79 | return "CustomText{" +
80 | "oriText='" + oriText + '\'' +
81 | ", newText='" + newText + '\'' +
82 | '}';
83 | }
84 |
85 | public boolean isEmpty() {
86 | if (this.newText == null || this.newText.equals("")) {
87 | if (this.oriText == null || this.oriText.equals("")) {
88 | return true;
89 | }
90 | }
91 | return false;
92 | }
93 |
94 | public JSONObject toJson() throws JSONException {
95 | JSONObject o = new JSONObject();
96 | o.put("ori", oriText).put("new", newText);
97 | return o;
98 | }
99 |
100 | public static CustomText fromJsonObject(JSONObject o) {
101 | CustomText text = new CustomText();
102 | text.oriText = o.optString("ori");
103 | text.newText = o.optString("new");
104 | return text;
105 | }
106 |
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_donate.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
17 |
18 |
25 |
26 |
27 |
28 |
35 |
36 |
43 |
44 |
51 |
52 |
60 |
61 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_set_text.xml:
--------------------------------------------------------------------------------
1 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
7 |
8 |
14 |
19 |
24 |
29 |
30 |
31 |
34 |
35 |
36 |
40 |
41 |
42 |
43 |
45 |
49 |
52 |
53 |
56 |
59 |
60 |
64 |
65 |
66 |
69 |
72 |
73 |
74 |
77 |
78 |
79 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/utils/AppListFilter.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.utils;
2 |
3 | import android.widget.Filter;
4 |
5 | import java.text.Collator;
6 | import java.util.ArrayList;
7 | import java.util.Collections;
8 | import java.util.Comparator;
9 | import java.util.List;
10 | import java.util.Locale;
11 |
12 | import liubaoyua.customtext.adapters.AppRecyclerAdapter;
13 | import liubaoyua.customtext.entity.AppInfo;
14 |
15 | /**
16 | * Created by liubaoyua on 2015/6/20 0020.
17 | * this is a filter of appInfo class.
18 | */
19 | public class AppListFilter extends Filter {
20 | private AppRecyclerAdapter adapter;
21 | private List appList;
22 | private CharSequence text = "";
23 |
24 | public AppListFilter(AppRecyclerAdapter adapter, List appList) {
25 | super();
26 | this.adapter = adapter;
27 | this.appList = appList;
28 | }
29 |
30 | public List getAppList() {
31 | return this.appList;
32 | }
33 |
34 | public void setAppList(List newList) {
35 | this.appList = newList;
36 | }
37 |
38 | @Override
39 | protected FilterResults performFiltering(final CharSequence constraint) {
40 | text = constraint;
41 | List items = new ArrayList<>();
42 | items.clear();
43 | // 判断 包名 和 应用名 里面是否含有 constraint
44 | // 并且在中文下进行拼音和拼音首字过滤
45 | FilterResults results = new FilterResults();
46 | if (constraint != null && constraint.length() > 0) {
47 | for (int i = 0; i < appList.size(); i++) {
48 | AppInfo appInfo = appList.get(i);
49 | if (appInfo.packageName.contains(constraint)) {
50 | items.add(appInfo);
51 | } else if (appInfo.appName.contains(constraint)) {
52 | items.add(appInfo);
53 | } else if (Locale.getDefault().equals(Locale.CHINA) || Locale.getDefault().equals(Locale.TAIWAN)) {
54 | if (appInfo.appNamePinYin.contains(constraint)) {
55 | items.add(appInfo);
56 | } else if (appInfo.appNameHeadChar.contains(constraint)) {
57 | items.add(appInfo);
58 | }
59 | }
60 | }
61 | Collections.sort(items, new Comparator() {
62 | @Override
63 | public int compare(AppInfo lhs, AppInfo rhs) {
64 | int tag = 0;
65 | if (lhs.appName.toLowerCase().startsWith(constraint.toString().toLowerCase())) {
66 | tag += 1;
67 | }
68 | if (rhs.appName.toLowerCase().startsWith(constraint.toString().toLowerCase())) {
69 | tag += 2;
70 | }
71 | switch (tag) {
72 | // 0 ,3 为都不是或都是以cons..开头
73 | case 0:
74 | case 3:
75 | return Collator.getInstance(Locale.getDefault()).compare(lhs.appName, rhs.appName);
76 | case 1:
77 | return -1;
78 | case 2:
79 | default:
80 | return 1;
81 | }
82 | }
83 | });
84 | results.values = items;
85 | results.count = items.size();
86 | return results;
87 | } else {
88 | results.values = appList;
89 | results.count = appList.size();
90 | return results;
91 | }
92 |
93 | }
94 |
95 | @Override
96 | protected void publishResults(CharSequence constraint, FilterResults results) {
97 | // NOTE: this function is *always* called from the UI thread.
98 | if (adapter != null) {
99 | adapter.setAppList((List) results.values);
100 | adapter.notifyDataSetChanged();
101 | }
102 | }
103 |
104 | public void reFilter() {
105 | filter(text);
106 | }
107 |
108 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_card_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
26 |
27 |
41 |
42 |
43 |
44 |
57 |
58 |
67 |
68 |
69 |
70 |
78 |
79 |
93 |
94 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/ui/SettingActivity.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.ui;
2 |
3 | import android.app.FragmentManager;
4 | import android.content.ComponentName;
5 | import android.content.Intent;
6 | import android.content.pm.PackageInfo;
7 | import android.content.pm.PackageManager;
8 | import android.databinding.DataBindingUtil;
9 | import android.net.Uri;
10 | import android.os.Bundle;
11 | import android.preference.Preference;
12 | import android.preference.PreferenceFragment;
13 | import android.preference.PreferenceScreen;
14 | import android.support.v7.app.AppCompatActivity;
15 | import android.support.v7.widget.Toolbar;
16 | import android.view.MenuItem;
17 | import android.view.View;
18 |
19 | import liubaoyua.customtext.R;
20 | import liubaoyua.customtext.databinding.ActivitySettingsBinding;
21 | import liubaoyua.customtext.utils.Common;
22 | import liubaoyua.customtext.utils.Utils;
23 |
24 | public class SettingActivity extends AppCompatActivity {
25 | private SettingsFragment mSettingsFragment;
26 | private Toolbar toolbar;
27 |
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | ActivitySettingsBinding b = DataBindingUtil.setContentView(this, R.layout.activity_settings);
33 | toolbar = b.toolbar;
34 | setupToolbar();
35 | Utils.configStatusBarColor(this);
36 | if (savedInstanceState == null) {
37 | mSettingsFragment = new SettingsFragment();
38 | FragmentManager fragmentManager = getFragmentManager();
39 | fragmentManager.beginTransaction().replace(R.id.setting_content, mSettingsFragment).commit();
40 | }
41 |
42 | }
43 |
44 | private void setupToolbar() {
45 | toolbar.setTitle(R.string.title_activity_settings);
46 | toolbar.setNavigationIcon(R.mipmap.ic_back_white_24dp);
47 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
48 | @Override
49 | public void onClick(View v) {
50 | onBackPressed();
51 | }
52 | });
53 | }
54 |
55 | @Override
56 | public boolean onOptionsItemSelected(MenuItem item) {
57 | // Handle action bar item clicks here. The action bar will
58 | // automatically handle clicks on the Home/Up button, so long
59 | // as you specify a parent activity in AndroidManifest.xml.
60 | int id = item.getItemId();
61 |
62 | if (id == android.R.id.home) {
63 | onBackPressed();
64 | }
65 |
66 | return super.onOptionsItemSelected(item);
67 | }
68 |
69 | public static class SettingsFragment extends PreferenceFragment {
70 |
71 | Preference version;
72 |
73 | @Override
74 | public void onCreate(Bundle savedInstanceState) {
75 | super.onCreate(savedInstanceState);
76 | addPreferencesFromResource(R.xml.preferences);
77 | version = findPreference(Common.SETTING_VERSION_INFO);
78 | String versionName = Utils.getPackageInfoByPackageName(getActivity(), getActivity().getPackageName()).versionName;
79 | version.setTitle(version.getTitle() + " " + versionName);
80 | }
81 |
82 | @Override
83 | public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
84 | super.onPreferenceTreeClick(preferenceScreen, preference);
85 | if (preference == findPreference(Common.CHECK_UPDATE)) {
86 | try {
87 | PackageInfo packageInfo = getActivity().getPackageManager().getPackageInfo("com.coolapk.market", 0);
88 | if (packageInfo != null) {
89 | Intent intent = getActivity().getPackageManager().getLaunchIntentForPackage("com.coolapk.market");
90 | if (intent == null) {
91 | Intent urlIntent = new Intent();
92 | urlIntent.setData(Uri.parse("http://www.coolapk.com/apk/" + Common.PACKAGE_NAME));
93 | urlIntent.setAction(Intent.ACTION_VIEW);
94 | startActivity(urlIntent);
95 | } else {
96 | intent.setComponent(new ComponentName("com.coolapk.market", "com.coolapk.market" + ".AppViewActivity"));
97 | intent.setData(Uri.parse("market://details?id=" + Common.PACKAGE_NAME));
98 | startActivity(intent);
99 | }
100 | }
101 | return true;
102 | } catch (Exception e) {
103 | e.printStackTrace();
104 | }
105 | } else if (preference == findPreference(Common.SETTING_ATTENTION)) {
106 | PackageInfo packageInfo = null;
107 | try {
108 | packageInfo = getActivity().getPackageManager().getPackageInfo(Common.PACKAGE_NAME, 0);
109 | } catch (PackageManager.NameNotFoundException e) {
110 | e.printStackTrace();
111 | }
112 | if (packageInfo != null) {
113 | Utils.showMessage(getActivity(), packageInfo.versionName);
114 | }
115 | }
116 | return false;
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/adapters/AppRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.adapters;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.drawable.Drawable;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ImageView;
11 | import android.widget.TextView;
12 |
13 | import com.squareup.picasso.Picasso;
14 | import com.squareup.picasso.Target;
15 |
16 | import java.util.List;
17 |
18 | import liubaoyua.customtext.R;
19 | import liubaoyua.customtext.entity.AppInfo;
20 | import liubaoyua.customtext.utils.AppListFilter;
21 | import liubaoyua.customtext.utils.Common;
22 | import liubaoyua.customtext.utils.IconLoader;
23 | import liubaoyua.customtext.utils.PicassoTools;
24 |
25 | /**
26 | * Created by liubaoyua on 2015/6/20 0020.
27 | */
28 | public class AppRecyclerAdapter extends RecyclerView.Adapter {
29 |
30 | private Context mContext;
31 | private List appList;
32 | private AppListFilter filter;
33 | private OnItemClickListener listener;
34 | private Drawable icon;
35 | private Drawable errorIcon;
36 |
37 |
38 | public AppRecyclerAdapter(Context mContext, List appList) {
39 | this.mContext = mContext;
40 | this.appList = appList;
41 | filter = new AppListFilter(this, appList);
42 | icon = mContext.getResources().getDrawable(R.mipmap.ic_default);
43 | errorIcon = mContext.getResources().getDrawable(R.mipmap.ic_launcher);
44 | }
45 |
46 | public AppListFilter getFilter() {
47 | return filter;
48 | }
49 |
50 | @Override
51 | public AppRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
52 | View view = LayoutInflater.from(mContext).inflate(R.layout.list_item_card_app, parent, false);
53 | return new ViewHolder(view, listener);
54 | }
55 |
56 |
57 | @Override
58 | public void onBindViewHolder(final AppRecyclerAdapter.ViewHolder holder, int position) {
59 | final AppInfo temp = appList.get(position);
60 | holder.appNameView.setText(temp.appName);
61 | holder.packageNameView.setText(temp.packageName);
62 | if (temp.state == AppInfo.ENABLED) {
63 | holder.appNameView.setTextColor(mContext.getResources().getColor(android.R.color.holo_red_light));
64 | holder.packageNameView.setTextColor(mContext.getResources().getColor(android.R.color.holo_red_light));
65 | } else {
66 | holder.appNameView.setTextColor(mContext.getResources().getColor(android.R.color.black));
67 | holder.packageNameView.setTextColor(mContext.getResources().getColor(android.R.color.black));
68 | }
69 |
70 | PicassoTools.getInstance()
71 | .load(IconLoader.SCHEME_PACKAGE_NAME + ":" + temp.packageName)
72 | .noFade().into(holder);
73 | }
74 |
75 | @Override
76 | public int getItemCount() {
77 | return appList == null ? 0 : appList.size();
78 | }
79 |
80 | public List getAppList() {
81 | return appList;
82 | }
83 |
84 | public void setAppList(List appList) {
85 | this.appList = appList;
86 | }
87 |
88 | /**
89 | * 设置监听方法
90 | *
91 | * @param listener
92 | */
93 | public void setOnItemClickListener(OnItemClickListener listener) {
94 | this.listener = listener;
95 | }
96 |
97 | /**
98 | * 内部接口回调方法
99 | */
100 | public interface OnItemClickListener {
101 | void onItemClick(int position, String packageName);
102 | }
103 |
104 | public class ViewHolder extends RecyclerView.ViewHolder implements Target {
105 | public final View mView;
106 | public TextView appNameView;
107 | public TextView packageNameView;
108 | public ImageView iconView;
109 |
110 | public ViewHolder(final View view, final OnItemClickListener listener) {
111 | super(view);
112 | mView = view;
113 | appNameView = (TextView) mView.findViewById(R.id.app_name);
114 | packageNameView = (TextView) mView.findViewById(R.id.package_name);
115 | iconView = (ImageView) mView.findViewById(R.id.image_icon);
116 |
117 | view.setOnClickListener(new View.OnClickListener() {
118 | @Override
119 | public void onClick(View view) {
120 | if (listener != null)
121 | listener.onItemClick(getAdapterPosition(), appList.get(getAdapterPosition()).packageName);
122 | }
123 | });
124 | }
125 |
126 | @Override
127 | public void onPrepareLoad(Drawable placeHolderDrawable) {
128 | if (!packageNameView.getText().toString().startsWith(Common.PACKAGE_NAME)) {
129 | iconView.setImageDrawable(icon);
130 | } else {
131 | iconView.setImageDrawable(errorIcon);
132 | }
133 |
134 | }
135 |
136 | @Override
137 | public void onBitmapFailed(Drawable errorDrawable) {
138 |
139 | }
140 |
141 | @Override
142 | public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
143 | iconView.setImageBitmap(bitmap);
144 | }
145 | }
146 | }
147 |
148 |
149 |
--------------------------------------------------------------------------------
/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/liubaoyua/customtext/fragments/AppListFragment.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.fragments;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v7.widget.DefaultItemAnimator;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.LinearLayout;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | import de.greenrobot.event.EventBus;
18 | import liubaoyua.customtext.R;
19 | import liubaoyua.customtext.adapters.AppRecyclerAdapter;
20 | import liubaoyua.customtext.app.AppHelper;
21 | import liubaoyua.customtext.entity.AppInfo;
22 | import liubaoyua.customtext.entity.DataLoadedEvent;
23 | import liubaoyua.customtext.ui.SetTextActivity;
24 | import liubaoyua.customtext.utils.Common;
25 | import liubaoyua.customtext.utils.Utils;
26 |
27 | public class AppListFragment extends Fragment {
28 |
29 | private static int count = 0;
30 | private RecyclerView mRecyclerView;
31 | private AppRecyclerAdapter appRecyclerAdapter;
32 | private String type = Common.FRAG_TYPE_ALL_LIST;
33 |
34 | @Override
35 | public void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | Bundle arguments = getArguments();
38 | EventBus.getDefault().register(this);
39 | if (arguments == null) {
40 | throw new IllegalStateException("Fragment with no Arguments");
41 | } else {
42 | type = arguments.getString(Common.FRAG_TYPE);
43 | }
44 | }
45 |
46 | @Override
47 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
48 | View view = inflater.inflate(R.layout.list_fragment_app, container, false);
49 | mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
50 | return mRecyclerView;
51 | }
52 |
53 | @Override
54 | public void onActivityCreated(Bundle savedInstanceState) {
55 | super.onActivityCreated(savedInstanceState);
56 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mRecyclerView.getContext(), LinearLayout.VERTICAL, false));
57 | mRecyclerView.setItemAnimator(new DefaultItemAnimator());
58 |
59 | List appList = new ArrayList<>();
60 | if (type.equals(Common.FRAG_TYPE_ALL_LIST)) {
61 | appList.addAll(AppHelper.getAllList());
62 | } else if (type.equals(Common.FRAG_TYPE_RECENT_LIST)) {
63 | appList.addAll(AppHelper.getRecentList());
64 | }
65 |
66 | appRecyclerAdapter = new AppRecyclerAdapter(getActivity(), appList);
67 | mRecyclerView.setAdapter(appRecyclerAdapter);
68 | appRecyclerAdapter.setOnItemClickListener(new AppRecyclerAdapter.OnItemClickListener() {
69 | @Override
70 | public void onItemClick(int position, String packageName) {
71 | Intent intent = new Intent(getActivity(), SetTextActivity.class);
72 | intent.putExtra(Common.POSITION_ARG, position);
73 | intent.putExtra(Common.PACKAGE_NAME_ARG, packageName);
74 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
75 | getActivity().startActivity(intent);
76 | }
77 | });
78 | }
79 |
80 | public void filter(String nameFilter) {
81 | if (appRecyclerAdapter != null)
82 | appRecyclerAdapter.getFilter().filter(nameFilter);
83 | }
84 |
85 | public List getAppList() {
86 | if (appRecyclerAdapter != null) {
87 | return appRecyclerAdapter.getFilter().getAppList();
88 | } else {
89 | throw new IllegalStateException("appRecyclerAdapter is null");
90 | }
91 | }
92 |
93 | public List getShowingAppList() {
94 | if (appRecyclerAdapter != null) {
95 | return appRecyclerAdapter.getAppList();
96 | } else {
97 | throw new IllegalStateException("appRecyclerAdapter is null");
98 | }
99 | }
100 |
101 | public void stopScrolling() {
102 | if (mRecyclerView != null) {
103 | mRecyclerView.stopScroll();
104 | }
105 | }
106 |
107 | public void scrollToTopOrBottom() {
108 | if (mRecyclerView == null) {
109 | Utils.myLog("in method scrollToTopOrBottom : mRecyclerView is null");
110 | return;
111 | }
112 |
113 | if (mRecyclerView.canScrollVertically(-1)) {
114 | mRecyclerView.smoothScrollToPosition(0);
115 | } else {
116 | // mRecyclerView.smoothScrollToPosition(appRecyclerAdapter.getItemCount() - 1);
117 | }
118 |
119 | }
120 |
121 | @Override
122 | public void onDestroy() {
123 | super.onDestroy();
124 | EventBus.getDefault().unregister(this);
125 | }
126 |
127 |
128 | public void onEventMainThread(DataLoadedEvent event) {
129 | if (type.equals(Common.FRAG_TYPE_ALL_LIST)) {
130 | if (appRecyclerAdapter != null) {
131 | appRecyclerAdapter.getFilter().setAppList(AppHelper.getAllList());
132 | appRecyclerAdapter.getFilter().reFilter();
133 | }
134 | } else if (type.equals(Common.FRAG_TYPE_RECENT_LIST)) {
135 | if (appRecyclerAdapter != null) {
136 | appRecyclerAdapter.getFilter().setAppList(AppHelper.getRecentList());
137 | appRecyclerAdapter.getFilter().reFilter();
138 | }
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/entity/AppPreference.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.entity;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import liubaoyua.customtext.app.AppHelper;
10 | import liubaoyua.customtext.utils.Common;
11 |
12 | /**
13 | * Created by liubaoyua on 2016/4/28.
14 | */
15 | public class AppPreference {
16 |
17 | // appPrefs 用于当前 packageName 所在包的数据读写, globalPrefs 是全局信息
18 | private SharedPreferences appPrefs, globalPrefs;
19 | private int maxPage = 0;
20 | private boolean hookEnable;
21 |
22 | private boolean useRegex;
23 | private boolean moreType;
24 |
25 | private List data;
26 | private String packageName;
27 |
28 | public AppPreference(String packageName) {
29 | Context context = AppHelper.getApplication();
30 | this.packageName = packageName;
31 | globalPrefs = context.getSharedPreferences(Common.PREFS, Context.MODE_WORLD_READABLE);
32 | appPrefs = context.getSharedPreferences(packageName, Context.MODE_WORLD_READABLE);
33 | maxPage = appPrefs.getInt(Common.MAX_PAGE_OLD, 0);
34 |
35 | int count = (maxPage + 1) * Common.DEFAULT_NUM;
36 |
37 | data = new ArrayList<>();
38 | for (int i = 0; i < count; i++) {
39 | String oriText = appPrefs.getString(Common.ORI_TEXT_PREFIX + i, "");
40 | String newText = appPrefs.getString(Common.NEW_TEXT_PREFIX + i, "");
41 | CustomText customText = new CustomText(oriText, newText);
42 | data.add(customText);
43 | }
44 | hookEnable = globalPrefs.getBoolean(packageName, false);
45 |
46 | if (appPrefs.contains(Common.SETTING_MORE_TYPE)) {
47 | moreType = appPrefs.getBoolean(Common.SETTING_MORE_TYPE, false);
48 | } else {
49 | moreType = globalPrefs.getBoolean(Common.SETTING_MORE_TYPE, false);
50 | }
51 |
52 | if (appPrefs.contains(Common.SETTING_USE_REGEX)) {
53 | useRegex = appPrefs.getBoolean(Common.SETTING_USE_REGEX, false);
54 | } else {
55 | useRegex = globalPrefs.getBoolean(Common.SETTING_USE_REGEX, false);
56 | }
57 |
58 | }
59 |
60 | public ArrayList getClonedData() {
61 | ArrayList texts = new ArrayList<>();
62 | for (CustomText text : data) {
63 | texts.add(new CustomText(text));
64 | }
65 | return texts;
66 | }
67 |
68 | public boolean isHookEnable() {
69 | return hookEnable;
70 | }
71 |
72 | public void setHookEnable(boolean hookEnable) {
73 | this.hookEnable = hookEnable;
74 | globalPrefs.edit().putBoolean(packageName, hookEnable).commit();
75 | }
76 |
77 | public void removeEmptyItems() {
78 | int count = (maxPage + 1) * Common.DEFAULT_NUM;
79 |
80 | SharedPreferences.Editor editor = appPrefs.edit();
81 | for (int i = 0; i < count; i++) {
82 | if (appPrefs.contains(Common.ORI_TEXT_PREFIX + i)) {
83 | if (appPrefs.getString(Common.ORI_TEXT_PREFIX + i, "").equals(""))
84 | editor.remove(Common.ORI_TEXT_PREFIX + i);
85 | }
86 | if (appPrefs.contains(Common.NEW_TEXT_PREFIX + i)) {
87 | if (appPrefs.getString(Common.NEW_TEXT_PREFIX + i, "").equals(""))
88 | editor.remove(Common.NEW_TEXT_PREFIX + i);
89 | }
90 | }
91 | editor.commit();
92 | }
93 |
94 | public boolean isUseRegex() {
95 | return useRegex;
96 | }
97 |
98 | public void setMoreTypeEnable(boolean moreType) {
99 | this.moreType = moreType;
100 | appPrefs.edit().putBoolean(Common.SETTING_MORE_TYPE, moreType).commit();
101 | }
102 |
103 | public void setUseRegex(boolean useRegex) {
104 | this.useRegex = useRegex;
105 | appPrefs.edit().putBoolean(Common.SETTING_USE_REGEX, moreType).commit();
106 | }
107 |
108 | public boolean isMoreTypeEnabled() {
109 | return moreType;
110 | }
111 |
112 | public boolean isDataEquals(List texts) {
113 | return data.equals(texts);
114 | }
115 |
116 | public void setNewData(List newData) {
117 | data.clear();
118 | for (int i = 0; i < newData.size(); i++) {
119 | data.add(new CustomText(newData.get(i)));
120 | }
121 | SharedPreferences.Editor mEditor = appPrefs.edit();
122 |
123 | int all = (maxPage + 1) * Common.DEFAULT_NUM;
124 |
125 | for (int i = 0; i < newData.size(); i++) {
126 | CustomText temp = newData.get(i);
127 | if (!temp.oriText.isEmpty()) {
128 | mEditor.putString(Common.ORI_TEXT_PREFIX + i, temp.oriText);
129 | } else {
130 | mEditor.remove(Common.ORI_TEXT_PREFIX + i);
131 | }
132 |
133 | if (!temp.newText.isEmpty()) {
134 | mEditor.putString(Common.NEW_TEXT_PREFIX + i, temp.newText);
135 | } else {
136 | mEditor.remove(Common.NEW_TEXT_PREFIX + i);
137 | }
138 | }
139 |
140 | for (int i = newData.size(); i < all; i++) {
141 | mEditor.remove(Common.ORI_TEXT_PREFIX + i);
142 | mEditor.remove(Common.NEW_TEXT_PREFIX + i);
143 | }
144 |
145 | int delta = newData.size() - newData.size() / Common.DEFAULT_NUM * Common.DEFAULT_NUM == 0 ? 0 : 1;
146 | int pageNum = newData.size() / Common.DEFAULT_NUM + delta;
147 | mEditor.putInt(Common.MAX_PAGE_OLD, pageNum - 1);
148 | mEditor.commit();
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Все приложения
4 | Custom Text
5 | Очистить
6 | Удалить
7 | Действие
8 | Очистить
9 | Буфер обмена пуст.
10 | Закрыть
11 | Модуль предоставляет возможность изменять тексты на любые, по Вашему желанию. Разработано liubaoyua.
12 |
13 | Изменения ещё не сохранены
14 | Введите название бэкапа
15 | Загрузка
16 | Не сохранять
17 | Сохранить
18 | Сохранить сейчас?
19 | Выберите бэкап
20 | Что сделать?
21 | Обнаружена ошибка. Выход. Сообщение об ошибке:
22 | Введите название
23 | Хотите импортировать бэкап и переписать все текущие настройки?
24 | Ошибка резервного копирования: %s
25 | Настройки экспортированы в папку: %s
26 | Папка не существует: %s
27 | Ошибка импорта: %s
28 | Импорт успешно выполнен; перезапустие приложение, чтобы применить настройки.
29 | Резервные копии не найдены
30 | Добавить ещё элемент
31 | Сведения о приложении
32 | БЭКАП
33 | Очистить все
34 | Очистить пустые
35 | ВЫХОД
36 | ГЛАВНАЯ
37 | О ПРИЛОЖЕНИИ
38 | Открыть в маркете
39 | Перезапустить приложение
40 | ВОССТАНОВЛЕНИЕ
41 | Поиск
42 | НАСТРОЙКИ
43 | ПЕРЕКЛЮЧАТЕЛЬ
44 | Новый текст
45 | Да
46 | Исходный текст
47 | Последние
48 | Имя пакета или приложения
49 | О модуле
50 | Внимание!
51 | Модуль разработан просто для удовольствия. Используйте его на свой страх и риск. Я не несу ответственности за то, что Вы с ним делаете.
52 | Автор: liubaoyua. Нажмите, чтобы посетить мой микро-блог
53 | Проверка обновлений
54 | Благодарности
55 | Пользовательское сообщение
56 | Измените сообщение, чтобы посмотреть, как это работает:)
57 | Это работает :)
58 | Связаться со мной
59 | "Email:liubaoyua@gmail.com
60 |
61 | CoolApk Market: пишите на этот адрес: @liubaoyua и я увижу"
62 | Расширенная замена
63 | Позволяет заменять больше типов текста (если в виджетах, что-то отображается неверно, отключите этот параметр)
64 | Общие настройки
65 | Понравилось приложение?
66 | Если Вам нравится это приложение, пожалуйста, оцените его в Google Play.
67 | Модуль отключён
68 | Модуль включён
69 | Функционал модуля
70 | Этот подуль поможет Вам заменять тексты в: IDs, названиях приложений, подписи оператора и т.д. Требуется Xposed.
71 | Custom Text
72 | Включение модуля
73 | успешно
74 | Включить?
75 | Настройки
76 | Отмена
77 |
78 |
79 |
80 | - Добавить выше
81 | - Копировать
82 | - Удалить
83 | - Вырезать
84 | - Вставить
85 | - Добавить ниже
86 |
87 | Глобальный замена
88 | включены приложения
89 | редактор
90 |
91 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/utils/DBManager.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.utils;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.database.sqlite.SQLiteDatabase;
6 | import android.database.sqlite.SQLiteException;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | import liubaoyua.customtext.entity.AppInfo;
12 |
13 | /**
14 | * Created by liubaoyua on 2015/7/27 0027.
15 | */
16 | public class DBManager {
17 |
18 | private static DBManager instance;
19 | private DBHelper helper;
20 | private SQLiteDatabase db;
21 |
22 | private DBManager(Context context) {
23 | helper = DBHelper.getInstance(context);
24 | db = helper.getWritableDatabase();
25 | }
26 |
27 | public static DBManager getInstance(Context context) {
28 | if (instance == null) {
29 | instance = new DBManager(context);
30 | return instance;
31 | } else {
32 | return instance;
33 | }
34 | }
35 |
36 |
37 | public static void createDateBase(SQLiteDatabase db) {
38 | try {
39 | db.execSQL("CREATE TABLE IF NOT EXISTS " + "'APP_INFO' (" + //
40 | "'PACKAGE_NAME' TEXT PRIMARY KEY ," + // 1: packageName
41 | "'APP_NAME' TEXT NOT NULL ," + // 2: appName
42 | "'APP_NAME_PIN_YIN' TEXT NOT NULL ," + // 3: appNamePinYin
43 | "'APP_NAME_HEAD_CHAR' TEXT NOT NULL ," + // 4: appNameHeadChar
44 | "'FIRST_INSTALL_TIME' INTEGER," + // firstInstallTime
45 | "'LAST_UPDATE_TIME' INTEGER," + // lastUpdateTime
46 | "'STATE' INTEGER );"); // state
47 | } catch (SQLiteException e) {
48 | e.printStackTrace();
49 | }
50 | }
51 |
52 | protected static String[] getColumnNames(SQLiteDatabase db, String tableName) {
53 | String[] columnNames = null;
54 | Cursor c = null;
55 | try {
56 | c = db.rawQuery("PRAGMA table_info(" + tableName + ")", null);
57 | if (null != c) {
58 | int columnIndex = c.getColumnIndex("name");
59 | if (-1 == columnIndex) {
60 | return null;
61 | }
62 |
63 | int index = 0;
64 | columnNames = new String[c.getCount()];
65 | for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
66 | columnNames[index] = c.getString(columnIndex);
67 | index++;
68 | }
69 | }
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | } finally {
73 | if (c != null) {
74 | c.close();
75 | }
76 | }
77 | return columnNames;
78 | }
79 |
80 | public void insert(AppInfo appInfo) {
81 | db.execSQL(
82 | "INSERT INTO " + DBHelper.TABLE_NAME + " VALUES(?,?,?,?,?,?,?)",
83 | new Object[]{appInfo.packageName, appInfo.appName,
84 | appInfo.appNamePinYin, appInfo.appNameHeadChar, appInfo.firstInstallTime,
85 | appInfo.lastUpdateTime, appInfo.state});
86 | }
87 |
88 | public void insert(List appInfoList) {
89 | if (appInfoList == null) {
90 | return;
91 | }
92 | for (AppInfo appInfo : appInfoList) {
93 | insert(appInfo);
94 | }
95 | }
96 |
97 | private void updateCustom(AppInfo appInfo) {
98 | db.execSQL("UPDATE " + DBHelper.TABLE_NAME
99 | + " SET "
100 | + DBHelper.Properties.state.columnName + " = ? , "
101 | + " WHERE " + DBHelper.Properties.packageName.columnName + " = ?",
102 | new Object[]{appInfo.state, appInfo.packageName});
103 | }
104 |
105 | public void delete(String packageName) {
106 | db.execSQL("DELETE FROM " + DBHelper.TABLE_NAME + " WHERE " + DBHelper.Properties.packageName.columnName + " = ? ",
107 | new String[]{packageName});
108 | }
109 |
110 | public void delete() {
111 | db.execSQL("DELETE FROM " + DBHelper.TABLE_NAME);
112 | }
113 |
114 | public List query() {
115 | List appInfoList = new ArrayList<>();
116 | Cursor cursor = queryTheCursor();
117 | AppInfo appInfo;
118 | while (cursor.moveToNext()) {
119 | int offset = cursor.getColumnIndex(DBHelper.Properties.packageName.columnName);
120 | appInfo = new AppInfo( //
121 | cursor.getString(offset), // packageName
122 | cursor.isNull(offset + 1) ? "" : cursor.getString(offset + 1), // appName
123 | cursor.isNull(offset + 2) ? "" : cursor.getString(offset + 2), // appNamePinYin
124 | cursor.isNull(offset + 3) ? "" : cursor.getString(offset + 3), // appNameHeadChar
125 | cursor.isNull(offset + 4) ? 0 : cursor.getLong(offset + 4), // firstInstallTime
126 | cursor.isNull(offset + 5) ? 0 : cursor.getLong(offset + 5), // lastUpdateTime
127 | cursor.isNull(offset + 6) ? 0 : cursor.getInt(offset + 6) // state
128 | );
129 | appInfoList.add(appInfo);
130 | }
131 | return appInfoList;
132 | }
133 |
134 | public Cursor queryTheCursor() {
135 | return db.rawQuery("SELECT * FROM " + DBHelper.TABLE_NAME, new String[]{});
136 | }
137 |
138 | public void close() {
139 | if (db != null && db.isOpen()) {
140 | db.close();
141 | }
142 | db = null;
143 | helper.close();
144 | instance = null;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/ui/DonateActivity.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.ui;
2 |
3 | import android.content.Intent;
4 | import android.databinding.DataBindingUtil;
5 | import android.graphics.PorterDuff;
6 | import android.graphics.drawable.Drawable;
7 | import android.net.Uri;
8 | import android.os.Build;
9 | import android.os.Bundle;
10 | import android.os.Environment;
11 | import android.support.annotation.Nullable;
12 | import android.support.v7.app.AppCompatActivity;
13 | import android.view.View;
14 | import android.widget.Toast;
15 |
16 | import java.io.File;
17 | import java.io.FileOutputStream;
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.io.OutputStream;
21 |
22 | import liubaoyua.customtext.R;
23 | import liubaoyua.customtext.databinding.ActivityDonateBinding;
24 |
25 | /**
26 | * Created by liubaoyua on 2016/4/22.
27 | */
28 | public class DonateActivity extends AppCompatActivity implements View.OnClickListener {
29 |
30 |
31 | ActivityDonateBinding binding;
32 |
33 |
34 | @Override
35 | protected void onCreate(@Nullable Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 |
38 | binding = DataBindingUtil.setContentView(this, R.layout.activity_donate);
39 | int color = getResources().getColor(R.color.primary);
40 |
41 | binding.toolbar.setNavigationOnClickListener(new View.OnClickListener() {
42 | @Override
43 | public void onClick(View v) {
44 | onBackPressed();
45 | }
46 | });
47 |
48 | binding.toolbar.setTitle(R.string.menu_donate);
49 |
50 | binding.buttonAlipay.setOnClickListener(this);
51 | tintBackground(binding.buttonAlipay, color);
52 |
53 | binding.buttonPaypal.setOnClickListener(this);
54 | tintBackground(binding.buttonPaypal, color);
55 |
56 | binding.buttonWechat.setOnClickListener(this);
57 | tintBackground(binding.buttonWechat, color);
58 | }
59 |
60 | public void tintBackground(View view, int color) {
61 | if (view == null) {
62 | return;
63 | }
64 | Drawable drawable = view.getBackground();
65 | drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
66 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN)
67 | view.setBackground(drawable);
68 | }
69 |
70 | @Override
71 | public void onClick(View v) {
72 | Intent intent = new Intent();
73 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
74 | switch (v.getId()) {
75 | case R.id.button_wechat:
76 | try {
77 | donateViaWeChat();
78 | } catch (Throwable e) {
79 | e.printStackTrace();
80 | }
81 | break;
82 | case R.id.button_alipay:
83 | try {
84 | startActivity(new Intent("android.intent.action.VIEW",
85 | Uri.parse("https://ds.alipay.com/?from=mobilecodec&" +
86 | "scheme=alipayqr%3A%2F%2Fplatformapi%2Fstartapp%3FsaId%3D10000007%26clientVersion%3D3.7.0.0718%26qrcode%3D" +
87 | "https%253A%252F%252Fqr.alipay.com%252Fapeiz5mouj1akmf2cc%253F_s%253Dweb-other")));
88 | } catch (Exception e) {
89 | e.printStackTrace();
90 | }
91 | break;
92 | case R.id.button_paypal:
93 | try {
94 | startActivity(new Intent("android.intent.action.VIEW",
95 | Uri.parse("https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=liubaoyua@gmail.com")));
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | }
99 | break;
100 | }
101 |
102 | }
103 |
104 | private boolean donateViaWeChat() {
105 | File path = getPngPath();
106 | if (path == null) {
107 | return false;
108 | }
109 | try {
110 | InputStream is = getAssets().open("donate_wechat.png");
111 | byte[] buffer = new byte[0x1000];
112 | OutputStream os = new FileOutputStream(path);
113 | int length;
114 | while ((length = is.read(buffer)) > 0) {
115 | os.write(buffer, 0, length);
116 | }
117 | os.flush();
118 | is.close();
119 | } catch (IOException e) {
120 | return false;
121 | }
122 | Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
123 | mediaScanIntent.setData(Uri.fromFile(path));
124 | sendBroadcast(mediaScanIntent);
125 | Intent intent = new Intent("com.tencent.mm.action.BIZSHORTCUT");
126 | intent.setPackage("com.tencent.mm");
127 | intent.putExtra("LauncherUI.From.Scaner.Shortcut", true);
128 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
129 | try {
130 | startActivity(intent);
131 | for (int i = 0; i < 0x3; ++i) {
132 | Toast.makeText(this, R.string.str_wechat_choose_qr_code, Toast.LENGTH_LONG).show();
133 | }
134 | } catch (Throwable t) {
135 | }
136 | return true;
137 | }
138 |
139 | private File getPngPath() {
140 | File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
141 | if (dir == null) {
142 | return null;
143 | }
144 |
145 | File screenshots = new File(dir, "Screenshots");
146 | if (!screenshots.exists()) {
147 | screenshots.mkdirs();
148 | }
149 | return new File(screenshots, "donate_wechat.png");
150 | }
151 | }
152 |
153 |
154 |
--------------------------------------------------------------------------------
/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 C:\Programs\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 | -ignorewarnings
19 |
20 | -optimizationpasses 88
21 | -dontusemixedcaseclassnames
22 | -dontskipnonpubliclibraryclasses
23 | -dontpreverify
24 | -verbose
25 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
26 |
27 | #四大组件排除 自定义的view排除(因为xml中使用的是hardcode)
28 | -keep public class * extends android.support.v4.**
29 | -keep public class * extends android.app.Fragment
30 | -keep public class * extends android.app.Activity
31 | -keep public class * extends android.app.Application {*;}
32 | -keep public class * extends android.app.Service
33 | -keep public class * extends android.content.BroadcastReceiver
34 | -keep public class * extends android.view.View {*;}
35 | -keep public class * extends android.widget.BaseAdapter {*;}
36 | -keep public class liubaoyua.customtext.HookMethod{*;}
37 | -keep public class liubaoyua.customtext.entity.CustomText{*;}
38 | -keep public class liubaoyua.customtext.HookMethod{*;}
39 |
40 | -keepattributes *Annotation*
41 | -keepattributes Signature
42 | -keepattributes EnclosingMethod
43 |
44 | -dontwarn android.support.v4.**
45 | #忽略picasso库的警告
46 | -dontwarn com.squareup.picasso.**
47 | #忽略拼音库的警告
48 | -dontwarn net.soureceforge.pinyin4j.**
49 | -dontwarn demo.**
50 | -keep class net.sourceforge.pinyin4j.** { *;}
51 | -keep class demo.** { *;}
52 |
53 |
54 | -keepclassmembers class liubaoyua.customtext.utils.Common {
55 | public static final ;
56 | }
57 |
58 |
59 | -keepclassmembers class **.R$* {
60 | public static ;
61 | }
62 | -keepclasseswithmembernames class * {
63 | native ;
64 | }
65 |
66 |
67 |
68 | -keepclasseswithmembers class * {
69 | public (android.content.Context, android.util.AttributeSet);
70 | }
71 |
72 | -keepclasseswithmembers class * {
73 | public (android.content.Context, android.util.AttributeSet, int);
74 | }
75 |
76 | -keepclassmembers class * extends android.app.Activity {
77 | public void *(android.view.View);
78 | }
79 |
80 |
81 | -keepclassmembers enum * {
82 | public static **[] values();
83 | public static ** valueOf(java.lang.String);
84 | }
85 |
86 | #eventbus的相关函数
87 | -keepclassmembers class ** {
88 | public void onEvent*(**);
89 | }
90 |
91 |
92 | -keep class * implements android.os.Parcelable {
93 | public static final android.os.Parcelable$Creator *;
94 | }
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | #-ignorewarnings
112 | ##
113 | #-optimizationpasses 5
114 | #-dontusemixedcaseclassnames
115 | #-dontskipnonpubliclibraryclasses
116 | #-dontpreverify
117 | #-verbose
118 | #-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
119 | ##第三方的库声明
120 | ##-libraryjars libs/commons-io-2.4.jar
121 | ##-libraryjars libs/eventbus-2.4.0.jar
122 | ##-libraryjars libs/pinyin4j-2.5.0.jar
123 | ##-libraryjars libs/greendao-1.3.7.jar
124 | ##-libraryjars libs/nineoldandroids-2.4.0.jar
125 | ##-libraryjars libs/picasso-2.5.2.jar
126 | ##-libraryjars libs/systembartint-1.0.4.jar
127 | ##四大组件排除 自定义的view排除(因为xml中使用的是hardcode)
128 | #-keep public class * extends android.support.v4.**
129 | #-keep public class * extends android.app.Fragment
130 | #-keep public class * extends android.app.Activity
131 | #-keep public class * extends android.app.Application {*;}
132 | #-keep public class * extends android.app.Service
133 | #-keep public class * extends android.content.BroadcastReceiver
134 | #-keep public class * extends android.view.View {*;}
135 | #-keep public class * extends android.widget.BaseAdapter {*;}
136 | #
137 | #-keepattributes *Annotation*
138 | #-keepattributes Signature
139 | #-keepattributes EnclosingMethod
140 | #
141 | #-dontwarn android.support.v4.**
142 | ##忽略picasso库的警告
143 | ##-dontwarn com.squareup.picasso.**
144 | ##忽略拼音库的警告
145 | #-dontwarn net.soureceforge.pinyin4j.**
146 | ##-dontwarn demo.**
147 | #-keep class net.sourceforge.pinyin4j.** { *;}
148 | ##-keep class demo.** { *;}
149 | #
150 | ##保留greendao生成的数据库操作
151 | ##-keep class com.doloop.www.myappmgr.material.dao.*$Properties {
152 | ## public static ;
153 | ##}
154 | ##
155 | ##-keepclassmembers class liubaoyua.customtext.utils.** {
156 | ## public static final ;
157 | ##}
158 | #
159 | ##
160 | ##-keepclassmembers class **.R$* {
161 | ## public static ;
162 | ##}
163 | ##-keepclasseswithmembernames class * {
164 | ## native ;
165 | ##}
166 | ##
167 | ##-keepclasseswithmembers class * {
168 | ## public (android.content.Context, android.util.AttributeSet);
169 | ##}
170 | ##
171 | ##-keepclasseswithmembers class * {
172 | ## public (android.content.Context, android.util.AttributeSet, int);
173 | ##}
174 | #
175 | ##-keepclassmembers class * extends android.app.Activity {
176 | ## public void *(android.view.View);
177 | ##}
178 | ##eventbus的相关函数
179 | ##-keepclassmembers class ** {
180 | ## public void onEvent*(**);
181 | ##}
182 | ##
183 | ##-keepclassmembers enum * {
184 | ## public static **[] values();
185 | ## public static ** valueOf(java.lang.String);
186 | ##}
187 | ##
188 | ##-keep class * implements android.os.Parcelable {
189 | ## public static final android.os.Parcelable$Creator *;
190 | ##}
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rHK/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 文字自定義
4 | 打開
5 | 關閉
6 | 所有程式
7 | 最近程式
8 | 發現錯誤,即將退出。錯誤資訊:
9 | 成功
10 | 撤銷
11 | 清空
12 | 程式名(或首字母)、包名等等
13 | 剪貼簿為空
14 | 是否啟用開關?
15 |
16 | 來包辣條?
17 | 修改尚未儲存
18 | 是否現在儲存?
19 | 不儲存
20 | 儲存
21 | 輸入備份名
22 | 選擇要還原的備份
23 | 正在讀取
24 |
25 | - 前排加一樓
26 | - 複製本樓
27 | - 刪除本樓
28 | - 剪下本樓
29 | - 貼上本樓
30 | - 後排加一樓
31 |
32 |
33 | 資料夾不存在: %s
34 | 是否刪除原來的設定並導入選擇的備份?
35 | 設定檔案已經備份到資料夾: %s
36 | 備份失敗: %s
37 | 還原失敗: %s
38 | 還原成功,重啟程式吧~
39 | 沒有找到備份
40 | 隨意輸入
41 |
42 |
43 | 搜尋
44 |
45 | 首頁
46 | 關於
47 | 還原
48 | 備份
49 | 設定
50 | 退出
51 | 開關
52 |
53 | 增加十樓
54 | 清除空行
55 | 重啟程式
56 | 程式資訊
57 | 市場連結
58 | 清除所有
59 |
60 |
61 | 操作
62 | 清空
63 | 原文字
64 | 新文字
65 | 介是一個可以自定義替換文字的模組by liubaoyua from Xposed框架吧
66 | 設定
67 | 刪除
68 |
69 |
70 | 全局設定
71 | 模組開關
72 | 模組已啟用
73 | 模組已禁用
74 | 深度替換
75 | 將替換更多類型的字符(如果導致圖片不正確,請取消這個選項)
76 | 自定義資訊
77 | 模組可用
78 | 修改模組可用時在主界面上顯示的資訊
79 | 手動檢查更新
80 |
81 | 關於模組
82 | 文字自定義
83 | 作者: liubaoyua. 我只能說,作者是個死宅(笑),寫個代碼都能拖那麼久,微博點這裡。
84 | 模組功能
85 | 本模組可以幫助您修改程式中顯示的文字,比如:程式名字、運營商標籤等手機上顯示的文字。使用前確保安裝了 Xposed 框架。更多使用方法請戳這裡。
86 | 使用注意
87 | 本程式是無聊之作,作者不對你的使用負責,也不承擔任何損失和風險。如有不爽,家無水錶,不收快遞,請勿跨省,謝謝合作。
88 |
89 | 喜歡本程式?
90 | 如果覺得本程式不錯的話,歡迎到程式商店給個好評哈
91 | 建議回饋
92 | 信箱:liubaoyua@gmail.com
93 | \n\n百度貼吧:歡迎在xposed框架吧討論。
94 | 或者請艾特我 @liubaoyua
95 | \n\n酷市場評論區:本人常駐酷安,歡迎在評論區
96 | 評論、回饋、或調戲 @liubaoyua
97 | 感謝幫助
98 |
99 | \n tommy990607/提供 Html 代碼支援
100 | \n XXXXL/icon
101 | \n
102 | \n david082321/繁體中文(臺灣)
103 | \n Nicolas Woelker/Deutsch-Übersetzung
104 | \n dvaleron/русский перевод
105 | \n Ravhi Rizaldi/Bahasa Indonesia
106 | \n
107 | \n mitchtech/XposedGroot
108 | \n GermainZ/Hodor
109 | \n rovo89/xposed & Appsettings
110 | \n drakeet/material-design-settings
111 |
112 | 全局替換
113 | 已啟用程式
114 | 編輯模式
115 |
116 | 更新日誌:
117 | \n 增加一个正则表达式的开关(这就是为何无法替换带有"+"等其他符号的原因。默认关闭了,有需要自行开启)
118 | \n 可以為單個應用導入導出配置文件
119 | \n UI 調整
120 | \n 修復一些 Bug..
121 | \n 中秋節快樂 ^_^
122 | \n
123 | \n 另:
124 | \n 本程式需要安裝Xposed 框架才能使用。代碼已在 github 開源。
125 | \n
126 | \n 免責聲明:
127 | \n 作者已經盡量測試,但仍然可能出現未知的問題,請使用者自行承擔風險,作者不對你的使用負責,也不承擔任何損失。如有不爽,家無水錶,不收快遞,請勿跨省,謝謝合作。
128 | \n
129 | \n 作者:liubaoyua
130 | \n 目前版本:
131 |
132 |
133 |
--------------------------------------------------------------------------------
/app/src/main/res/values-id/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Custom Text
5 | Buka
6 | Tutup
7 | Semua Aplikasi
8 | Aplikasi Terkini
9 | Kesalahan ditemukan. Mengeluarkan. Pesan Kesalahan:
10 | Sukses
11 | Kembali
12 | Kosongkan
13 | Nama aplikasi(Head Char),Nama paket,dll
14 | Papan klip Kosong
15 | Aktifkan switch?
16 |
17 | Apa yang harus dilakukan?
18 | Modifikasi belum disimpan
19 | Simpan sekarang?
20 | Tidak disimpan
21 | Simpan
22 | Masukan nama pencadangan
23 | Pilih Sebuah Pencadangan
24 | Menunggu
25 |
26 | - Menambah ke atas
27 | - Salin
28 | - Hapus
29 | - Pindah
30 | - Tempel
31 | - Menambah ke bawah
32 |
33 |
34 | Folder tidak ditemukan: %s
35 | Impor cadangan dan timpa semua pengaturan saat ini?
36 | Pengaturan diekspor ke folder: %s
37 | Pencadangan gagal: %s
38 | Impor gagal: %s
39 | Impor sukses; jalankan ulang untuk membuat efek.
40 |
41 |
42 |
43 | Cari
44 |
45 | BERANDA
46 | TENTANG
47 | KEMBALIKAN
48 | CADANGKAN
49 | PENGATURAN
50 | KELUAR
51 | PINDAH
52 |
53 | Tambahkan lebih banyak item
54 | Bersihkan kosong
55 | Jalankan ulang Aplikasi
56 | Info Aplikasi
57 | Tautan Market
58 | Kosongkan Semua
59 |
60 |
61 |
62 | Aksi
63 | Kosongkan
64 | Teks Asli
65 | Teks Baru
66 | Sebuah modul yang membantu Anda mengganti teks dengan teks yang Anda inginkan. Dikembangkan oleh liubaoyua.
67 | Pengaturan
68 | Hapus
69 |
70 |
71 |
72 | Pengaturan Global
73 | Pindah Modul
74 | Perpanjangan Pengganti
75 | Ganti lebih banyak jenis teks(jika suatu widget tidak tampil dengan benar, Anda dapat hapus tanda centang pilihan ini)
76 | Pesan ubahsuaian
77 | Ini Bekerja :)
78 | Ubah pesan yang menampilkan "Ini Bekerja:)"
79 | Periksa Pembaruan secara manual
80 |
81 | Tentang modul
82 | Custom Text
83 | Pemilik: liubaoyua. Klik untuk mengunjungi blog mikro saya
84 | Fungsi modul
85 | Ini membantu Anda mengganti teks seperti: ID, Nama App, Label Carrier, dll. Xposed dibutuhkan.
86 | Perhatian
87 | Hal ini dibuat hanya untuk bersenang-senang. Menggunakannya dengan resiko Anda sendiri. Saya tidak bertanggung jawab untuk apa yang Anda lakukan dengan itu.
88 |
89 | Menyukai Aplikasi ini?
90 | Jika anda menyukai Aplikasi ini, Tolong beri nilai di app market.
91 | Masukan
92 | Email:liubaoyua@gmail.com
93 | \n\nCoolApk Market: Masukan dan @liubaoyua disini saya akan melihatnya
94 | Terima kasih banyak
95 |
96 | Masukan sesuatu
97 | Tidak ada cadangan ditemukan
98 | Modul dinonaktifkan
99 | Module diaktifkan
100 | Penggantian Global
101 | Diaktifkan Apps
102 | Mode Edit
103 |
104 |
--------------------------------------------------------------------------------
/app/src/main/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Custom Text
5 | Öffnen
6 | Schließen
7 | Alle Apps
8 | Kürzlich bearbeitet
9 | Fehler gefunden. Beende. Fehlernachricht:
10 | Erfolgreich
11 | Rückgängig
12 | Leeren
13 | Appname, Packagename, etc
14 | Zwischenablage ist leer
15 | Schalter aktivieren?
16 |
17 | Was tun?
18 | Änderungen nicht gespeichert
19 | Jetzt speichern?
20 | Nicht speichern
21 | Speichern
22 | Backupname eingeben
23 | Backup wählen
24 | Lädt...
25 |
26 | - Oberhalb hinzufügen
27 | - Kopieren
28 | - Löschen
29 | - Ausschneiden
30 | - Einfügen
31 | - Unterhalb hinzufügen
32 |
33 |
34 | Ordner existiert nicht: %s
35 | Backup importieren und alle derzeitigen Einstellungen überschreiben?
36 | Einstellungen gespeichert in Ordner: %s
37 | Backup fehlgeschlagen: %s
38 | Importieren fehlgeschlagen: %s
39 | Importieren erfolgreich; App zum Übernehmen neustarten.
40 |
41 |
42 |
43 | Suchen
44 |
45 | HOME
46 | ÜBER
47 | WIEDERHERSTELLEN
48 | BACKUP
49 | EINSTELLUNGEN
50 | BEENDEN
51 | SCHALTER
52 |
53 | Felder hinzufügen
54 | Leere Felder löschen
55 | App starten
56 | App-Info
57 | Market-Link
58 | Alle Felder leeren
59 |
60 |
61 |
62 | Aktion
63 | Leeren
64 | Ursprünglicher Text
65 | Neuer Text
66 | Ein Module, das dir hilft, Text mit beliebigem anderen Text zu ersetzen. Programmiert von liubaoyua.
67 | Einstellungen
68 | Löschen
69 |
70 |
71 |
72 | Allgemeine Einstellungen
73 | Modul-Schalter
74 | Erweitertes Ersetzen
75 | Ersetzt mehr Texttypen (falls etwas falsch angezeigt wird, kannst du diese Option deaktivieren)
76 | Eigene Nachricht
77 | Es funktioniert :)
78 | Ändere die Nachricht, die zeigt, dass "Es funktioniert :)"
79 | Manuell auf Updates überprüfen
80 |
81 | Über das Modul
82 | Custom Text
83 | Autor: liubaoyua. Klicken, um meinen micro blog zu besuchen
84 | Funktion des Moduls
85 | Es hilft dir, Texte zu ersetzen wie: IDs, Appnamen, Mobilfunkbetreibername, etc. Xposed benötigt.
86 | Achtung
87 | Diese App ist nur zum Spaß. Benutzung erfolgt auf eigene Gefahr. Ich bin nicht verantwortlich für das, was du damit tust.
88 |
89 | Gefällt dir diese App?
90 | Falls dir diese App gefällt, bewerte sie doch im AppMarket.
91 | Feedback
92 | E-Mail: liubaoyua@gmail.com
93 | \n\nCoolApk Market: Hinterlasst dort ein Feedback mit @liubaoyua und ich werde es sehen
94 | Danke
95 |
96 | \n tommy990607/Quellcode
97 | \n XXXXL/icon
98 | \n
99 | \n Nicolas Woelker/Deutsche Übersetzung
100 | \n dvaleron/русский перевод
101 | \n Ravhi Rizaldi/Bahasa Indonesia
102 | \n
103 | \n mitchtech/XposedGroot
104 | \n GermainZ/Hodor
105 | \n rovo89/xposed & Appsettings
106 | \n drakeet/material-design-settings
107 |
108 | Gib etwas ein
109 | Keine Backups gefunden
110 | Modul ist deaktiviert
111 | Modul ist aktiviert
112 | Globale Ersatz
113 | Aktiviert Apps
114 | Edit-Modus
115 |
116 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/app/MyApplication.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.app;
2 |
3 | import android.app.Activity;
4 | import android.app.Application;
5 | import android.content.Intent;
6 | import android.os.Environment;
7 | import android.util.Log;
8 |
9 | import java.io.ByteArrayOutputStream;
10 | import java.io.File;
11 | import java.io.FileNotFoundException;
12 | import java.io.FileOutputStream;
13 | import java.io.FilenameFilter;
14 | import java.io.IOException;
15 | import java.io.PrintStream;
16 | import java.text.SimpleDateFormat;
17 | import java.util.ArrayList;
18 | import java.util.Date;
19 | import java.util.List;
20 | import java.util.Locale;
21 |
22 | import liubaoyua.customtext.entity.AppInfo;
23 | import liubaoyua.customtext.ui.AppListActivity;
24 | import liubaoyua.customtext.utils.Common;
25 | import liubaoyua.customtext.utils.DBManager;
26 | import liubaoyua.customtext.utils.PicassoTools;
27 |
28 | //import com.squareup.leakcanary.LeakCanary;
29 | //import com.squareup.leakcanary.RefWatcher;
30 |
31 | /**
32 | * Created by kazzy on 2015/7/14 0014.
33 | * debug test
34 | */
35 | public class MyApplication extends Application {
36 |
37 |
38 | private static final String LOG_NAME = "crash_log_" + getCurrentDateString() + ".txt";
39 | public static File prefsDir = new File(Environment.getDataDirectory() + "/data/" + Common.PACKAGE_NAME + "/shared_prefs");
40 | public static File backupDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + Common.BACKUP_DIR);
41 | private static MyApplication application;
42 | private ArrayList list = new ArrayList<>();
43 |
44 | private Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
45 |
46 | @Override
47 | public void uncaughtException(Thread thread, Throwable ex) {
48 | writeErrorLog(ex);
49 | Intent intent = new Intent(getApplicationContext(),
50 | AppListActivity.class);
51 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
52 | startActivity(intent);
53 | exit();
54 | }
55 | };
56 | private List allList = new ArrayList<>();
57 |
58 | /**
59 | * 获取当前日期
60 | *
61 | * @return
62 | */
63 | private static String getCurrentDateString() {
64 | String result = null;
65 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH.mm.ss",
66 | Locale.getDefault());
67 | Date nowDate = new Date();
68 | result = sdf.format(nowDate);
69 | return result;
70 | }
71 |
72 | public static MyApplication getInstance() {
73 | return application;
74 | }
75 |
76 | @Override
77 | public void onCreate() {
78 | super.onCreate();
79 | if (Common.CRASH_LOG) {
80 | Thread.setDefaultUncaughtExceptionHandler(handler);
81 | } else {
82 | clearCrashLog();
83 | }
84 | application = this;
85 | PicassoTools.init(getApplicationContext());
86 |
87 | }
88 |
89 | /**
90 | * 打印错误日志
91 | */
92 | protected void writeErrorLog(Throwable ex) {
93 | String info = null;
94 | ByteArrayOutputStream baos = null;
95 | PrintStream printStream = null;
96 | try {
97 | baos = new ByteArrayOutputStream();
98 | printStream = new PrintStream(baos);
99 | ex.printStackTrace(printStream);
100 | byte[] data = baos.toByteArray();
101 | info = new String(data);
102 | data = null;
103 | } catch (Exception e) {
104 | e.printStackTrace();
105 | } finally {
106 | try {
107 | if (printStream != null) {
108 | printStream.close();
109 | }
110 | if (baos != null) {
111 | baos.close();
112 | }
113 | } catch (Exception e) {
114 | e.printStackTrace();
115 | }
116 | }
117 | Log.d("example", "崩溃信息\n" + info);
118 | File dir = new File(AppHelper.EXTERNAL_DIR);
119 | if (!dir.exists()) {
120 | dir.mkdirs();
121 | }
122 | File file = new File(dir, LOG_NAME);
123 | try {
124 | FileOutputStream fileOutputStream = new FileOutputStream(file, true);
125 | fileOutputStream.write(info.getBytes());
126 | fileOutputStream.close();
127 | } catch (FileNotFoundException e) {
128 | e.printStackTrace();
129 | } catch (IOException e) {
130 | e.printStackTrace();
131 | }
132 |
133 | }
134 |
135 | /**
136 | * Activity关闭时,删除Activity列表中的Activity对象
137 | */
138 | public void removeActivity(Activity a) {
139 | list.remove(a);
140 | }
141 |
142 | /**
143 | * 向Activity列表中添加Activity对象
144 | */
145 | public void addActivity(Activity a) {
146 | list.add(a);
147 | }
148 |
149 | /**
150 | * 关闭Activity列表中的所有Activity
151 | */
152 | public void exit() {
153 | for (Activity activity : list) {
154 | if (null != activity) {
155 | activity.finish();
156 | }
157 | }
158 | // 杀死该应用进程
159 | android.os.Process.killProcess(android.os.Process.myPid());
160 | }
161 |
162 | @Override
163 | public void onTerminate() {
164 | PicassoTools.destroy();
165 | DBManager.getInstance(getApplicationContext()).close();
166 | super.onTerminate();
167 | System.exit(0);
168 | }
169 |
170 | @Override
171 | public void onLowMemory() {
172 | super.onLowMemory();
173 | PicassoTools.clearCache();
174 | }
175 |
176 | @Override
177 | public void onTrimMemory(int level) {
178 | super.onTrimMemory(level);
179 | PicassoTools.clearCache();
180 | }
181 |
182 | protected List getAllList() {
183 | return allList;
184 | }
185 |
186 | protected void setAllList(List allList) {
187 | this.allList = allList;
188 | }
189 |
190 |
191 | private void clearCrashLog() {
192 | final String prefix = "crash_log";
193 | final File file = new File(AppHelper.EXTERNAL_DIR);
194 | if (!file.exists() || !file.isDirectory()) {
195 | return;
196 | }
197 |
198 | String[] logList = file.list(new FilenameFilter() {
199 | @Override
200 | public boolean accept(File dir, String filename) {
201 | return filename.startsWith(prefix) && (new File(dir, filename).isFile());
202 | }
203 | });
204 |
205 | for (String log : logList) {
206 | new File(file, log).delete();
207 | }
208 | }
209 |
210 | }
211 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 文本自定义
5 | 打开
6 | 关闭
7 | 所有应用
8 | 最近应用
9 | 发现错误,即将退出。错误信息:
10 | 成功
11 | 失败
12 | 撤销
13 | 清空
14 | 应用名(或首字母)、包名等等
15 | 剪切板为空
16 | 是否启用开关?
17 | 全局替换
18 | 已启用应用
19 |
20 | 来包辣条?
21 | 修改尚未保存
22 | 是否现在保存?
23 | 不保存
24 | 保存
25 | 输入备份名
26 | 选择要还原的备份
27 | 正在读取
28 |
29 | - 前排加一楼
30 | - 复制本楼
31 | - 删除本楼
32 | - 剪切本楼
33 | - 粘贴本楼
34 | - 后排加一楼
35 |
36 |
37 | 文件夹不存在: %s
38 | 是否删除原来的设置并导入选择的备份?
39 | 设置文件已经备份到文件夹: %s
40 | 备份失败: %s
41 | 还原失败: %s
42 | 还原成功,重启应用吧~
43 | 没有找到备份
44 | 随意输入
45 |
46 |
47 |
48 | 搜索
49 |
50 | 主页
51 | 刷新
52 | 关于
53 | 还原
54 | 备份
55 | 设置
56 | 捐赠
57 | 退出
58 | 开关
59 |
60 | 更多
61 | 增加十楼
62 | 清除空行
63 | 重启应用
64 | 应用信息
65 | 市场链接
66 | 清除所有
67 |
68 |
69 |
70 | 操作
71 | 清空
72 | 原文本
73 | 新文本
74 | 介是一个可以自定义替换文字的模块 by liubaoyua from Xposed框架吧
75 | 设置
76 | 删除
77 |
78 |
79 |
80 | 全局设置
81 | 模块开关
82 | 模块已启用
83 | 模块已禁用
84 | 深度替换
85 | 将替换更多类型的字符(启用可能导致某些文本或图片显示不正确)
86 | 正则表达式
87 | 调试模式
88 | 替换默认支持正则表达式(如果出现)
89 | 自定义信息
90 | 模块可用
91 | 修改模块可用时在主界面上显示的信息
92 | 手动检查更新
93 |
94 | 关于模块
95 | 文本自定义
96 | 作者: liubaoyua. 我只能说,作者是个死宅(笑),写个代码都能拖那么久,微博点这里。
97 | 模块功能
98 | 本模块可以帮助您修改应用中显示的文本,比如:应用名字、运营商标签 等手机上显示的文字。使用前确保安装了 Xposed 框架。
99 | 使用注意
100 | 本应用是无聊之作,作者不对你的使用负责,也不承担任何损失和风险。如有不爽,家无水表,不收快递,请勿跨省,谢谢合作。
101 |
102 | 喜欢本应用?
103 | 如果觉得本应用不错的话,欢迎到应用商店给个好评哈
104 | 建议反馈
105 | 邮箱:liubaoyua@gmail.com
106 | \n\n百度贴吧:欢迎在xposed框架吧讨论。
107 | 或者请艾特我 @liubaoyua
108 | \n\n酷市场评论区:本人常驻酷安,欢迎在评论区
109 | 评论、反馈、或调戏 @liubaoyua
110 | 感谢帮助
111 | 编辑模式
112 | 选择图片
113 |
114 | - 选择图片
115 | - 默认图片
116 |
117 |
118 | 导入导出
119 | 更多设置
120 | 可以将当前的配置文件导出分享给别人,也可以导入别人分享的配置文件。
121 | 导出
122 | 导入
123 | 导入成功,请重启应用
124 | 导入失败 :
125 | 导入失败 : 文件不存在或无法读取或非 xml 配置文件
126 | 以下选项设置会覆盖全局设置
127 | 通过文件分享
128 | 通过Json分享
129 | 支付宝
130 | 贝宝
131 | 微信
132 | 将当前的配置内容导出 Json 字符串进行分享,或导入别人的导出的 Json 字符串进行配置覆盖
133 | 导入 Json 数据
134 | 将会覆盖当前的配置
135 | 已经复制到剪贴板
136 | 请从相册选取二维码
137 | 如果喜欢这个作品,请支持我
138 |
139 |
140 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 文字自定義
5 | 打開
6 | 關閉
7 | 所有程式
8 | 最近程式
9 | 發現錯誤,即將退出。錯誤資訊:
10 | 成功
11 | 失敗
12 | 撤銷
13 | 清空
14 | 程式名(或首字母)、包名等等
15 | 剪貼簿為空
16 | 是否啟用開關?
17 | 全局替換
18 | 已啟用程式
19 |
20 | 來包辣條?
21 | 修改尚未儲存
22 | 是否現在儲存?
23 | 不儲存
24 | 儲存
25 | 輸入備份名
26 | 選擇要還原的備份
27 | 正在讀取
28 |
29 | - 前排加一樓
30 | - 複製本樓
31 | - 刪除本樓
32 | - 剪下本樓
33 | - 貼上本樓
34 | - 後排加一樓
35 |
36 |
37 | 資料夾不存在: %s
38 | 是否刪除原來的設定並導入選擇的備份?
39 | 設定檔案已經備份到資料夾: %s
40 | 備份失敗: %s
41 | 還原失敗: %s
42 | 還原成功,重啟程式吧~
43 | 沒有找到備份
44 | 隨意輸入
45 |
46 |
47 |
48 | 搜尋
49 |
50 | 首頁
51 | 更新
52 | 關於
53 | 還原
54 | 備份
55 | 設定
56 | 捐贈
57 | 退出
58 | 開關
59 |
60 | 更多
61 | 增加十樓
62 | 清除空行
63 | 重啟程式
64 | 程式資訊
65 | 市場連結
66 | 清除所有
67 |
68 |
69 |
70 | 操作
71 | 清空
72 | 原文字
73 | 新文字
74 | 介是一個可以自定義替換文字的模組by liubaoyua from Xposed框架吧
75 | 設定
76 | 刪除
77 |
78 |
79 |
80 | 全局設定
81 | 模組開關
82 | 模組已啟用
83 | 模組已禁用
84 | 深度替換
85 | 將替換更多類型的字符(如果導致圖片不正確,請取消這個選項)
86 | 正規表示式
87 | 調適模式
88 | 替換預設支援正規表示式(如果出現)
89 | 自定義資訊
90 | 模組可用
91 | 修改模組可用時在主界面上顯示的資訊
92 | 手動檢查更新
93 |
94 | 關於模組
95 | 文字自定義
96 | 作者: liubaoyua. 我只能說,作者是個死宅(笑),寫個代碼都能拖那麼久,微博點這裡。
97 | 模組功能
98 | 本模組可以幫助您修改程式中顯示的文字,比如:程式名字、運營商標籤等手機上顯示的文字。使用前確保安裝了 Xposed 框架。
99 | 使用注意
100 | 本程式是無聊之作,作者不對你的使用負責,也不承擔任何損失和風險。如有不爽,家無水錶,不收快遞,請勿跨省,謝謝合作。
101 |
102 | 喜歡本程式?
103 | 如果覺得本程式不錯的話,歡迎到程式商店給個好評哈
104 | 建議回饋
105 | 信箱:liubaoyua@gmail.com
106 | \n\n百度貼吧:歡迎在xposed框架吧討論。
107 | 或者請艾特我 @liubaoyua
108 | \n\n酷市場評論區:本人常駐酷安,歡迎在評論區
109 | 評論、回饋、或調戲 @liubaoyua
110 | 感謝幫助
111 | 編輯模式
112 | 選擇圖片
113 |
114 | - 選擇圖片
115 | - 預設圖片
116 |
117 |
118 | 匯入匯出
119 | 更多設定
120 | 可以將目前的配置文件匯出分享給別人,也可以匯入別人分享的配置文件。
121 | 匯出
122 | 匯入
123 | 匯入成功,請重啟程式
124 | 匯入失敗 :
125 | 匯入失敗: 文件不存在或無法讀取或非 xml 配置文件
126 | 以下選項設定會覆蓋全局設定
127 | 透過文件分享
128 | 透過Json分享
129 | 支付寶
130 | PayPal
131 | 微信
132 | 將目前的配置內容匯出 Json 字符串進行分享,或匯入別人的匯出的 Json 字符串進行配置覆蓋
133 | 匯入 Json 數據
134 | 將會覆蓋目前的配置
135 | 已經複製到剪貼簿
136 | 請從相冊選取二維碼
137 | 如果喜歡這個作品,請支持我
138 |
139 |
140 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Custom Text
5 | Open
6 | Close
7 | All apps
8 | Recent apps
9 | Error found. Exiting. Error message:
10 | Success
11 | Undo
12 | Clear
13 | App Name(Head Char),package Name,etc
14 | ClickBoard is empty
15 | Enable the switch?
16 |
17 |
18 | What to do?
19 | Modify hasn\'t been saved
20 | Save now?
21 | Not Save
22 | Save
23 | Input Backup Name
24 | Select A Backup
25 | Loading
26 |
27 | - Add upstairs
28 | - Copy
29 | - Delete
30 | - Cut
31 | - Paste
32 | - Add downstairs
33 |
34 |
35 | Folder does not exist: %s
36 | Import backup and overwrite all current settings?
37 | Settings exported to folder: %s
38 | Backup failed: %s
39 | Import failed: %s
40 | Import successful; relaunch to make effect.
41 |
42 |
43 |
44 | Search
45 |
46 | HOME
47 | ABOUT
48 | RESTORE
49 | BACKUP
50 | SETTING
51 | EXIT
52 | SWITCH
53 |
54 | Add More Item
55 | Clear Empty
56 | Relaunch App
57 | Edit Mode
58 | App Info
59 | Market Link
60 | Clear All
61 |
62 |
63 |
64 | Action
65 | Clear
66 | Original Text
67 | New Text
68 | A module which helps you replace text with any text you want. Developed by liubaoyua.
69 | Setting
70 | Delete
71 |
72 |
73 |
74 | Global Settings
75 | Module Switch
76 | Extended Replacement
77 | Replace more type of text(if something widget is incorrectly showed, you can uncheck this option)
78 | Custom Message
79 | It works :)
80 | Change the message that show "It works:)"
81 | Check Update Manually
82 |
83 | About Module
84 | Custom Text
85 | Author: liubaoyua. Click to visit my micro blog
86 | Module Function
87 | It helps you replace texts such as: IDs, App names, carrier label, etc. Xposed is required.
88 | Attention
89 | It is made just for fun. Use it at your own risk. I am not responsible for what you do with it.
90 |
91 | Like this app?
92 | If you like this app, please rate it in app market.
93 | Feedback
94 | Email:liubaoyua@gmail.com
95 | \n\nCoolApk Market: feedback and @liubaoyua here and i will see
96 | Thanks
97 |
98 | \n tommy990607/source code
99 | \n XXXXL/icon
100 | \n
101 | \n david082321/繁體中文(臺灣)
102 | \n Nicolas Woelker/Deutsch-Übersetzung
103 | \n dvaleron/русский перевод
104 | \n Ravhi Rizaldi/Bahasa Indonesia
105 | \n
106 | \n mitchtech/XposedGroot
107 | \n GermainZ/Hodor
108 | \n rovo89/xposed & Appsettings
109 | \n drakeet/material-design-settings
110 |
111 | Input Something
112 | No backups found
113 | Module is disabled
114 | Module is enabled
115 | Enabled Apps
116 | Global Replacement
117 | Regex Expression
118 | Use regex expression ( don\'t enable it if you don\'t know what it is
119 | Import failed:
120 | Import failed: file not found or isn\'t a xml file
121 | Import Successfully. You need to relaunch this app to reload new data.
122 | Select a pic
123 | More
124 | Refresh
125 | Import\/Export
126 | failed
127 | Export
128 | Setting below will override global setting
129 | Import
130 | You can share you pref files whit others or get pref files from other.
131 | More Settings
132 | Debug Mode
133 |
134 |
135 | - Select a pic
136 | - Default pic
137 |
138 | Paypal
139 | Wechat
140 | DONATE
141 | Convert current preferences to json string as to share with others, or import the exported json string to override current preference.
142 | Through file
143 | Through json
144 | Alipay
145 | Import with json
146 | Will override current preference.
147 | Copied to clip board.
148 | Please choose the qrcode from albums.
149 | If you like this module, please support me.
150 |
151 |
152 |
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/HookMethod.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.drawable.Drawable;
6 | import android.text.Html;
7 | import android.text.TextUtils;
8 | import android.widget.TextView;
9 |
10 | import org.json.JSONArray;
11 | import org.json.JSONException;
12 | import org.json.JSONObject;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.regex.Matcher;
17 | import java.util.regex.Pattern;
18 |
19 | import de.robv.android.xposed.IXposedHookLoadPackage;
20 | import de.robv.android.xposed.XC_MethodHook;
21 | import de.robv.android.xposed.XC_MethodReplacement;
22 | import de.robv.android.xposed.XSharedPreferences;
23 | import de.robv.android.xposed.XposedBridge;
24 | import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
25 | import liubaoyua.customtext.entity.CustomText;
26 | import liubaoyua.customtext.utils.Common;
27 | import liubaoyua.customtext.utils.XposedUtil;
28 |
29 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
30 |
31 |
32 | public class HookMethod implements IXposedHookLoadPackage {
33 |
34 | private XSharedPreferences prefs;
35 | private CustomText[] current;
36 | private CustomText[] shared;
37 | private CustomText[] global;
38 | private Html.ImageGetter imageGetter = new Html.ImageGetter() {
39 | public Drawable getDrawable(String source) {
40 | Drawable d = Drawable.createFromPath(source);
41 | d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
42 | return d;
43 | }
44 | };
45 |
46 | @Override
47 | public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
48 |
49 | prefs = new XSharedPreferences(Common.PACKAGE_NAME);
50 | prefs.makeWorldReadable();
51 | if (!prefs.getBoolean(Common.SETTING_MODULE_SWITCH, true)) {
52 | return;
53 | }
54 |
55 | XSharedPreferences mPrefs = new XSharedPreferences(Common.PACKAGE_NAME, lpparam.packageName);
56 | mPrefs.makeWorldReadable();
57 | XSharedPreferences sPrefs = new XSharedPreferences(Common.PACKAGE_NAME, Common.SHARING_SETTING_PACKAGE_NAME);
58 | sPrefs.makeWorldReadable();
59 |
60 | final boolean isInDebugMode = prefs.getBoolean(Common.SETTING_XPOSED_DEBUG_MODE, Common.XPOSED_DEBUG);
61 |
62 | final boolean shouldHackMoreType;
63 | if (mPrefs.contains(Common.SETTING_MORE_TYPE)) {
64 | shouldHackMoreType = mPrefs.getBoolean(Common.SETTING_MORE_TYPE, false);
65 | } else {
66 | shouldHackMoreType = prefs.getBoolean(Common.SETTING_MORE_TYPE, false);
67 | }
68 |
69 | final boolean shouldUseRegex;
70 | if (mPrefs.contains(Common.SETTING_MORE_TYPE)) {
71 | shouldUseRegex = mPrefs.getBoolean(Common.SETTING_USE_REGEX, false);
72 | } else {
73 | shouldUseRegex = prefs.getBoolean(Common.SETTING_USE_REGEX, false);
74 | }
75 |
76 | final boolean isGlobalHackEnabled = prefs.getBoolean(Common.PREFS, false);
77 | final boolean isCurrentHackEnabled = prefs.getBoolean(lpparam.packageName, false);
78 | final boolean isInThisApp = lpparam.packageName.equals(Common.PACKAGE_NAME);
79 | final boolean isSharedHackEnabled = prefs.getBoolean(Common.SHARING_SETTING_PACKAGE_NAME, false);
80 |
81 | final String thisAppName = prefs.getString(Common.PACKAGE_NAME_ARG, Common.DEFAULT_APP_NAME);
82 |
83 | if (isInDebugMode) {
84 | JSONObject object = new JSONObject();
85 | XposedBridge.log("Custom Text Debugging...");
86 | object.put("packageName", lpparam.packageName)
87 | .put("isGlobalHackEnabled", isGlobalHackEnabled)
88 | .put("isCurrentHackEnabled", isCurrentHackEnabled)
89 | .put("isSharedHackEnabled", isSharedHackEnabled)
90 | .put("shouldUseRegex", shouldUseRegex)
91 | .put("shouldHackMoreType", shouldHackMoreType);
92 | try {
93 | XposedBridge.log(object.toString(4));
94 | } catch (Throwable e) {
95 | }
96 | }
97 |
98 | XC_MethodHook textMethodHook;
99 | if (isInThisApp) {
100 | final String hackSucceedMessage;
101 | String temp = prefs.getString(Common.SETTING_HACK_SUCCEED_MESSAGE, Common.DEFAULT_MESSAGE);
102 |
103 | if (temp.equals("")) {
104 | hackSucceedMessage = prefs.getString(Common.MESSAGE, Common.DEFAULT_MESSAGE);
105 | } else {
106 | hackSucceedMessage = temp;
107 | }
108 |
109 | textMethodHook = new XC_MethodHook() {
110 | @Override
111 | protected void beforeHookedMethod(MethodHookParam methodHookParam) throws Throwable {
112 | if (methodHookParam.args[0] instanceof String) {
113 | String abc = (String) methodHookParam.args[0];
114 | abc = abc.replaceAll(thisAppName, hackSucceedMessage);
115 | methodHookParam.args[0] = abc;
116 | }
117 | }
118 | };
119 | findAndHookMethod(XposedUtil.class.getName(), lpparam.classLoader,
120 | "isXposedEnable", XC_MethodReplacement.returnConstant(true));
121 | } else {
122 | if (!isGlobalHackEnabled && !isCurrentHackEnabled)
123 | return;
124 |
125 | current = loadCustomTextArrayFromPrefs(mPrefs, isCurrentHackEnabled, shouldUseRegex);
126 | shared = loadCustomTextArrayFromPrefs(sPrefs, isSharedHackEnabled && isCurrentHackEnabled, shouldUseRegex);
127 | global = loadCustomTextArrayFromPrefs(prefs, isGlobalHackEnabled, shouldUseRegex);
128 |
129 | if (isInDebugMode) {
130 | try {
131 | JSONObject object = new JSONObject();
132 | XposedBridge.log("Custom Text pending replacement...");
133 | object.put("packageName", lpparam.packageName)
134 | .put("current", toJSonArray(current))
135 | .put("shared", toJSonArray(shared))
136 | .put("global", toJSonArray(global));
137 |
138 | XposedBridge.log(object.toString(4));
139 | } catch (Throwable e) {
140 | }
141 | }
142 |
143 | textMethodHook = new XC_MethodHook() {
144 | @Override
145 | protected void beforeHookedMethod(MethodHookParam methodHookParam) throws Throwable {
146 | String source;
147 | if (shouldHackMoreType && methodHookParam.args[0] != null) {
148 | source = methodHookParam.args[0].toString();
149 | } else if (!shouldHackMoreType && methodHookParam.args[0] instanceof String) {
150 | source = (String) methodHookParam.args[0];
151 | } else {
152 | return;
153 | }
154 |
155 | Result result = new Result(source, false);
156 | if (isCurrentHackEnabled) {
157 | replaceAllFromArray(current, result, shouldUseRegex);
158 | }
159 | if (isSharedHackEnabled && isCurrentHackEnabled) {
160 | replaceAllFromArray(shared, result, shouldUseRegex);
161 | }
162 | if (isGlobalHackEnabled) {
163 | replaceAllFromArray(global, result, shouldUseRegex);
164 | }
165 |
166 | if (result.isChange()) {
167 | // changed... so we reset the arg[0]...
168 | setTextFromHtml(result.getText(), methodHookParam, 0);
169 | if (isInDebugMode) {
170 | try {
171 | JSONObject o = new JSONObject();
172 | o.put("package", lpparam.packageName)
173 | .put("source", source)
174 | .put("after", result.getText());
175 | XposedBridge.log("Custom Text... Replace text in Package: \n" + o.toString(4));
176 | } catch (Throwable e) {
177 | //
178 | }
179 | }
180 | }
181 | }
182 | };
183 | }
184 |
185 | findAndHookMethod(TextView.class, "setText", CharSequence.class,
186 | TextView.BufferType.class, boolean.class, int.class, textMethodHook);
187 | findAndHookMethod(TextView.class, "setHint", CharSequence.class, textMethodHook);
188 | try {
189 | findAndHookMethod(Canvas.class, "drawText", String.class,
190 | float.class, float.class, Paint.class, textMethodHook);
191 | } catch (Throwable e) {
192 | //ignore...
193 | }
194 |
195 | if (isInDebugMode) {
196 | XposedBridge.log("Custom Text..." + thisAppName + ": findAndHookDone");
197 | }
198 | }
199 |
200 | private void setTextFromHtml(String html, XC_MethodHook.MethodHookParam param, int n) {
201 | if (html.contains("<") && html.contains(">")) {
202 | CharSequence text = Html.fromHtml(html, imageGetter, null);
203 | if (param.thisObject instanceof TextView)
204 | param.args[n] = text;
205 | else
206 | param.args[n] = text.toString();
207 | } else
208 | param.args[n] = html;
209 | }
210 |
211 | public static void replaceAllFromArray(CustomText[] customTexts, Result result, boolean regex) {
212 | if (customTexts == null) {
213 | return;
214 | }
215 | for (CustomText customText : customTexts) {
216 | if (regex) {
217 | result = patternReplace(result, customText.getPattern(), customText.getNewText());
218 | } else {
219 | result = normalReplace(result, customText.getOriText(), customText.getNewText());
220 | }
221 | }
222 | }
223 |
224 | public static JSONArray toJSonArray(CustomText[] texts) throws JSONException {
225 | if (texts == null || texts.length == 0) {
226 | return null;
227 | }
228 | JSONArray array = new JSONArray();
229 | for (CustomText text : texts) {
230 | array.put(text.toJson());
231 | }
232 | return array;
233 | }
234 |
235 | public static CustomText[] loadCustomTextArrayFromPrefs(XSharedPreferences prefs, Boolean enabled, boolean shouldUseRegex) {
236 | if (!enabled) {
237 | return null;
238 | }
239 | List list = new ArrayList<>();
240 | final int num = (prefs.getInt(Common.MAX_PAGE_OLD, 0) + 1) * Common.DEFAULT_NUM;
241 | for (int i = 0; i < num; i++) {
242 | String oriString = prefs.getString(Common.ORI_TEXT_PREFIX + i, "");
243 | String newString = prefs.getString(Common.NEW_TEXT_PREFIX + i, "");
244 | if (!TextUtils.isEmpty(oriString)) {
245 | CustomText customText = new CustomText(oriString, newString);
246 | if (!shouldUseRegex) {
247 | list.add(customText);
248 | } else if (customText.createOriginPattern() != null) {
249 | list.add(customText);
250 | }
251 | }
252 | }
253 | return list.toArray(new CustomText[list.size()]);
254 | }
255 |
256 |
257 | public static Result patternReplace(Result origin, Pattern target, String replacement) {
258 | String text = origin.getText();
259 | Matcher matcher = target.matcher(text);
260 | StringBuffer buffer = null;
261 | boolean change = false;
262 | matcher.reset();
263 | while (matcher.find()) {
264 | if (buffer == null) {
265 | buffer = new StringBuffer(text.length());
266 | }
267 | matcher.appendReplacement(buffer, replacement);
268 | change = true;
269 | }
270 | if (change) {
271 | origin.setText(matcher.appendTail(buffer).toString());
272 | }
273 | return origin;
274 | }
275 |
276 | @SuppressWarnings("all")
277 | public static Result normalReplace(Result origin, CharSequence target, CharSequence replacement) {
278 | String text = origin.getText();
279 | String result = text.replace(target, replacement);
280 | // if text not change, the method "String.replace(target, replacement)" will return text itself.
281 | // so just check text != result is ok...
282 | if (text != result) {
283 | origin.setText(result);
284 | }
285 | return origin;
286 | }
287 |
288 | /**
289 | * Created by liubaoyua on 2016/4/21.
290 | */
291 | static class Result {
292 | private boolean change;
293 | private String text;
294 |
295 | public Result(String text, boolean change) {
296 | this.text = text;
297 | this.change = change;
298 | }
299 |
300 | public boolean isChange() {
301 | return change;
302 | }
303 |
304 | public void setText(String text) {
305 | this.text = text;
306 | this.change = true;
307 | }
308 |
309 | public String getText() {
310 | return text;
311 | }
312 | }
313 | }
--------------------------------------------------------------------------------
/app/src/main/java/liubaoyua/customtext/adapters/TextRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package liubaoyua.customtext.adapters;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.os.Build;
7 | import android.support.design.widget.Snackbar;
8 | import android.support.v7.app.AlertDialog;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.text.Editable;
11 | import android.text.TextWatcher;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.Button;
16 | import android.widget.CheckBox;
17 | import android.widget.CompoundButton;
18 | import android.widget.EditText;
19 |
20 | import java.util.ArrayList;
21 |
22 | import liubaoyua.customtext.R;
23 | import liubaoyua.customtext.entity.CustomText;
24 |
25 | /**
26 | * Created by liubaoyua on 2015/6/19 0019.
27 | */
28 | public class TextRecyclerAdapter extends RecyclerView.Adapter {
29 |
30 |
31 | public boolean multiSelectMode = false;
32 | private Context mContext;
33 | private ArrayList data = new ArrayList<>();
34 | private boolean selectAll = false;
35 | private CustomText tempCT = new CustomText();
36 | private CustomText undo = new CustomText();
37 | private RecyclerView recyclerView;
38 |
39 | public TextRecyclerAdapter(Context mContext, ArrayList data, RecyclerView recyclerView) {
40 | this.mContext = mContext;
41 | setData(data);
42 | this.recyclerView = recyclerView;
43 | }
44 |
45 | @Override
46 | public TextRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
47 | View view = LayoutInflater.from(mContext).inflate(R.layout.list_item_card_text, parent, false);
48 | return new ViewHolder(view);
49 | }
50 |
51 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
52 | @Override
53 | public void onBindViewHolder(final TextRecyclerAdapter.ViewHolder holder, int position) {
54 | CustomText customText = data.get(position);
55 | holder.oriEditText.setText(customText.oriText);
56 | holder.newEditText.setText(customText.newText);
57 | if (multiSelectMode) {
58 | holder.checkBox.setVisibility(View.VISIBLE);
59 | holder.checkBox.setChecked(customText.isCheck);
60 | } else {
61 | holder.checkBox.setVisibility(View.INVISIBLE);
62 | }
63 |
64 | }
65 |
66 | public ArrayList getData() {
67 | return data;
68 | }
69 |
70 | public void setData(ArrayList data) {
71 | if (data == null) {
72 | return;
73 | }
74 | this.data = new ArrayList<>();
75 | for (int i = 0; i < data.size(); i++) {
76 | this.data.add(new CustomText(data.get(i)));
77 | }
78 | notifyDataSetChanged();
79 | }
80 |
81 | public void addData(ArrayList texts) {
82 | if (texts == null) {
83 | return;
84 | }
85 | removeEmptyData();
86 | int start = data.size();
87 | for (int i = 0; i < texts.size(); i++) {
88 | data.add(new CustomText(texts.get(i)));
89 | }
90 | notifyItemRangeInserted(start, texts.size());
91 | }
92 |
93 |
94 | public void removeEmptyData() {
95 | for (int i = 0; i < data.size(); i++) {
96 | CustomText customText = data.get(i);
97 | if (customText.oriText.equals("") && customText.newText.equals("")) {
98 | data.remove(i);
99 | i--;
100 | }
101 | }
102 | notifyDataSetChanged();
103 | }
104 | @Override
105 | public int getItemCount() {
106 | return data == null ? 0 : data.size();
107 |
108 | }
109 |
110 | public ArrayList getSelectedItem() {
111 | ArrayList list = new ArrayList<>();
112 | for (CustomText customText : data) {
113 | if (customText.isCheck) {
114 | list.add(new CustomText(customText));
115 | }
116 | }
117 | Snackbar.make(recyclerView, mContext.getString(android.R.string.copy) + " " +
118 | mContext.getString(R.string.succeed), Snackbar.LENGTH_LONG).show();
119 | return list;
120 | }
121 |
122 | public ArrayList cutSelectedItem() {
123 | ArrayList list = new ArrayList<>();
124 | for (int i = 0; i < data.size(); i++) {
125 | if (data.get(i).isCheck) {
126 | list.add(new CustomText(data.get(i)));
127 | data.remove(i);
128 | i--;
129 | }
130 | }
131 | notifyDataSetChanged();
132 | recyclerView.scrollToPosition(0);
133 | Snackbar.make(recyclerView, mContext.getString(android.R.string.cut) + " " +
134 | mContext.getString(R.string.succeed), Snackbar.LENGTH_LONG).show();
135 | return list;
136 | }
137 |
138 | public void deselectAllItem() {
139 | for (CustomText customText : data) {
140 | customText.isCheck = false;
141 | }
142 | notifyDataSetChanged();
143 | }
144 |
145 | public void pasteClipBoard(ArrayList clipboard) {
146 | for (int i = 0; i < clipboard.size(); i++) {
147 | data.add(i, new CustomText(clipboard.get(i)));
148 | }
149 | notifyItemRangeInserted(0, clipboard.size());
150 | recyclerView.scrollToPosition(0);
151 | Snackbar.make(recyclerView, mContext.getString(android.R.string.paste) + " " +
152 | mContext.getString(R.string.succeed), Snackbar.LENGTH_LONG).show();
153 | }
154 |
155 | public void selectAll() {
156 | if (!selectAll) {
157 | for (CustomText customText : data) {
158 | customText.isCheck = true;
159 | }
160 | selectAll = true;
161 | notifyDataSetChanged();
162 | } else {
163 | selectAll = false;
164 | deselectAllItem();
165 | }
166 | notifyDataSetChanged();
167 | }
168 |
169 | public void onClickView(View view, final ViewHolder viewHolder) {
170 | if (view.getId() == R.id.button_serial) {
171 | final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
172 | builder.setIcon(R.mipmap.ic_launcher);
173 | builder.setTitle("(" + viewHolder.getAdapterPosition() + ") " + mContext.getString(R.string.dialog_title));
174 | final String[] texts = mContext.getResources().getStringArray(R.array.dialog_item);
175 | builder.setItems(texts, new DialogInterface.OnClickListener() {
176 | @Override
177 | public void onClick(DialogInterface dialog, int which) {
178 | String succeed = mContext.getString(R.string.succeed);
179 | switch (which) {
180 | case 0: {//- 前排加一楼
181 | CustomText now = data.get(viewHolder.getAdapterPosition());
182 | if (viewHolder.getAdapterPosition() == 0) {
183 | data.add(viewHolder.getAdapterPosition(), new CustomText());
184 | } else {
185 | CustomText prev = data.get(viewHolder.getAdapterPosition() - 1);
186 | data.add(viewHolder.getAdapterPosition(), new CustomText());
187 | }
188 | notifyItemInserted(viewHolder.getAdapterPosition());
189 | Snackbar.make(recyclerView, texts[which] + " " + succeed, Snackbar.LENGTH_LONG)
190 | .show();
191 | break;
192 | }
193 | case 1: {//- 复制本楼
194 | tempCT = new CustomText(data.get(viewHolder.getAdapterPosition()));
195 | Snackbar.make(recyclerView, texts[which] + " " + succeed, Snackbar.LENGTH_LONG)
196 | .show();
197 | break;
198 | }
199 | case 2: {//- 删除本楼
200 | final int position = viewHolder.getAdapterPosition();
201 | undo = data.get(position);
202 | data.remove(position);
203 | notifyItemRemoved(position);
204 | Snackbar.make(recyclerView, texts[which] + " " + succeed, Snackbar.LENGTH_LONG)
205 | .setAction(mContext.getString(R.string.undo), new View.OnClickListener() {
206 | @Override
207 | public void onClick(View v) {
208 | data.add(position, undo);
209 | notifyItemInserted(position);
210 | }
211 | }).show();
212 | break;
213 | }
214 | case 3: {//- 剪切本楼
215 | final int position = viewHolder.getAdapterPosition();
216 | tempCT = new CustomText(data.get(viewHolder.getAdapterPosition()));
217 | undo = data.get(viewHolder.getAdapterPosition());
218 | data.remove(viewHolder.getAdapterPosition());
219 | notifyItemRemoved(viewHolder.getAdapterPosition());
220 | Snackbar.make(recyclerView, texts[which] + " " + succeed, Snackbar.LENGTH_LONG)
221 | .setAction(mContext.getString(R.string.undo), new View.OnClickListener() {
222 | @Override
223 | public void onClick(View v) {
224 | data.add(position, undo);
225 | notifyItemInserted(position);
226 | }
227 | }).show();
228 | break;
229 | }
230 | case 4: {//- 粘贴本楼
231 | final CustomText now = data.get(viewHolder.getAdapterPosition());
232 | if (tempCT.isEmpty()) {
233 | Snackbar.make(recyclerView, mContext.getString(R.string.clipboard_is_empty), Snackbar.LENGTH_LONG)
234 | .show();
235 | break;
236 | } else {
237 | undo = new CustomText(now);
238 | now.oriText = tempCT.oriText;
239 | now.newText = tempCT.newText;
240 | notifyItemChanged(viewHolder.getAdapterPosition());
241 | Snackbar.make(recyclerView, texts[which] + " " + succeed, Snackbar.LENGTH_LONG)
242 | .setAction(mContext.getString(R.string.undo), new View.OnClickListener() {
243 | @Override
244 | public void onClick(View v) {
245 | now.oriText = undo.oriText;
246 | now.newText = undo.newText;
247 | notifyItemChanged(viewHolder.getAdapterPosition());
248 | }
249 | }).show();
250 | break;
251 | }
252 | }
253 | case 5: {// - 后排加一楼
254 | CustomText now = data.get(viewHolder.getAdapterPosition());
255 | if (viewHolder.getAdapterPosition() == data.size() - 1) {
256 | data.add(viewHolder.getAdapterPosition() + 1, new CustomText());
257 | } else {
258 | CustomText next = data.get(viewHolder.getAdapterPosition() + 1);
259 | data.add(viewHolder.getAdapterPosition() + 1, new CustomText());
260 | }
261 | notifyItemInserted(viewHolder.getAdapterPosition() + 1);
262 | Snackbar.make(recyclerView, texts[which] + " " + succeed, Snackbar.LENGTH_LONG)
263 | .show();
264 | break;
265 | }
266 | }
267 | }
268 | }
269 |
270 | );
271 | builder.show();
272 | } else if (view.getId() == R.id.button_clear) {
273 | final CustomText customText = data.get(viewHolder.getAdapterPosition());
274 | undo = new CustomText(customText);
275 | customText.newText = "";
276 | customText.oriText = "";
277 | notifyItemChanged(viewHolder.getAdapterPosition());
278 | Snackbar.make(recyclerView, mContext.getString(R.string.clear) + " " +
279 | mContext.getString(R.string.succeed), Snackbar.LENGTH_LONG)
280 | .setAction(mContext.getString(R.string.undo), new View.OnClickListener() {
281 | @Override
282 | public void onClick(View v) {
283 | customText.oriText = undo.oriText;
284 | customText.newText = undo.newText;
285 | notifyItemChanged(viewHolder.getAdapterPosition());
286 | }
287 | }).show();
288 | }
289 | }
290 |
291 | public class ViewHolder extends RecyclerView.ViewHolder {
292 | public Button clearButton;
293 | public Button operateButton;
294 | public EditText oriEditText;
295 | public EditText newEditText;
296 | public CheckBox checkBox;
297 |
298 | public ViewHolder(final View view) {
299 | super(view);
300 | clearButton = (Button) view.findViewById(R.id.button_clear);
301 | operateButton = (Button) view.findViewById(R.id.button_serial);
302 | oriEditText = (EditText) view.findViewById(R.id.editText_original_text);
303 | newEditText = (EditText) view.findViewById(R.id.editText_new_text);
304 | checkBox = (CheckBox) view.findViewById(R.id.check_box);
305 | checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
306 | @Override
307 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
308 | data.get(getAdapterPosition()).isCheck = b;
309 | }
310 | });
311 | clearButton.setOnClickListener(new View.OnClickListener() {
312 | @Override
313 | public void onClick(View view) {
314 | onClickView(view, ViewHolder.this);
315 | }
316 | });
317 | oriEditText.addTextChangedListener(new TextWatcher() {
318 | @Override
319 | public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
320 |
321 | }
322 |
323 | @Override
324 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
325 |
326 | }
327 |
328 | @Override
329 | public void afterTextChanged(Editable editable) {
330 | CustomText customText = data.get(getAdapterPosition());
331 | customText.oriText = oriEditText.getText().toString();
332 | }
333 | });
334 | newEditText.addTextChangedListener(new TextWatcher() {
335 | @Override
336 | public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
337 |
338 | }
339 |
340 | @Override
341 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
342 |
343 | }
344 |
345 | @Override
346 | public void afterTextChanged(Editable editable) {
347 | CustomText customText = data.get(getAdapterPosition());
348 | customText.newText = newEditText.getText().toString();
349 | }
350 | });
351 | operateButton.setOnClickListener(new View.OnClickListener() {
352 | @Override
353 | public void onClick(View view) {
354 | onClickView(view, ViewHolder.this);
355 | }
356 | });
357 | }
358 | }
359 | }
360 |
--------------------------------------------------------------------------------