├── AndroidManifest.xml
├── README.md
├── assets
└── xposed_init
├── proguard-project.txt
├── res
├── drawable-hdpi
│ └── drag.9.png
├── drawable-mdpi
│ └── drag.9.png
├── drawable
│ ├── arrow.xml
│ ├── blue_progress.xml
│ ├── btn_delete.png
│ ├── drag.9.png
│ ├── green_progress.xml
│ ├── ic_launcher.png
│ └── red_progress.xml
├── layout-v14
│ └── chainkey.xml
├── layout
│ ├── arrow.xml
│ ├── chainitem.xml
│ ├── chainkey.xml
│ ├── chainlist.xml
│ ├── color_picker.xml
│ ├── editor.xml
│ ├── itneditor.xml
│ ├── keyeditor.xml
│ ├── main.xml
│ ├── simple.xml
│ └── test.xml
├── menu
│ └── main.xml
├── values
│ ├── other.xml
│ ├── strings_pbmc.xml
│ └── themes.xml
└── xml
│ └── settings.xml
└── src
├── com
└── android
│ └── vending
│ └── billing
│ └── IInAppBillingService.aidl
└── xeed
└── xposed
└── cbppmod
├── Action.java
├── Chain.java
├── Coded.java
├── InAppMgmt.java
├── Key.java
├── PBMain.java
├── PBSettings.java
├── prf
├── ColorPreference.java
├── FlagListPreference.java
└── ValueListPreference.java
├── ui
├── ActionDialog.java
├── ChainEditFragment.java
├── ChainListFragment.java
├── KeyTestFragment.java
└── PagerAdapter.java
└── viw
└── CustomListView.java
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
31 |
35 |
39 |
47 |
48 |
49 |
50 |
51 |
52 |
60 |
64 |
65 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Physical Buttom Music Control
2 | Xposed Framework module for Android 2.3-6.0, all info here: http://forum.xda-developers.com/xposed/modules/mod-physical-button-music-control-1-8-t2620777/
3 |
--------------------------------------------------------------------------------
/assets/xposed_init:
--------------------------------------------------------------------------------
1 | xeed.xposed.cbppmod.PhysicalButtonMod
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | -keep public class xeed.xposed.cbppmod.PhysicalButtonMod
2 |
3 | -keep public class xeed.xposed.cbppmod.PBMain
4 | {
5 | public static java.lang.String getActiveVerName();
6 | public static int getActiveVerCode();
7 | }
8 |
9 | -keep public class xeed.library.ui.BaseSettings
10 | {
11 | protected static int getActiveVer();
12 | }
13 |
14 | -keepattributes InnerClasses
15 |
16 | -libraryjars ../Libraries/XposedBridgeApi.jar
17 |
18 | -libraryjars ../ZZHacks/bin
--------------------------------------------------------------------------------
/res/drawable-hdpi/drag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XspeedPL/PhysicalButtonMod/c419bd313209548010e6d2ce57f4ccfbe97c2fa2/res/drawable-hdpi/drag.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/drag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XspeedPL/PhysicalButtonMod/c419bd313209548010e6d2ce57f4ccfbe97c2fa2/res/drawable-mdpi/drag.9.png
--------------------------------------------------------------------------------
/res/drawable/arrow.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 | -
11 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 | -
25 |
28 |
29 |
30 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/res/drawable/blue_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/res/drawable/btn_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XspeedPL/PhysicalButtonMod/c419bd313209548010e6d2ce57f4ccfbe97c2fa2/res/drawable/btn_delete.png
--------------------------------------------------------------------------------
/res/drawable/drag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XspeedPL/PhysicalButtonMod/c419bd313209548010e6d2ce57f4ccfbe97c2fa2/res/drawable/drag.9.png
--------------------------------------------------------------------------------
/res/drawable/green_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/res/drawable/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XspeedPL/PhysicalButtonMod/c419bd313209548010e6d2ce57f4ccfbe97c2fa2/res/drawable/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable/red_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/res/layout-v14/chainkey.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/res/layout/arrow.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/res/layout/chainitem.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
22 |
28 |
35 |
47 |
60 |
61 |
62 |
63 |
68 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/res/layout/chainkey.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/res/layout/chainlist.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
17 |
30 |
31 |
--------------------------------------------------------------------------------
/res/layout/color_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
21 |
33 |
45 |
46 |
--------------------------------------------------------------------------------
/res/layout/editor.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
21 |
27 |
37 |
47 |
57 |
64 |
70 |
71 |
81 |
88 |
100 |
107 |
113 |
119 |
120 |
130 |
140 |
150 |
157 |
167 |
174 |
184 |
191 |
201 |
208 |
218 |
225 |
232 |
239 |
247 |
248 |
--------------------------------------------------------------------------------
/res/layout/itneditor.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/res/layout/keyeditor.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
19 |
20 |
33 |
34 |
35 |
42 |
43 |
44 |
45 |
52 |
53 |
56 |
57 |
64 |
65 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/res/layout/simple.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/res/layout/test.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
14 |
24 |
33 |
34 |
40 |
41 |
--------------------------------------------------------------------------------
/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/res/values/other.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/res/values/strings_pbmc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Physical Button Music Control
4 | PBMC Settings
5 | PBMC Key Chains
6 | Control your media player easily!
7 |
8 | Confirm action
9 | Do you really want to remove this chain?
10 | Overriding this key can be dangerous, do you really want to continue?
11 | Pick an action
12 | Current key:
13 | Pick a key
14 | Name this chain
15 | Add key
16 | Change
17 | Enter custom intent URI
18 | Entered URI is invalid and couldn\'t be parsed
19 | Keypress action options
20 | Whitelisted apps
21 | App \'%1$s\' killed
22 | One of the chains doesn\'t have a name and wasn\'t saved
23 | One of the chains doesn\'t have any keys and wasn\'t saved
24 | Another chain with the same name exists, changes reverted
25 | It seems you don\'t have any key chains set yet. Would you like to add some basic ones?
26 | Android version %1$s or newer is required
27 | Action of chain \'%1$s\' executed
28 |
29 | Intercept input
30 | Status
31 | Screen
32 | Audio
33 | Music
34 | Telephony
35 | Notify
36 | Action
37 | Delay
38 | Name
39 | Keys
40 | Repeats
41 | Vibration
42 | Cancel original key functions
43 | Long keypress
44 | Yes
45 | No
46 | OK
47 | Via everything
48 | Cancel
49 | Saved
50 | Not saved
51 | Always
52 | Never
53 | Delete
54 | Wake up the screen if off
55 | Convert to advanced chain
56 |
57 | Until key pressed/released
58 |
59 |
60 | - Single press
61 | - Double press
62 | - Triple press
63 | - Press & hold
64 | - Press then press & hold
65 | - Press twice then press & hold
66 |
67 |
68 | Delay/hold time:
69 |
70 |
71 | - Internal speaker
72 | - Wired headset
73 | - Bluetooth headset
74 |
75 |
76 |
77 | - Screen off
78 | - Lockscreen
79 | - Screen on
80 |
81 |
82 |
83 | - Music playing
84 | - Music not playing
85 |
86 |
87 |
88 | - Idle
89 | - Ringing
90 | - In-call
91 |
92 |
93 |
94 | - Show toast
95 | - Play sound
96 | - Pulse light
97 |
98 |
99 | Chain list
100 | Key test
101 | Edit:
102 |
103 | Pressed
104 | Released
105 |
106 | Settings
107 | Add chain
108 | Basic chain
109 | Advanced chain
110 | Save chains
111 |
112 |
113 | - Do nothing
114 | - Media controls
115 | - Keypress
116 | - Extra actions
117 | - Other
118 |
119 |
120 |
121 | - Launch application
122 | - Launch activity
123 | - Launch shortcut
124 | - Custom intent URI
125 |
126 |
127 |
128 | - Play/Pause media
129 | - Next media
130 | - Previous media
131 | - Music volume up
132 | - Music volume down
133 | - Fast forward media
134 | - Rewind media
135 |
136 |
137 |
138 | - Soft reboot
139 | - Toggle flashlight
140 | - Switch to previous app
141 | - Kill foreground app
142 |
143 |
144 | Plug & Play
145 | Send a play media signal when audio devices get connected
146 |
147 | Media signal receiver
148 | Pick an application that will receive media signals
149 | Let the system decide
150 | Use last media player from recents
151 |
152 | Signal send options
153 | Some applications may need a launched activity to work properly
154 |
155 | - No special action
156 | - Launch activity
157 | - Running activity only
158 |
159 |
160 | Enable starting volume
161 | Enable changing media volume on play signals
162 |
163 | Media volume on play signals
164 | Set media volume on play signals
165 | Starting volume
166 |
167 | Sound notification
168 | Select a sound to use for chain notifications
169 |
170 | Pulse light color
171 | Pick a color to pulse the notification light in
172 |
173 | Pulse light time
174 | Choose how long to pulse the notification light
175 |
176 |
--------------------------------------------------------------------------------
/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFDBDBDB
4 | #FFA7A7A7
5 | #FF5A5A5A
6 | #FF404040
7 |
--------------------------------------------------------------------------------
/res/xml/settings.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
17 |
23 |
28 |
38 |
45 |
50 |
59 |
--------------------------------------------------------------------------------
/src/com/android/vending/billing/IInAppBillingService.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.vending.billing;
18 |
19 | import android.os.Bundle;
20 |
21 | /**
22 | * InAppBillingService is the service that provides in-app billing version 3 and beyond.
23 | * This service provides the following features:
24 | * 1. Provides a new API to get details of in-app items published for the app including
25 | * price, type, title and description.
26 | * 2. The purchase flow is synchronous and purchase information is available immediately
27 | * after it completes.
28 | * 3. Purchase information of in-app purchases is maintained within the Google Play system
29 | * till the purchase is consumed.
30 | * 4. An API to consume a purchase of an inapp item. All purchases of one-time
31 | * in-app items are consumable and thereafter can be purchased again.
32 | * 5. An API to get current purchases of the user immediately. This will not contain any
33 | * consumed purchases.
34 | *
35 | * All calls will give a response code with the following possible values
36 | * RESULT_OK = 0 - success
37 | * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
38 | * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
39 | * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
40 | * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
41 | * RESULT_ERROR = 6 - Fatal error during the API action
42 | * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
43 | * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
44 | */
45 | interface IInAppBillingService {
46 | /**
47 | * Checks support for the requested billing API version, package and in-app type.
48 | * Minimum API version supported by this interface is 3.
49 | * @param apiVersion the billing version which the app is using
50 | * @param packageName the package name of the calling app
51 | * @param type type of the in-app item being purchased "inapp" for one-time purchases
52 | * and "subs" for subscription.
53 | * @return RESULT_OK(0) on success, corresponding result code on failures
54 | */
55 | int isBillingSupported(int apiVersion, String packageName, String type);
56 |
57 | /**
58 | * Provides details of a list of SKUs
59 | * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
60 | * with a list JSON strings containing the productId, price, title and description.
61 | * This API can be called with a maximum of 20 SKUs.
62 | * @param apiVersion billing API version that the Third-party is using
63 | * @param packageName the package name of the calling app
64 | * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
65 | * @return Bundle containing the following key-value pairs
66 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
67 | * failure as listed above.
68 | * "DETAILS_LIST" with a StringArrayList containing purchase information
69 | * in JSON format similar to:
70 | * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
71 | * "title : "Example Title", "description" : "This is an example description" }'
72 | */
73 | Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
74 |
75 | /**
76 | * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
77 | * the type, a unique purchase token and an optional developer payload.
78 | * @param apiVersion billing API version that the app is using
79 | * @param packageName package name of the calling app
80 | * @param sku the SKU of the in-app item as published in the developer console
81 | * @param type the type of the in-app item ("inapp" for one-time purchases
82 | * and "subs" for subscription).
83 | * @param developerPayload optional argument to be sent back with the purchase information
84 | * @return Bundle containing the following key-value pairs
85 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
86 | * failure as listed above.
87 | * "BUY_INTENT" - PendingIntent to start the purchase flow
88 | *
89 | * The Pending intent should be launched with startIntentSenderForResult. When purchase flow
90 | * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
91 | * If the purchase is successful, the result data will contain the following key-value pairs
92 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
93 | * failure as listed above.
94 | * "INAPP_PURCHASE_DATA" - String in JSON format similar to
95 | * '{"orderId":"12999763169054705758.1371079406387615",
96 | * "packageName":"com.example.app",
97 | * "productId":"exampleSku",
98 | * "purchaseTime":1345678900000,
99 | * "purchaseToken" : "122333444455555",
100 | * "developerPayload":"example developer payload" }'
101 | * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
102 | * was signed with the private key of the developer
103 | * TODO: change this to app-specific keys.
104 | */
105 | Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
106 | String developerPayload);
107 |
108 | /**
109 | * Returns the current SKUs owned by the user of the type and package name specified along with
110 | * purchase information and a signature of the data to be validated.
111 | * This will return all SKUs that have been purchased in V3 and managed items purchased using
112 | * V1 and V2 that have not been consumed.
113 | * @param apiVersion billing API version that the app is using
114 | * @param packageName package name of the calling app
115 | * @param type the type of the in-app items being requested
116 | * ("inapp" for one-time purchases and "subs" for subscription).
117 | * @param continuationToken to be set as null for the first call, if the number of owned
118 | * skus are too many, a continuationToken is returned in the response bundle.
119 | * This method can be called again with the continuation token to get the next set of
120 | * owned skus.
121 | * @return Bundle containing the following key-value pairs
122 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
123 | * failure as listed above.
124 | * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
125 | * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
126 | * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
127 | * of the purchase information
128 | * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
129 | * next set of in-app purchases. Only set if the
130 | * user has more owned skus than the current list.
131 | */
132 | Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
133 |
134 | /**
135 | * Consume the last purchase of the given SKU. This will result in this item being removed
136 | * from all subsequent responses to getPurchases() and allow re-purchase of this item.
137 | * @param apiVersion billing API version that the app is using
138 | * @param packageName package name of the calling app
139 | * @param purchaseToken token in the purchase information JSON that identifies the purchase
140 | * to be consumed
141 | * @return 0 if consumption succeeded. Appropriate error values for failures.
142 | */
143 | int consumePurchase(int apiVersion, String packageName, String purchaseToken);
144 | }
145 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/Action.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod;
2 |
3 | import android.content.SharedPreferences;
4 | import android.content.SharedPreferences.Editor;
5 | import android.view.KeyEvent;
6 |
7 | public final class Action
8 | {
9 | public static final int ACTION_NONE = -1, ACTION_MEDIA = 0, ACTION_KEY = 1, ACTION_CODED = 2, ACTION_OTHER = 3;
10 |
11 | public static final int MEDIA_PLAY = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
12 | public static final int MEDIA_NEXT = KeyEvent.KEYCODE_MEDIA_NEXT;
13 | public static final int MEDIA_PREV = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
14 | public static final int MEDIA_VOUP = KeyEvent.KEYCODE_VOLUME_UP;
15 | public static final int MEDIA_VODN = KeyEvent.KEYCODE_VOLUME_DOWN;
16 | public static final int MEDIA_FORV = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
17 | public static final int MEDIA_REWD = KeyEvent.KEYCODE_MEDIA_REWIND;
18 | public static final int[] MEDIA = new int[] { MEDIA_PLAY, MEDIA_NEXT, MEDIA_PREV, MEDIA_VOUP, MEDIA_VODN, MEDIA_FORV, MEDIA_REWD };
19 |
20 | public static final int CODED_SRBT = 0, CODED_FLHT = 1, CODED_PAPP = 2, CODED_KFGD = 3;
21 |
22 | public static final String OTHER_SPLT = " <-> ";
23 |
24 | public int type;
25 | public int ex_i;
26 | public String ex_s;
27 |
28 | public Action(final int atype, final String extra) { type = atype; ex_s = extra; }
29 | public Action(final int atype, final int extra) { type = atype; ex_i = extra; }
30 |
31 | public Action(final SharedPreferences sp, final String pref)
32 | {
33 | type = sp.getInt(pref + "type", -1);
34 | if (type < 3) ex_i = sp.getInt(pref + "ex_i", -1);
35 | if (type > 0) ex_s = sp.getString(pref + "ex_s", " " + OTHER_SPLT + " ");
36 | }
37 |
38 | public final void save(final Editor e, final String pref)
39 | {
40 | e.putInt(pref + "type", type);
41 | if (type < 3) e.putInt(pref + "ex_i", ex_i);
42 | if (type > 0) e.putString(pref + "ex_s", ex_s);
43 | }
44 |
45 | public final boolean isKeyLong()
46 | {
47 | return ex_s != null && ex_s.contains("long");
48 | }
49 |
50 | public final String getOtherName()
51 | {
52 | return ex_s.substring(0, ex_s.indexOf(OTHER_SPLT));
53 | }
54 |
55 | public final String getOtherIntent()
56 | {
57 | return ex_s.substring(ex_s.indexOf(OTHER_SPLT) + 5);
58 | }
59 | }
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/Chain.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod;
2 |
3 | import java.util.LinkedList;
4 |
5 | import android.content.SharedPreferences;
6 | import android.content.SharedPreferences.Editor;
7 |
8 | public final class Chain
9 | {
10 | public final LinkedList ks = new LinkedList();
11 | public int vib = 200, rep = 0, au = 7, md = 1, pl = 7, tel = 1, not = 0;
12 | private int ez = -1;
13 | public Action act;
14 | public boolean ccl = true, en = true, scr = false;
15 | public String nm;
16 |
17 | public Chain(final SharedPreferences sp, final String name)
18 | {
19 | nm = name;
20 | if (sp != null) load(sp);
21 | else act = new Action(Action.ACTION_NONE, -1);
22 | }
23 |
24 | @Override
25 | public final int hashCode() { return nm.hashCode() + (ez == -1 ? 0 : 1); }
26 |
27 | @Override
28 | public final boolean equals(final Object o) { return o instanceof Chain && nm.equals(((Chain)o).nm); }
29 |
30 | final void load(final SharedPreferences sp)
31 | {
32 | final String pref = "chains." + nm + ".";
33 | act = new Action(sp, pref + "act.");
34 | try
35 | {
36 | en = sp.getBoolean(pref + "en", true);
37 | ez = sp.getInt(pref + "ez", -1);
38 | vib = sp.getInt(pref + "vib", 200);
39 | rep = sp.getInt(pref + "rep", 0);
40 | au = sp.getInt(pref + "au", 7);
41 | pl = sp.getInt(pref + "pl", 7);
42 | md = sp.getInt(pref + "md", 1);
43 | tel = sp.getInt(pref + "tel", 1);
44 | ccl = sp.getBoolean(pref + "ccl", true);
45 | scr = sp.getBoolean(pref + "scr", false);
46 | not = sp.getInt(pref + "not", 0);
47 | }
48 | catch (final Exception ex) { }
49 | int kct = sp.getInt(pref + "kct", 0);
50 | for (int i = 0; i < kct; ++i)
51 | {
52 | int c = sp.getInt(pref + "k" + i + ".c", 0);
53 | boolean dn = sp.getBoolean(pref + "k" + i + ".dn", false);
54 | int dl = sp.getInt(pref + "k" + i + ".dl", 0);
55 | ks.add(new Key(c, dn, dl));
56 | }
57 | }
58 |
59 | public final void save(final Editor e)
60 | {
61 | final String pref = "chains." + nm + ".";
62 | act.save(e, pref + "act.");
63 | e.putBoolean(pref + "en", en);
64 | e.putInt(pref + "ez", ez);
65 | e.putInt(pref + "vib", vib);
66 | e.putInt(pref + "rep", rep);
67 | e.putInt(pref + "au", au);
68 | e.putInt(pref + "pl", pl);
69 | e.putInt(pref + "md", md);
70 | e.putInt(pref + "tel", tel);
71 | e.putBoolean(pref + "ccl", ccl);
72 | e.putBoolean(pref + "scr", scr);
73 | e.putInt(pref + "not", not);
74 | e.putInt(pref + "kct", ks.size());
75 | int i = -1;
76 | for (final Key k : ks)
77 | {
78 | e.putInt(pref + "k" + (++i) + ".c", k.code);
79 | e.putBoolean(pref + "k" + i + ".dn", k.dn);
80 | e.putInt(pref + "k" + i + ".dl", k.dl);
81 | }
82 | }
83 |
84 | public final boolean isEz() { return ez != -1; }
85 |
86 | public final int getEz() { return ez; }
87 |
88 | public final void setEz(final int t, final int key, final int dl)
89 | {
90 | if (t != -1)
91 | {
92 | ks.clear();
93 | for (int i = t % 3; i >= 0; --i)
94 | {
95 | ks.add(new Key(key, true, 0));
96 | ks.add(new Key(key, false, 0));
97 | }
98 | if (t > 2) ks.removeLast();
99 | ks.getLast().dl = dl;
100 | }
101 | ez = t;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/Coded.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 |
6 | import android.annotation.TargetApi;
7 | import android.app.*;
8 | import android.content.*;
9 | import android.content.pm.ApplicationInfo;
10 | import android.content.pm.ResolveInfo;
11 | import android.hardware.Camera;
12 | import android.hardware.Camera.Parameters;
13 | import android.hardware.camera2.*;
14 | import android.os.*;
15 | import android.support.v7.app.NotificationCompat;
16 | import android.widget.Toast;
17 | import de.robv.android.xposed.XposedHelpers;
18 |
19 | @SuppressWarnings("deprecation")
20 | public final class Coded
21 | {
22 | public static final int SDK = Build.VERSION.SDK_INT;
23 |
24 | public static final String IACT_TOGGLE_LIGHT = "xeed.xposed.cbppmod.TOGGLE_LIGHT";
25 | private static Context app = null;
26 |
27 | public static final void setAppCtx(final Context c) { app = c; }
28 |
29 | public static final class AppBridge extends BroadcastReceiver
30 | {
31 | @Override
32 | public final void onReceive(final Context c, final Intent i)
33 | {
34 | if (i != null && i.getAction() == IACT_TOGGLE_LIGHT)
35 | {
36 | final Intent ni = new Intent(c, LightService.class);
37 | ni.setAction(IACT_TOGGLE_LIGHT);
38 | c.startService(ni);
39 | }
40 | }
41 | }
42 |
43 | public static final class LightService extends Service
44 | {
45 | private Notification mTorchNotif = null;
46 | private TorchAccess mAccess = null;
47 | private boolean state = false;
48 |
49 | @Override
50 | public final IBinder onBind(final Intent i) { return null; }
51 |
52 | @Override
53 | public final void onCreate()
54 | {
55 | super.onCreate();
56 | if (app == null) app = this;
57 | if (SDK > 22) mAccess = new TorchNew();
58 | else mAccess = new TorchOld();
59 | final NotificationCompat.Builder b = new NotificationCompat.Builder(this);
60 | b.setContentTitle(getResources().getStringArray(R.array.action_coded_k)[Action.CODED_FLHT]);
61 | b.setSmallIcon(android.R.drawable.ic_menu_camera);
62 | b.setContentIntent(PendingIntent.getService(this, 0, new Intent(this, LightService.class), 0));
63 | mTorchNotif = b.build();
64 | }
65 |
66 | @Override
67 | public final int onStartCommand(final Intent i, final int f, final int id)
68 | {
69 | if (i != null && i.getAction() == IACT_TOGGLE_LIGHT && !state && mAccess.toggle(true))
70 | {
71 | state = true;
72 | startForeground(2, mTorchNotif);
73 | return START_REDELIVER_INTENT;
74 | }
75 | stopSelf();
76 | return START_NOT_STICKY;
77 | }
78 |
79 | @Override
80 | public final void onDestroy()
81 | {
82 | mAccess.close();
83 | super.onDestroy();
84 | }
85 |
86 | private interface TorchAccess
87 | {
88 | public boolean toggle(final boolean on);
89 | public void close();
90 | }
91 |
92 | private final class TorchOld implements TorchAccess
93 | {
94 | private Camera mCam = null;
95 |
96 | @Override
97 | public final void close()
98 | {
99 | if (mCam != null) toggle(false);
100 | mCam.release();
101 | mCam = null;
102 | }
103 |
104 | @Override
105 | public synchronized final boolean toggle(final boolean on)
106 | {
107 | if (mCam == null) mCam = Camera.open();
108 | if (mCam == null) return false;
109 | final Parameters p = mCam.getParameters();
110 | if (on)
111 | {
112 | final List l = p.getSupportedFlashModes();
113 | if (l != null && l.contains(Parameters.FLASH_MODE_TORCH))
114 | {
115 | p.setFlashMode(Parameters.FLASH_MODE_TORCH);
116 | mCam.setParameters(p);
117 | mCam.startPreview();
118 | }
119 | else return false;
120 | }
121 | else
122 | {
123 | p.setFlashMode(Parameters.FLASH_MODE_OFF);
124 | mCam.setParameters(p);
125 | mCam.stopPreview();
126 | }
127 | return on;
128 | }
129 | }
130 |
131 | @TargetApi(23)
132 | private final class TorchNew implements TorchAccess
133 | {
134 | @Override
135 | public final void close() { toggle(false); }
136 |
137 | @Override
138 | public final boolean toggle(final boolean on)
139 | {
140 | final CameraManager cammgr = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
141 | try
142 | {
143 | final String[] ids = cammgr.getCameraIdList();
144 | for (final String id : ids)
145 | {
146 | final CameraCharacteristics cc = cammgr.getCameraCharacteristics(id);
147 | if (cc.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))
148 | {
149 | cammgr.setTorchMode(id, on);
150 | return on;
151 | }
152 | }
153 | showError("No flash");
154 | return !on;
155 | }
156 | catch (final Exception ex)
157 | {
158 | showError(ex.getLocalizedMessage());
159 | return !on;
160 | }
161 | }
162 | }
163 | }
164 |
165 | public static final void toggleFlash(final Context c)
166 | {
167 | final Intent i = new Intent(c, LightService.class);
168 | i.setAction(IACT_TOGGLE_LIGHT);
169 | c.startService(i);
170 | }
171 |
172 | public static final void softReboot() throws Exception
173 | {
174 | Runtime.getRuntime().exec(new String[] { "setprop", "ctl.restart", "surfaceflinger" }).waitFor();
175 | Runtime.getRuntime().exec(new String[] { "setprop", "ctl.restart", "zygote" }).waitFor();
176 | }
177 |
178 | @TargetApi(11)
179 | public static final void switchToLastApp(final Context c)
180 | {
181 | if (SDK > 10)
182 | {
183 | final ActivityManager am = (ActivityManager)c.getSystemService(Context.ACTIVITY_SERVICE);
184 | int lastAppId = 0;
185 | final Intent intent = new Intent(Intent.ACTION_MAIN);
186 | String homePackage = "com.android.launcher";
187 | intent.addCategory(Intent.CATEGORY_HOME);
188 | final ResolveInfo res = c.getPackageManager().resolveActivity(intent, 0);
189 | if (res.activityInfo != null && !res.activityInfo.packageName.equals("android"))
190 | homePackage = res.activityInfo.packageName;
191 | final List tasks = am.getRunningTasks(5);
192 | for (int i = 1; i < tasks.size(); ++i)
193 | {
194 | final String pkg = tasks.get(i).topActivity.getPackageName();
195 | if (!homePackage.equals(pkg) && !pkg.equals("com.android.systemui"))
196 | {
197 | lastAppId = tasks.get(i).id;
198 | break;
199 | }
200 | }
201 | if (lastAppId != 0) am.moveTaskToFront(lastAppId, 0);
202 | }
203 | else showError(app.getString(R.string.diag_and_req, "11 (Honeycomb)"));
204 | }
205 |
206 | public static final void killForeground(final Context c, final String topPkg, final String data)
207 | {
208 | try
209 | {
210 | final List wlist = Arrays.asList(data.split(" "));
211 | if (wlist.contains(topPkg)) return;
212 | final ApplicationInfo ai = c.getPackageManager().getApplicationInfo(topPkg, 0);
213 | XposedHelpers.callMethod(c.getSystemService(Context.ACTIVITY_SERVICE), "forceStopPackage", topPkg);
214 | Toast.makeText(c, app.getString(R.string.diag_kill, ai.loadLabel(c.getPackageManager()).toString()), Toast.LENGTH_SHORT).show();
215 | }
216 | catch (final Exception ex) { showError(ex.getLocalizedMessage()); }
217 | }
218 |
219 | private static final void showError(final String txt)
220 | {
221 | Toast.makeText(app, "ERROR: " + txt, Toast.LENGTH_SHORT).show();
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/InAppMgmt.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod;
2 |
3 | import java.util.ArrayList;
4 |
5 | import org.json.JSONException;
6 | import org.json.JSONObject;
7 |
8 | import com.android.vending.billing.IInAppBillingService;
9 |
10 | import android.app.Activity;
11 | import android.app.PendingIntent;
12 | import android.content.ComponentName;
13 | import android.content.Context;
14 | import android.content.Intent;
15 | import android.content.ServiceConnection;
16 | import android.os.Bundle;
17 | import android.os.IBinder;
18 | import android.os.RemoteException;
19 | import android.widget.Toast;
20 |
21 | public final class InAppMgmt implements ServiceConnection
22 | {
23 | static final String ITEM_EXCHAIN = "extraLenChains";
24 |
25 | private IInAppBillingService mService;
26 |
27 | @Override
28 | public final void onServiceDisconnected(final ComponentName cn)
29 | {
30 | mService = null;
31 | }
32 |
33 | @Override
34 | public final void onServiceConnected(final ComponentName cn, final IBinder b)
35 | {
36 | mService = IInAppBillingService.Stub.asInterface(b);
37 | }
38 |
39 | public final void bindService(final Context c)
40 | {
41 | final Intent it = new Intent("com.android.vending.billing.InAppBillingService.BIND");
42 | it.setPackage("com.android.vending");
43 | c.bindService(it, this, Context.BIND_AUTO_CREATE);
44 | }
45 |
46 | public final void unbindService(final Context c)
47 | {
48 | c.unbindService(this);
49 | }
50 |
51 | public final int getItemState(final String item)
52 | {
53 | try
54 | {
55 | final Bundle res = mService.getPurchases(3, "xeed.xposed.cbppmod", "inapp", null);
56 | final int resp = res.getInt("RESPONSE_CODE");
57 | if (resp == 0)
58 | {
59 | final ArrayList items = res.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
60 | if (items.contains(item)) return 1;
61 | }
62 | return 0;
63 | }
64 | catch (final RemoteException ex)
65 | {
66 | return -1;
67 | }
68 | }
69 |
70 | public final int buyItem(final Activity a, final String item)
71 | {
72 | try
73 | {
74 | final Bundle res = mService.getBuyIntent(3, "xeed.xposed.cbppmod", item, "inapp", "ilikepotatoes");
75 | final int resp = res.getInt("RESPONSE_CODE");
76 | if (resp == 0)
77 | {
78 | final PendingIntent pendingIntent = res.getParcelable("BUY_INTENT");
79 | a.startIntentSenderForResult(pendingIntent.getIntentSender(), PBMain.REQ_INAPP, new Intent(), 0, 0, 0);
80 | }
81 | return 0;
82 | }
83 | catch (final Exception ex)
84 | {
85 | return -1;
86 | }
87 | }
88 |
89 | public final String buyResult(final Context c, final int resultCode, final Intent data)
90 | {
91 | final String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
92 | if (resultCode == Activity.RESULT_OK && data.getIntExtra("RESPONSE_CODE", 0) == 0)
93 | {
94 | try
95 | {
96 | final JSONObject jo = new JSONObject(purchaseData);
97 | return jo.getString("productId");
98 | }
99 | catch (final JSONException ex)
100 | {
101 | Toast.makeText(c, ex.getLocalizedMessage(), Toast.LENGTH_LONG).show();
102 | ex.printStackTrace();
103 | }
104 | }
105 | // TODO: Messages...
106 | else Toast.makeText(c, "FAIL", Toast.LENGTH_LONG).show();
107 | return null;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/Key.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod;
2 |
3 | import android.os.SystemClock;
4 |
5 | public final class Key
6 | {
7 | public long sw;
8 | public int code, dl;
9 | public boolean dn;
10 |
11 | public Key(final int kcode, final boolean down, final int delay)
12 | {
13 | code = kcode; dn = down;
14 | dl = delay < 0 ? 0 : delay;
15 | sw = SystemClock.elapsedRealtime();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/PBMain.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod;
2 |
3 | import java.util.Iterator;
4 | import java.util.ListIterator;
5 | import java.util.Locale;
6 |
7 | import android.annotation.SuppressLint;
8 | import android.content.*;
9 | import android.content.DialogInterface.*;
10 | import android.content.pm.PackageInfo;
11 | import android.content.res.Resources;
12 | import android.os.Bundle;
13 | import android.support.v4.view.ViewPager;
14 | import android.support.v7.app.AppCompatActivity;
15 | import android.text.SpannableString;
16 | import android.text.style.StyleSpan;
17 | import android.util.SparseArray;
18 | import android.view.*;
19 | import android.view.View.OnClickListener;
20 | import android.widget.*;
21 | import xeed.library.ui.BaseSettings;
22 | import xeed.library.ui.SimpleDialog;
23 | import xeed.xposed.cbppmod.ui.*;
24 |
25 | public final class PBMain extends AppCompatActivity
26 | {
27 | public static final int REQ_SHCUT = 1028, REQ_INAPP = 1666;
28 | public static final SparseArray keyDb = new SparseArray();
29 | public static final StyleSpan bold = new StyleSpan(android.graphics.Typeface.BOLD);
30 |
31 | public static Resources r = null;
32 |
33 | public SharedPreferences sp = null;
34 | private String[] pl_v, not_v;
35 | private PagerAdapter spa = null;
36 | private ViewPager vp = null;
37 | private InAppMgmt pro = null;
38 | private int th = -1;
39 |
40 | @SuppressLint("WorldReadableFiles")
41 | @SuppressWarnings("deprecation")
42 | @Override
43 | protected final void onCreate(final Bundle b)
44 | {
45 | super.onCreate(b);
46 | r = getResources();
47 | pl_v = r.getStringArray(R.array.pl_items);
48 | not_v = r.getStringArray(R.array.not_items);
49 | sp = getSharedPreferences("pbmcsettings", MODE_WORLD_READABLE);
50 | BaseSettings.reloadThemes(sp);
51 | setTheme(th = BaseSettings.getActTh());
52 | setContentView(R.layout.main);
53 | vp = (ViewPager)findViewById(R.id.pager);
54 | vp.setOffscreenPageLimit(4);
55 | spa = new PagerAdapter(vp, getSupportFragmentManager());
56 | vp.setAdapter(spa);
57 | }
58 |
59 | @Override
60 | public final void onRequestPermissionsResult(final int req, final String[] perms, final int[] ress)
61 | {
62 | // TODO?
63 | }
64 |
65 | private final InAppMgmt getInApp()
66 | {
67 | if (pro == null)
68 | {
69 | pro = new InAppMgmt();
70 | pro.bindService(this);
71 | }
72 | return pro;
73 | }
74 |
75 | public final PagerAdapter getPager() { return spa; }
76 |
77 | public static final void populateKeys(final ViewGroup view, final LayoutInflater li, final Chain ch, final OnClickListener l)
78 | {
79 | view.removeAllViews();
80 | if (ch.isEz())
81 | {
82 | final Key k = ch.ks.getLast();
83 | final String[] ezt = PBMain.r.getStringArray(R.array.ez_types);
84 | final Button bt = (Button)li.inflate(R.layout.chainkey, view, false);
85 | bt.setId(R.id.ch_ez);
86 | final String title = ezt[ch.getEz()] + " (" + PBMain.key(k.code) + ")";
87 | final SpannableString ss = new SpannableString(title + "\n" + r.getString(R.string.ez_delay) + " " + (k.dl / 1000F) + "s");
88 | ss.setSpan(PBMain.bold, 0, title.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
89 | bt.setText(ss);
90 | bt.setLines(2);
91 | if (l != null) bt.setOnClickListener(l);
92 | view.addView(bt);
93 | }
94 | else
95 | {
96 | final Iterator it = ch.ks.iterator();
97 | while (it.hasNext())
98 | {
99 | final Key k = it.next();
100 | final Button bt = (Button)li.inflate(R.layout.chainkey, view, false);
101 | final String key = PBMain.key(k.code);
102 | final SpannableString ss = new SpannableString(key + "\n" + r.getString(k.dn ? R.string.key_pressed : R.string.key_released) + "\n" + (k.dl < 1 ? "" : r.getString(R.string.diag_dl) + ": " + (k.dl/1000F) + "s"));
103 | ss.setSpan(PBMain.bold, 0, key.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
104 | bt.setText(ss);
105 | bt.setTag(k);
106 | if (l != null) bt.setOnClickListener(l);
107 | view.addView(bt);
108 | if (l != null || it.hasNext()) view.addView(li.inflate(R.layout.arrow, view, false));
109 | }
110 | if (l != null)
111 | {
112 | final Button bt = (Button)li.inflate(R.layout.chainkey, view, false);
113 | bt.setId(R.id.add_key);
114 | bt.getBackground().setAlpha(127);
115 | bt.setText("\n" + r.getString(R.string.diag_add_key) + "\n");
116 | bt.setOnClickListener(l);
117 | view.addView(bt);
118 | }
119 | }
120 | }
121 |
122 | @Override
123 | public final void onActivityResult(final int req, final int res, final Intent i)
124 | {
125 | if (req == REQ_SHCUT)
126 | {
127 | if (res == RESULT_OK)
128 | {
129 | final ChainEditFragment cef = spa.getEdit();
130 | final String name = i.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
131 | final Intent main = i.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
132 | final Action a = spa.edit.act;
133 | a.type = Action.ACTION_OTHER;
134 | a.ex_i = 1;
135 | a.ex_s = name + Action.OTHER_SPLT + main.toUri(0);
136 | cef.actionChanged();
137 | }
138 | }
139 | else if (req == REQ_INAPP)
140 | {
141 | final String item = getInApp().buyResult(this, res, i);
142 | if (item != null) sp.edit().putBoolean("pro." + item, true).commit();
143 | }
144 | else super.onActivityResult(req, res, i);
145 | }
146 |
147 | @Override
148 | protected final void onDestroy()
149 | {
150 | if (pro != null)
151 | {
152 | pro.unbindService(this);
153 | pro = null;
154 | }
155 | super.onDestroy();
156 | }
157 |
158 | @Override
159 | protected final void onPause()
160 | {
161 | requestIntercept(false);
162 | super.onPause();
163 | }
164 |
165 | @Override
166 | protected final void onResume()
167 | {
168 | super.onResume();
169 | if (th != BaseSettings.getActTh()) finish();
170 | }
171 |
172 | @Override
173 | public final void onStart()
174 | {
175 | super.onStart();
176 | final PackageInfo pi = getVerInfo();
177 | if (pi.versionCode != getActiveVerCode())
178 | {
179 | final CharSequence msg = getString(getActiveVerCode() == 0 ? R.string.diag_reboot : R.string.diag_update, pi.versionCode, getActiveVerCode());
180 | SimpleDialog.create(this, BaseSettings.getDiagTh(), R.string.diag_ok, R.string.app_name, msg, getActiveVerCode() == 0 ? new OnDismissListener()
181 | {
182 | @Override
183 | public final void onDismiss(final DialogInterface di)
184 | {
185 | finish();
186 | }
187 | } : null).show();
188 | }
189 | }
190 |
191 | @Override
192 | public final boolean onCreateOptionsMenu(final Menu m)
193 | {
194 | getMenuInflater().inflate(R.menu.main, m);
195 | return super.onCreateOptionsMenu(m);
196 | }
197 |
198 | @Override
199 | public final boolean onOptionsItemSelected(final MenuItem mi)
200 | {
201 | if (mi.getItemId() == R.id.setts)
202 | {
203 | startActivity(new Intent(this, PBSettings.class));
204 | return true;
205 | }
206 | else if (mi.getItemId() == R.id.basch || mi.getItemId() == R.id.advch)
207 | {
208 | final ListIterator li = spa.getIterator();
209 | while (li.hasNext())
210 | if (li.next().nm.equals(""))
211 | {
212 | li.remove();
213 | break;
214 | }
215 | final Chain ch = new Chain(sp, "");
216 | if (mi.getItemId() == R.id.basch) ch.setEz(0, KeyEvent.KEYCODE_UNKNOWN, 0);
217 | spa.addChain(ch);
218 | spa.setEdit(ch);
219 | return true;
220 | }
221 | else if (mi.getItemId() == R.id.save)
222 | {
223 | if (spa.edit != null) spa.getEdit().onFocusChange(spa.getEdit().getView().findViewById(R.id.ch_nm), false);
224 | final SharedPreferences.Editor e = sp.edit();
225 | int n = 0;
226 | final ListIterator li = spa.getIterator();
227 | while (li.hasNext())
228 | {
229 | final Chain ch = li.next();
230 | e.putString("chainlist." + n, ch.nm);
231 | if (ch.nm.length() < 1) Toast.makeText(this, R.string.diag_nm_err, Toast.LENGTH_LONG).show();
232 | else if (ch.ks.size() < 1) Toast.makeText(this, R.string.diag_ks_err, Toast.LENGTH_LONG).show();
233 | else ch.save(e);
234 | ++n;
235 | }
236 | e.putInt("chainlist.count", n);
237 | e.commit();
238 | spa.chainsSaved();
239 | if (vp.getCurrentItem() != 0) Toast.makeText(this, R.string.diag_sav, Toast.LENGTH_SHORT).show();
240 | return true;
241 | }
242 | return super.onOptionsItemSelected(mi);
243 | }
244 |
245 | public static final boolean isKeySafe(final int key)
246 | {
247 | return key != KeyEvent.KEYCODE_POWER && key != KeyEvent.KEYCODE_HOME;
248 | }
249 |
250 | @Override
251 | public final void onBackPressed()
252 | {
253 | if (vp.getCurrentItem() != 0) vp.setCurrentItem(0);
254 | else super.onBackPressed();
255 | }
256 |
257 | public static final String key(final int code, final int scan)
258 | {
259 | final String s = keyDb.get(code);
260 | if (s == null) return keyDb.get(0) + (scan == 0 ? "" : " (SC " + Integer.toHexString(scan) + ")");
261 | else return s;
262 | }
263 |
264 | public static final String key(final int code)
265 | {
266 | final String s = keyDb.get(code);
267 | if (s == null) return keyDb.get(0);
268 | else return s;
269 | }
270 |
271 | private static final String format(final String s)
272 | {
273 | final char[] c = s.toLowerCase(Locale.getDefault()).toCharArray();
274 | boolean f = true;
275 | for (int i = 0; i < c.length; ++i)
276 | {
277 | if (Character.isWhitespace(c[i])) f = true;
278 | else if (f)
279 | {
280 | c[i] = Character.toUpperCase(c[i]);
281 | f = false;
282 | }
283 | }
284 | return new String(c);
285 | }
286 |
287 | public static final String action(final Action a)
288 | {
289 | String ret = null;
290 | String[] arr = r.getStringArray(R.array.action_k);
291 | if (a.type == Action.ACTION_CODED)
292 | {
293 | arr = r.getStringArray(R.array.action_coded_k);
294 | ret = arr[a.ex_i];
295 | }
296 | else if (a.type == Action.ACTION_KEY)
297 | {
298 | ret = (a.isKeyLong() ? r.getString(R.string.diag_prs_lng) : arr[2]) + " (" + key(a.ex_i) + ')';
299 | }
300 | else if (a.type == Action.ACTION_MEDIA)
301 | {
302 | arr = r.getStringArray(R.array.action_media_k);
303 | for (int i = 0; i < Action.MEDIA.length; ++i)
304 | if (a.ex_i == Action.MEDIA[i])
305 | {
306 | ret = arr[i];
307 | break;
308 | }
309 | }
310 | else if (a.type == Action.ACTION_OTHER)
311 | {
312 | ret = arr[4] + " (" + a.getOtherName() + ')';
313 | }
314 | return ret == null ? arr[0] : ret;
315 | }
316 |
317 | public final String btnTxt(final int arrId, final int flags)
318 | {
319 | String ret = "";
320 | if ((flags & 7) == 7) ret = "+++" + getString(R.string.diag_alw);
321 | else
322 | {
323 | final String[] arr = r.getStringArray(arrId);
324 | if ((flags & 1) == 1) ret += " + " + arr[0];
325 | if ((flags & 2) == 2) ret += " + " + arr[1];
326 | if ((flags & 4) == 4) ret += " + " + arr[2];
327 | }
328 | if (ret.equals("")) ret = "---" + getString(R.string.diag_nev);
329 | return ret.substring(3);
330 | }
331 |
332 | public final String music(final int pl)
333 | {
334 | String ret = "";
335 | if ((pl & 3) == 3) ret = "+++" + getString(R.string.diag_alw);
336 | else
337 | {
338 | if ((pl & 1) == 1) ret += " + " + pl_v[0];
339 | if ((pl & 2) == 2) ret += " + " + pl_v[1];
340 | }
341 | if (ret.equals("")) ret = "---" + getString(R.string.diag_nev);
342 | return ret.substring(3);
343 | }
344 |
345 | public final String notify(final int not)
346 | {
347 | String ret = "";
348 | if ((not & 7) == 7) ret = "+++" + getString(R.string.diag_all);
349 | else
350 | {
351 | if ((not & 1) == 1) ret += " + " + not_v[0];
352 | if ((not & 2) == 2) ret += " + " + not_v[1];
353 | if ((not & 4) == 4) ret += " + " + not_v[2];
354 | }
355 | if (ret.equals("")) ret = "---" + getString(R.string.diag_no);
356 | return ret.substring(3);
357 | }
358 |
359 | private final PackageInfo getVerInfo()
360 | {
361 | try { return getPackageManager().getPackageInfo(getPackageName(), 0); }
362 | catch (final Exception ex) { return null; }
363 | }
364 |
365 | @Deprecated
366 | public static final String getActiveVerName() { return ""; }
367 |
368 | public static final int getActiveVerCode() { return 0; }
369 |
370 | public final void requestIntercept(final boolean state)
371 | {
372 | final Intent i = new Intent("xeed.xposed.cbppmod.Send");
373 | i.putExtra("xeed.xposed.cbppmod.Send", state);
374 | sendBroadcast(i);
375 | }
376 |
377 | static
378 | {
379 | for (final java.lang.reflect.Field f : KeyEvent.class.getDeclaredFields())
380 | try
381 | {
382 | if (f.getName().startsWith("KEYCODE_"))
383 | {
384 | f.setAccessible(true);
385 | keyDb.put(f.getInt(null), format(f.getName().substring(8).replace('_', ' ')));
386 | }
387 | }
388 | catch (final Exception ex) { }
389 | }
390 | }
391 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/PBSettings.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import android.content.*;
7 | import android.content.pm.PackageManager;
8 | import android.content.pm.ResolveInfo;
9 | import android.preference.DialogPreference;
10 | import android.preference.ListPreference;
11 | import android.preference.PreferenceManager;
12 | import xeed.library.ui.BaseSettings;
13 | import xeed.xposed.cbppmod.prf.FlagListPreference;
14 |
15 | public final class PBSettings extends BaseSettings
16 | {
17 | static final List getMediaReceivers(final PackageManager pm)
18 | {
19 | final Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON);
20 | return pm.queryBroadcastReceivers(i, PackageManager.GET_INTENT_FILTERS | PackageManager.GET_RESOLVED_FILTER);
21 | }
22 |
23 | @Override
24 | protected final void onCreatePreferences(final PreferenceManager mgr)
25 | {
26 | addPreferencesToCategory(R.xml.settings, Category.general);
27 | final SharedPreferences sp = mgr.getSharedPreferences();
28 | final FlagListPreference flp = (FlagListPreference)mgr.findPreference("usePlugIn");
29 | final CharSequence[] old = flp.getEntries();
30 | final CharSequence[] cs = new CharSequence[old.length - 1];
31 | System.arraycopy(old, 1, cs, 0, cs.length);
32 | flp.setEntries(cs);
33 | final ListPreference lp = (ListPreference)mgr.findPreference("setPlayer");
34 | final List ris = getMediaReceivers(getPackageManager());
35 | final ArrayList i = new ArrayList(ris.size() + 1), v = new ArrayList(ris.size() + 1);
36 | i.add(getString(R.string.pref_setplayer_v1)); v.add("system");
37 | i.add(getString(R.string.pref_setplayer_v2)); v.add("recent");
38 | for (final ResolveInfo ri : ris)
39 | {
40 | final String val = ri.activityInfo.packageName + '\t' + ri.activityInfo.name;
41 | final CharSequence lab = ri.activityInfo.applicationInfo.loadLabel(getPackageManager());
42 | i.add(lab + " (" + ri.activityInfo.name + ")");
43 | v.add(val);
44 | }
45 | lp.setEntries(i.toArray(new CharSequence[i.size()]));
46 | lp.setEntryValues(v.toArray(new CharSequence[v.size()]));
47 | mgr.findPreference("setPlrMode").setEnabled(sp.getString("setPlayer", "system").indexOf('\t') > 0);
48 | if (sp.getInt("usePlugOnly", 0) == 0) sp.edit().putInt("usePlugOnly", 7).apply();
49 | final DialogPreference idp = (DialogPreference)mgr.findPreference("authors");
50 | idp.setDialogMessage(idp.getDialogMessage() + "\n DragSortListView:\n bauerca & kelsos\n FlowLayout:\n ApmeM");
51 | mgr.findPreference("soundURI").setOnPreferenceChangeListener(this);
52 | }
53 |
54 | @Override
55 | protected final void onPreferenceChanged(final PreferenceManager mgr, final SharedPreferences prefs, final String key)
56 | {
57 | if (key.equals("setPlayer")) mgr.findPreference("setPlrMode").setEnabled(prefs.getString(key, "system").indexOf('\t') > 0);
58 | if (key.equals("usePlugOnly") && prefs.getInt("usePlugOnly", 0) == 0) prefs.edit().putInt("usePlugOnly", 7).apply();
59 | }
60 |
61 | @Override
62 | protected final String getPrefsName() { return "pbmcsettings"; }
63 | }
64 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/prf/ColorPreference.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.prf;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.annotation.TargetApi;
5 | import android.app.AlertDialog;
6 | import android.app.AlertDialog.Builder;
7 | import android.content.Context;
8 | import android.content.DialogInterface;
9 | import android.content.res.TypedArray;
10 | import android.graphics.Color;
11 | import android.graphics.drawable.ColorDrawable;
12 | import android.os.Build;
13 | import android.os.Bundle;
14 | import android.preference.DialogPreference;
15 | import android.util.AttributeSet;
16 | import android.util.TypedValue;
17 | import android.view.LayoutInflater;
18 | import android.view.View;
19 | import android.widget.*;
20 | import xeed.xposed.cbppmod.R;
21 |
22 | public class ColorPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener
23 | {
24 | private final ColorDrawable mImage;
25 |
26 | Button okColorButton;
27 | SeekBar redSeekBar, greenSeekBar, blueSeekBar;
28 | private int red, green, blue;
29 |
30 | public ColorPreference(final Context c, final AttributeSet as)
31 | {
32 | super(c, as);
33 | mImage = new ColorDrawable(0xffffff);
34 | }
35 |
36 | @Override
37 | protected final void onSetInitialValue(final boolean restore, final Object def) { }
38 |
39 | @Override
40 | protected final Object onGetDefaultValue(final TypedArray ta, final int i)
41 | {
42 | return ta.getInt(i, 0);
43 | }
44 |
45 | @SuppressLint("InflateParams")
46 | @Override
47 | protected void onPrepareDialogBuilder(final Builder b)
48 | {
49 | super.onPrepareDialogBuilder(b);
50 | final View v = LayoutInflater.from(getContext()).inflate(R.layout.color_picker, null, false);
51 | b.setView(v);
52 | redSeekBar = (SeekBar)v.findViewById(R.id.redSeekBar);
53 | greenSeekBar = (SeekBar)v.findViewById(R.id.greenSeekBar);
54 | blueSeekBar = (SeekBar)v.findViewById(R.id.blueSeekBar);
55 | redSeekBar.setOnSeekBarChangeListener(this);
56 | greenSeekBar.setOnSeekBarChangeListener(this);
57 | blueSeekBar.setOnSeekBarChangeListener(this);
58 |
59 | int c = 0xffffff;
60 | try { c = getPersistedInt(c); }
61 | catch (final Exception ex) { ex.printStackTrace(); }
62 | updateColor11(c);
63 | red = Color.red(c);
64 | green = Color.green(c);
65 | blue = Color.blue(c);
66 |
67 | redSeekBar.setProgress(red);
68 | greenSeekBar.setProgress(green);
69 | blueSeekBar.setProgress(blue);
70 | final int size = getPx(25);
71 | mImage.setBounds(0, 0, size, size);
72 | }
73 |
74 | @TargetApi(11)
75 | private final void updateColor11(final int color)
76 | {
77 | if (Build.VERSION.SDK_INT > 10) mImage.setColor(color);
78 | }
79 |
80 | @Override
81 | public final void showDialog(final Bundle b)
82 | {
83 | super.showDialog(b);
84 | final AlertDialog ad = (AlertDialog)getDialog();
85 | okColorButton = ad.getButton(AlertDialog.BUTTON_POSITIVE);
86 | okColorButton.setCompoundDrawablePadding(getPx(7));
87 | okColorButton.setCompoundDrawables(mImage, null, null, null);
88 | }
89 |
90 | public final int getPx(final float dp)
91 | {
92 | return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
93 | }
94 |
95 | @Override
96 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
97 | {
98 | if (seekBar.getId() == R.id.redSeekBar) red = progress;
99 | else if (seekBar.getId() == R.id.greenSeekBar) green = progress;
100 | else if (seekBar.getId() == R.id.blueSeekBar) blue = progress;
101 | updateColor11(getColor());
102 | }
103 |
104 | @Override
105 | public final void onClick(final DialogInterface di, final int pos)
106 | {
107 | if (pos == DialogInterface.BUTTON_POSITIVE) persistInt(getColor());
108 | }
109 |
110 | @Override
111 | public void onStopTrackingTouch(SeekBar seekBar) { }
112 |
113 | @Override
114 | public void onStartTrackingTouch(SeekBar seekBar) { }
115 |
116 | public int getRed() { return red; }
117 |
118 | public int getGreen() { return green; }
119 |
120 | public int getBlue() { return blue; }
121 |
122 | public int getColor() { return Color.rgb(red, green, blue); }
123 | }
124 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/prf/FlagListPreference.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.prf;
2 |
3 | import android.app.AlertDialog.Builder;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.DialogInterface.OnMultiChoiceClickListener;
7 | import android.content.res.TypedArray;
8 | import android.preference.DialogPreference;
9 | import android.util.AttributeSet;
10 |
11 |
12 | public final class FlagListPreference extends DialogPreference implements OnMultiChoiceClickListener
13 | {
14 | private CharSequence[] mEntries;
15 | private int mNewValue;
16 |
17 | public FlagListPreference(final Context c, final AttributeSet as)
18 | {
19 | super(c, as);
20 | final TypedArray ta = c.obtainStyledAttributes(as, new int[] { android.R.attr.entries });
21 | mEntries = ta.getTextArray(0);
22 | ta.recycle();
23 | }
24 |
25 | public final CharSequence[] getEntries() { return mEntries; }
26 | public final void setEntries(final CharSequence[] cs) { mEntries = cs; }
27 |
28 | @Override
29 | public final void onClick(final DialogInterface di, final int pos, final boolean check)
30 | {
31 | final int flag = 1 << pos;
32 | mNewValue = check ? (mNewValue |= flag) : (mNewValue &= ~flag);
33 | }
34 |
35 | @Override
36 | public final void onClick(final DialogInterface di, final int pos)
37 | {
38 | if (pos == DialogInterface.BUTTON_POSITIVE) persistInt(mNewValue);
39 | }
40 |
41 | @Override
42 | protected final void onPrepareDialogBuilder(final Builder b)
43 | {
44 | super.onPrepareDialogBuilder(b);
45 | try { mNewValue = getPersistedInt(0); }
46 | catch (final Exception ex) { mNewValue = 0; }
47 | b.setMultiChoiceItems(mEntries, getSelectedItems(), this);
48 | }
49 |
50 | private final boolean[] getSelectedItems()
51 | {
52 | final boolean[] res = new boolean[mEntries.length];
53 | int v = mNewValue;
54 | for (int i = 0; i < res.length; ++i)
55 | {
56 | res[i] = (v & 1) == 1;
57 | v >>= 1;
58 | }
59 | return res;
60 | }
61 |
62 | @Override
63 | protected final void onSetInitialValue(final boolean restore, final Object def) { }
64 |
65 | @Override
66 | protected final Object onGetDefaultValue(final TypedArray ta, final int i)
67 | {
68 | return ta.getInt(i, 0);
69 | }
70 | }
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/prf/ValueListPreference.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.prf;
2 |
3 | import android.app.AlertDialog.Builder;
4 | import android.content.*;
5 | import android.content.DialogInterface.OnClickListener;
6 | import android.preference.ListPreference;
7 | import android.util.AttributeSet;
8 |
9 | public final class ValueListPreference extends ListPreference
10 | {
11 | public ValueListPreference(final Context c)
12 | {
13 | super(c);
14 | }
15 |
16 | public ValueListPreference(final Context c, final AttributeSet as)
17 | {
18 | super(c, as);
19 | }
20 |
21 | @Override
22 | protected final void onPrepareDialogBuilder(final Builder b)
23 | {
24 | super.onPrepareDialogBuilder(b);
25 | final String s = getPersistedString("");
26 | int ix = 0;
27 | for (int i = getEntryValues().length - 1; i >= 0; --i)
28 | if (s.equals(getEntryValues()[i]))
29 | {
30 | ix = i;
31 | break;
32 | }
33 | b.setSingleChoiceItems(getEntries(), ix, new OnClickListener()
34 | {
35 | @Override
36 | public final void onClick(final DialogInterface di, final int pos)
37 | {
38 | if (shouldPersist()) persistString(getEntryValues()[pos].toString());
39 | di.dismiss();
40 | }
41 | });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/ui/ActionDialog.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.ui;
2 |
3 | import java.util.*;
4 |
5 | import android.annotation.SuppressLint;
6 | import android.content.*;
7 | import android.content.DialogInterface.OnClickListener;
8 | import android.content.DialogInterface.OnShowListener;
9 | import android.content.pm.*;
10 | import android.os.Build;
11 | import android.support.v7.app.AlertDialog;
12 | import android.support.v7.widget.SearchView;
13 | import android.view.*;
14 | import android.widget.*;
15 | import android.widget.AdapterView.OnItemClickListener;
16 | import xeed.library.common.AppInfo;
17 | import xeed.library.common.Utils;
18 | import xeed.library.ui.AppDialog;
19 | import xeed.library.ui.BaseSettings;
20 | import xeed.library.ui.FilteredAdapter;
21 | import xeed.library.view.AppListView;
22 | import xeed.xposed.cbppmod.*;
23 |
24 | public final class ActionDialog
25 | {
26 | private final ChainEditFragment cef;
27 | private final Action a;
28 | private final int th;
29 |
30 | public ActionDialog(final ChainEditFragment editor, final Action act, final int theme) { cef = editor; a = act; th = theme; }
31 |
32 | public final void show() { createDialog(-2); }
33 |
34 | private final void createAppDialog(final int type)
35 | {
36 | final Intent in = new Intent(type == 2 ? Intent.ACTION_CREATE_SHORTCUT : Intent.ACTION_MAIN);
37 | if (type == 0) in.addCategory(Intent.CATEGORY_LAUNCHER);
38 | AppDialog.create(cef.getActivity(), new AppDialog.AppInfoCollector()
39 | {
40 | @Override
41 | public final ArrayList> collectAsync(final PackageManager pm, final AppDialog.ProgressListener task)
42 | {
43 | final ArrayList> res = new ArrayList>();
44 | final ArrayList ris = new ArrayList();
45 | final List pkgs = pm.getInstalledPackages(0);
46 | task.postProgress(0, pkgs.size());
47 | for (int i = 0; i < pkgs.size(); ++i)
48 | {
49 | in.setPackage(pkgs.get(i).packageName);
50 | final List activityList = pm.queryIntentActivities(in, 0);
51 | for (final ResolveInfo ri : activityList) ris.add(ri);
52 | task.postProgress(1, i + 1);
53 | }
54 | in.setPackage(null);
55 | task.postProgress(0, ris.size());
56 | Collections.sort(ris, new ResolveInfo.DisplayNameComparator(pm));
57 | for (int i = 0; i < ris.size(); ++i)
58 | {
59 | final ResolveInfo ri = ris.get(i);
60 | AppInfo ai = new AppInfo(ri);
61 | ai.label = ri.loadLabel(pm).toString();
62 | ai.icon = ri.loadIcon(pm);
63 | ai.desc = ri.activityInfo.name;
64 | res.add(ai);
65 | task.postProgress(1, i + 1);
66 | }
67 | return res;
68 | }
69 | }, new AppDialog.AppInfoListener()
70 | {
71 | @Override
72 | public final void onDialogResult(final AppInfo ai)
73 | {
74 | if (type == 2)
75 | {
76 | in.setComponent(new ComponentName(ai.data.activityInfo.packageName, ai.data.activityInfo.name));
77 | cef.getActivity().startActivityForResult(in, PBMain.REQ_SHCUT);
78 | }
79 | else
80 | {
81 | in.setComponent(new ComponentName(ai.data.activityInfo.packageName, ai.data.activityInfo.name));
82 | change(Action.ACTION_OTHER, 0, ai.label + Action.OTHER_SPLT + in.toUri(0));
83 | }
84 | }
85 | }, th).show();
86 | }
87 |
88 | private final void createEditDialog(final int title, final View v, final EditFinishedListener l)
89 | {
90 | final AlertDialog.Builder b = new AlertDialog.Builder(cef.getContext(), th);
91 | b.setNegativeButton(R.string.diag_cancel, null);
92 | b.setPositiveButton(R.string.diag_ok, null);
93 | b.setTitle(title);
94 | b.setView(v);
95 | final AlertDialog ad = b.create();
96 | ad.setOnShowListener(new DialogInterface.OnShowListener()
97 | {
98 | @Override
99 | public final void onShow(final DialogInterface di)
100 | {
101 | l.setDialogInterface(di);
102 | final Button b = ad.getButton(AlertDialog.BUTTON_POSITIVE);
103 | b.setOnClickListener(l);
104 | }
105 | });
106 | ad.show();
107 | }
108 |
109 | private static abstract class EditFinishedListener implements View.OnClickListener
110 | {
111 | private DialogInterface di = null;
112 |
113 | @Override
114 | public final void onClick(final View v)
115 | {
116 | onClick(di);
117 | }
118 |
119 | public abstract void onClick(final DialogInterface di);
120 |
121 | public final void setDialogInterface(final DialogInterface diag) { di = diag; }
122 | }
123 |
124 | @SuppressLint("InflateParams")
125 | private final void createDialog(final int type)
126 | {
127 | final AlertDialog.Builder b = new AlertDialog.Builder(cef.getContext(), th);
128 | b.setTitle(R.string.diag_sel_act);
129 | if (type == -2)
130 | {
131 | b.setSingleChoiceItems(R.array.action_k, a.type + 1, new OnClickListener()
132 | {
133 | @Override
134 | public final void onClick(final DialogInterface di, final int i)
135 | {
136 | di.dismiss();
137 | if (i == 0) change(Action.ACTION_NONE, -1, null);
138 | else createDialog(i - 1);
139 | }
140 | });
141 | }
142 | else if (type == Action.ACTION_MEDIA)
143 | {
144 | int i = -1;
145 | if (a.type == Action.ACTION_MEDIA)
146 | {
147 | for (i = 0; i < Action.MEDIA.length; ++i)
148 | if (a.ex_i == Action.MEDIA[i])
149 | break;
150 | }
151 | b.setSingleChoiceItems(R.array.action_media_k, i, new OnClickListener()
152 | {
153 | @Override
154 | public final void onClick(final DialogInterface di, final int i)
155 | {
156 | di.dismiss();
157 | change(Action.ACTION_MEDIA, Action.MEDIA[i], null);
158 | }
159 | });
160 | }
161 | else if (type == Action.ACTION_KEY)
162 | {
163 | KeyListAdapter.inst.mSelected = a.type == Action.ACTION_KEY ? a.ex_i : -1;
164 | final View v = LayoutInflater.from(cef.getContext()).inflate(R.layout.srchdialog, null, false);
165 | v.findViewById(android.R.id.progress).setVisibility(View.GONE);
166 | final ListView lv = (ListView)v.findViewById(android.R.id.list);
167 | lv.setAdapter(KeyListAdapter.inst);
168 | lv.setSelection(KeyListAdapter.inst.mSelected);
169 | lv.setVisibility(View.VISIBLE);
170 | KeyListAdapter.inst.registerView((SearchView)v.findViewById(R.id.search));
171 | b.setView(v);
172 | }
173 | else if (type == Action.ACTION_CODED)
174 | {
175 | b.setSingleChoiceItems(R.array.action_coded_k, a.type == Action.ACTION_CODED ? a.ex_i : -1, new OnClickListener()
176 | {
177 | @Override
178 | public final void onClick(final DialogInterface di, final int i)
179 | {
180 | if (i == Action.CODED_PAPP && Build.VERSION.SDK_INT < 11) Toast.makeText(cef.getContext(), cef.getString(R.string.diag_and_req, "11 (Honeycomb)"), Toast.LENGTH_LONG).show();
181 | else if (i == Action.CODED_KFGD)
182 | {
183 | di.dismiss();
184 | final LinearLayout ll = new LinearLayout(cef.getContext());
185 | ll.setOrientation(LinearLayout.VERTICAL);
186 | final AppListView alv = new AppListView(cef.getContext());
187 | ll.addView(alv);
188 | final Button btn = new Button(cef.getContext());
189 | btn.setText(R.string.btn_add_new);
190 | btn.setOnClickListener(new View.OnClickListener()
191 | {
192 | @Override
193 | public final void onClick(final View v)
194 | {
195 | AppDialog.create(cef.getContext(), new AppDialog.AppInfoCollector()
196 | {
197 | @Override
198 | public final ArrayList> collectAsync(final PackageManager pm, final AppDialog.ProgressListener task)
199 | {
200 | final List pkgs = pm.getInstalledApplications(0);
201 | final ArrayList> res = new ArrayList>(pkgs.size());
202 | task.postProgress(0, pkgs.size());
203 | for (int i = 0; i < pkgs.size(); ++i)
204 | {
205 | final ApplicationInfo appi = pkgs.get(i);
206 | final AppInfo ai = new AppInfo(appi.packageName);
207 | ai.icon = appi.loadIcon(pm);
208 | ai.label = appi.loadLabel(pm).toString();
209 | res.add(ai);
210 | task.postProgress(1, i + 1);
211 | }
212 | return res;
213 | }
214 | }, new AppDialog.AppInfoListener()
215 | {
216 | @Override
217 | public final void onDialogResult(final AppInfo ai)
218 | {
219 | alv.addItem(ai);
220 | }
221 | }, BaseSettings.getDiagTh()).show();
222 | }
223 | });
224 | ll.addView(btn);
225 | alv.setData(Utils.deserialize(a.type == Action.ACTION_CODED && a.ex_i == Action.CODED_KFGD ? a.ex_s : ""));
226 | createEditDialog(R.string.diag_kill_opt, ll, new EditFinishedListener()
227 | {
228 | @Override
229 | public final void onClick(final DialogInterface di)
230 | {
231 | change(Action.ACTION_CODED, Action.CODED_KFGD, Utils.serialize(alv.getData()));
232 | di.dismiss();
233 | }
234 | });
235 | }
236 | else
237 | {
238 | di.dismiss();
239 | change(Action.ACTION_CODED, i, null);
240 | }
241 | }
242 | });
243 | }
244 | else if (type == Action.ACTION_OTHER)
245 | {
246 | b.setSingleChoiceItems(R.array.action_other_k, a.type == Action.ACTION_OTHER ? a.ex_i : -1, new OnClickListener()
247 | {
248 | @Override
249 | public final void onClick(final DialogInterface di, final int i)
250 | {
251 | di.dismiss();
252 | if (i < 3) createAppDialog(i);
253 | else
254 | {
255 | final EditText et = (EditText)View.inflate(cef.getContext(), R.layout.itneditor, null);
256 | if (a.type == Action.ACTION_OTHER) et.setText(a.getOtherIntent());
257 | createEditDialog(R.string.diag_edt_itn, et, new EditFinishedListener()
258 | {
259 | @Override
260 | public final void onClick(final DialogInterface di)
261 | {
262 | try
263 | {
264 | final Intent i = Intent.parseUri(et.getText().toString(), 0);
265 | change(Action.ACTION_OTHER, 3, "URI" + Action.OTHER_SPLT + i.toUri(0));
266 | di.dismiss();
267 | }
268 | catch (final Exception ex)
269 | {
270 | Toast.makeText(cef.getContext(), R.string.diag_itn_err, Toast.LENGTH_LONG).show();
271 | }
272 | }
273 | });
274 | }
275 | }
276 | });
277 | }
278 | b.setNegativeButton(R.string.diag_cancel, null);
279 | final AlertDialog ad = b.create();
280 | if (type == Action.ACTION_KEY)
281 | {
282 | ad.setOnShowListener(new OnShowListener()
283 | {
284 | @Override
285 | public final void onShow(final DialogInterface di)
286 | {
287 | ((ListView)ad.findViewById(android.R.id.list)).setOnItemClickListener(new OnItemClickListener()
288 | {
289 | @Override
290 | public final void onItemClick(final AdapterView> av, final View v, final int i, final long id)
291 | {
292 | di.dismiss();
293 | final CheckBox cb = new CheckBox(cef.getContext());
294 | cb.setChecked(a.type == Action.ACTION_KEY && a.isKeyLong());
295 | cb.setText(R.string.diag_prs_lng);
296 | createEditDialog(R.string.diag_prs_opt, cb, new EditFinishedListener()
297 | {
298 | @Override
299 | public final void onClick(final DialogInterface di)
300 | {
301 | change(Action.ACTION_KEY, (int)id, cb.isChecked() ? "long" : "");
302 | di.dismiss();
303 | }
304 | });
305 | }
306 | });
307 | }
308 | });
309 | }
310 | ad.show();
311 | }
312 |
313 | private final void change(final int type, final int ex_i, final String ex_s)
314 | {
315 | a.type = type;
316 | a.ex_i = ex_i;
317 | a.ex_s = ex_s;
318 | cef.actionChanged();
319 | }
320 |
321 | private static final class KeyListAdapter extends FilteredAdapter implements Comparator
322 | {
323 | static final KeyListAdapter inst = new KeyListAdapter();
324 |
325 | public int mSelected;
326 |
327 | private KeyListAdapter()
328 | {
329 | mData.ensureCapacity(PBMain.keyDb.size());
330 | for (int i = PBMain.keyDb.size() - 1; i >= 0; --i)
331 | mData.add(PBMain.keyDb.keyAt(i));
332 | Collections.sort(mData, this);
333 | getFilter().filter("");
334 | }
335 |
336 | protected final String getItemDescLower(final Integer item)
337 | {
338 | return PBMain.key(item).toLowerCase(Locale.getDefault());
339 | }
340 |
341 | protected final boolean isDataReady() { return true; }
342 |
343 | @Override
344 | public final long getItemId(final int pos)
345 | {
346 | return mFiltered.get(pos);
347 | }
348 |
349 | @Override
350 | public final View getView(int pos, View v, ViewGroup vg)
351 | {
352 | if (v == null)
353 | {
354 | final LayoutInflater li = LayoutInflater.from(vg.getContext());
355 | v = li.inflate(android.R.layout.simple_list_item_single_choice, vg, false);
356 | }
357 | final CheckedTextView ctv = (CheckedTextView)v;
358 | final int key = mFiltered.get(pos);
359 | ctv.setText(PBMain.keyDb.get(key) + " (" + key + ")");
360 | ctv.setChecked(key == mSelected);
361 | return v;
362 | }
363 |
364 | @Override
365 | public final int compare(final Integer lhs, final Integer rhs)
366 | {
367 | return PBMain.key(lhs).compareTo(PBMain.key(rhs));
368 | }
369 | }
370 | }
371 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/ui/ChainEditFragment.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.ui;
2 |
3 | import java.util.ListIterator;
4 |
5 | import android.content.*;
6 | import android.content.DialogInterface.*;
7 | import android.os.Bundle;
8 | import android.support.v4.app.Fragment;
9 | import android.support.v7.app.AlertDialog;
10 | import android.view.*;
11 | import android.view.View.OnClickListener;
12 | import android.view.View.OnFocusChangeListener;
13 | import android.widget.*;
14 | import android.widget.CompoundButton.OnCheckedChangeListener;
15 | import android.widget.SeekBar.OnSeekBarChangeListener;
16 | import xeed.library.ui.BaseSettings;
17 | import xeed.library.ui.SimpleDialog;
18 | import xeed.xposed.cbppmod.*;
19 |
20 | public final class ChainEditFragment extends Fragment implements OnFocusChangeListener, OnCheckedChangeListener, OnClickListener, OnSeekBarChangeListener
21 | {
22 | private PBMain pb = null;
23 | private PagerAdapter pa = null;
24 | private AlertDialog d = null;
25 | private BroadcastReceiver br = null;
26 | private int lk = -1;
27 | private boolean layout = true;
28 |
29 | public final void onCreate(final Bundle b)
30 | {
31 | super.onCreate(b);
32 | pb = (PBMain)getActivity();
33 | pa = pb.getPager();
34 | setRetainInstance(true);
35 | br = new BroadcastReceiver()
36 | {
37 | @Override
38 | public final void onReceive(final Context c, final Intent i)
39 | {
40 | lk = i.getIntExtra("xeed.xposed.cbppmod.Key", -1);
41 | if (lk != -1 && d != null)
42 | ((EditText)d.findViewById(R.id.key)).setText(PBMain.key(lk));
43 | }
44 | };
45 | pb.registerReceiver(br, new IntentFilter("xeed.xposed.cbppmod.Key"), null, null);
46 | }
47 |
48 | @Override
49 | public final void onDestroy()
50 | {
51 | try { pb.unregisterReceiver(br); }
52 | catch (final Exception ex) { }
53 | super.onDestroy();
54 | }
55 |
56 | @Override
57 | public final View onCreateView(final LayoutInflater li, final ViewGroup vg, final Bundle b)
58 | {
59 | layout = true;
60 | final ViewGroup ret = (ViewGroup)li.inflate(R.layout.editor, vg, false);
61 | PBMain.populateKeys((ViewGroup)ret.findViewById(R.id.keys), li, pa.edit, this);
62 | ret.findViewById(R.id.ch_nm).setOnFocusChangeListener(this);
63 | Button bt = (Button)ret.findViewById(R.id.ch_act);
64 | bt.setText(PBMain.action(pa.edit.act));
65 | bt.setOnClickListener(this);
66 | bt = (Button)ret.findViewById(R.id.ch_md);
67 | bt.setText(pb.btnTxt(R.array.md_items, pa.edit.md));
68 | bt.setOnClickListener(this);
69 | bt.setTag(Boolean.TRUE);
70 | bt = (Button)ret.findViewById(R.id.ch_au);
71 | bt.setText(pb.btnTxt(R.array.au_items, pa.edit.au));
72 | bt.setOnClickListener(this);
73 | bt.setTag(Boolean.TRUE);
74 | bt = (Button)ret.findViewById(R.id.ch_pl);
75 | bt.setText(pb.music(pa.edit.pl));
76 | bt.setOnClickListener(this);
77 | bt.setTag(Boolean.TRUE);
78 | bt = (Button)ret.findViewById(R.id.ch_tel);
79 | bt.setText(pb.btnTxt(R.array.tel_items, pa.edit.tel));
80 | bt.setOnClickListener(this);
81 | bt.setTag(Boolean.TRUE);
82 | bt = (Button)ret.findViewById(R.id.ch_not);
83 | bt.setText(pb.notify(pa.edit.not));
84 | bt.setOnClickListener(this);
85 | bt.setTag(Boolean.TRUE);
86 | ((Button)ret.findViewById(R.id.ch_adv_cnv)).setOnClickListener(this);
87 | ((CheckBox)ret.findViewById(R.id.ch_ccl)).setOnCheckedChangeListener(this);
88 | ((CheckBox)ret.findViewById(R.id.ch_rep_md)).setOnCheckedChangeListener(this);
89 | ((CheckBox)ret.findViewById(R.id.ch_scr)).setOnCheckedChangeListener(this);
90 | ((SeekBar)ret.findViewById(R.id.ch_rep)).setOnSeekBarChangeListener(this);
91 | ((SeekBar)ret.findViewById(R.id.ch_vib)).setOnSeekBarChangeListener(this);
92 | layout = false;
93 | return ret;
94 | }
95 |
96 | public final void actionChanged()
97 | {
98 | ((Button)getView().findViewById(R.id.ch_act)).setText(PBMain.action(pa.edit.act));
99 | onChange(false);
100 | }
101 |
102 | private final void showMultiDialog(final Button src, final int title, final int arr, int val)
103 | {
104 | final AlertDialog.Builder b = new AlertDialog.Builder(pb, BaseSettings.getDiagTh());
105 | b.setTitle(title);
106 | final boolean[] data = new boolean[3];
107 | for (int i = 0; i < 3; ++i)
108 | {
109 | data[i] = (val & 1) == 1;
110 | val >>= 1;
111 | }
112 | b.setPositiveButton(R.string.diag_ok, new DialogInterface.OnClickListener()
113 | {
114 | @Override
115 | public final void onClick(final DialogInterface di, final int pos)
116 | {
117 | int x = 0;
118 | for (int i = 2; i >= 0; --i)
119 | x = (x << 1) | (data[i] ? 1 : 0);
120 | if (src.getId() == R.id.ch_md)
121 | {
122 | pa.edit.md = x;
123 | src.setText(pb.btnTxt(R.array.md_items, pa.edit.md));
124 | }
125 | else if (src.getId() == R.id.ch_au)
126 | {
127 | pa.edit.au = x;
128 | src.setText(pb.btnTxt(R.array.au_items, pa.edit.au));
129 | }
130 | else if (src.getId() == R.id.ch_pl)
131 | {
132 | pa.edit.pl = x;
133 | src.setText(pb.music(pa.edit.pl));
134 | }
135 | else if (src.getId() == R.id.ch_tel)
136 | {
137 | pa.edit.tel = x;
138 | src.setText(pb.btnTxt(R.array.tel_items, pa.edit.tel));
139 | }
140 | else if (src.getId() == R.id.ch_not)
141 | {
142 | pa.edit.not = x;
143 | src.setText(pb.notify(pa.edit.not));
144 | }
145 | onChange(false);
146 | }
147 | });
148 | b.setNegativeButton(R.string.diag_cancel, null);
149 | b.setMultiChoiceItems(arr, data, new OnMultiChoiceClickListener()
150 | {
151 | @Override
152 | public final void onClick(final DialogInterface di, final int pos, final boolean f)
153 | {
154 | data[pos] = f;
155 | }
156 | });
157 | b.create().show();
158 | }
159 |
160 | @Override
161 | public final void onClick(final View v)
162 | {
163 | if (v.getId() == R.id.ch_act)
164 | new ActionDialog(this, pa.edit.act, BaseSettings.getDiagTh()).show();
165 | else if (v.getTag() == Boolean.TRUE)
166 | {
167 | final int title, arr, val;
168 | if (v.getId() == R.id.ch_md)
169 | {
170 | title = R.string.diag_md;
171 | arr = R.array.md_items;
172 | val = pa.edit.md;
173 | }
174 | else if (v.getId() == R.id.ch_au)
175 | {
176 | title = R.string.diag_au;
177 | arr = R.array.au_items;
178 | val = pa.edit.au;
179 | }
180 | else if (v.getId() == R.id.ch_pl)
181 | {
182 | title = R.string.diag_pl;
183 | arr = R.array.pl_items;
184 | val = pa.edit.pl;
185 | }
186 | else if (v.getId() == R.id.ch_tel)
187 | {
188 | title = R.string.diag_tel;
189 | arr = R.array.tel_items;
190 | val = pa.edit.tel;
191 | }
192 | else
193 | {
194 | title = R.string.diag_not;
195 | arr = R.array.not_items;
196 | val = pa.edit.not;
197 | }
198 | showMultiDialog((Button)v, title, arr, val);
199 | }
200 | else if (v.getId() == R.id.add_key) keyDialog(new Key(0, false, 0), 1);
201 | else if (v.getId() == R.id.ch_ez)
202 | {
203 | final AlertDialog.Builder b = new AlertDialog.Builder(pb, BaseSettings.getDiagTh());
204 | b.setSingleChoiceItems(R.array.ez_types, pa.edit.getEz(), new DialogInterface.OnClickListener()
205 | {
206 | @Override
207 | public final void onClick(final DialogInterface di, final int i)
208 | {
209 | keyDialog(pa.edit.ks.getLast(), i + 2);
210 | di.dismiss();
211 | }
212 | });
213 | b.setNegativeButton(R.string.diag_cancel, null);
214 | b.create().show();
215 | }
216 | else if (v.getId() == R.id.ch_adv_cnv)
217 | {
218 | pa.edit.setEz(-1, -1, -1);
219 | v.setVisibility(View.GONE);
220 | PBMain.populateKeys((ViewGroup)getView().findViewById(R.id.keys), LayoutInflater.from(pb), pa.edit, ChainEditFragment.this);
221 | onChange(true);
222 | }
223 | else if (v.getTag() != null) keyDialog((Key)v.getTag(), 0);
224 | if (v.getId() != R.id.ch_nm) onFocusChange(getView().findViewById(R.id.ch_nm), false);
225 | }
226 |
227 | private final void keyDialog(final Key k, final int type)
228 | {
229 | final AlertDialog.Builder b = new AlertDialog.Builder(pb, BaseSettings.getDiagTh());
230 | b.setView(R.layout.keyeditor);
231 | b.setPositiveButton(R.string.diag_ok, new DialogInterface.OnClickListener()
232 | {
233 | @Override
234 | public final void onClick(final DialogInterface di, final int i)
235 | {
236 | final int dl = ((SeekBar)d.findViewById(R.id.key_dl)).getProgress() * 50;
237 | if (type < 2 || PBMain.isKeySafe(lk)) updateKey(dl, k, type);
238 | else SimpleDialog.create(pb, BaseSettings.getDiagTh(), R.string.diag_yes, R.string.diag_no, R.string.diag_cnf_t, R.string.diag_cnf_dng, new DialogInterface.OnClickListener()
239 | {
240 | @Override
241 | public final void onClick(final DialogInterface di, final int i)
242 | {
243 | updateKey(dl, k, type);
244 | }
245 | }).show();
246 | }
247 | });
248 | b.setNegativeButton(R.string.diag_cancel, null);
249 | if (type == 0)
250 | b.setNeutralButton(R.string.diag_rmv, new DialogInterface.OnClickListener()
251 | {
252 | @Override
253 | public final void onClick(final DialogInterface di, final int i)
254 | {
255 | pa.edit.ks.remove(k);
256 | PBMain.populateKeys((ViewGroup)getView().findViewById(R.id.keys), LayoutInflater.from(pb), pa.edit, ChainEditFragment.this);
257 | onChange(false);
258 | }
259 | });
260 | d = b.create();
261 | d.setOnShowListener(new OnShowListener()
262 | {
263 | @Override
264 | public final void onShow(final DialogInterface di)
265 | {
266 | d.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
267 | ((EditText)d.findViewById(R.id.key)).setText(PBMain.key(lk = k.code));
268 | final CheckBox cb = (CheckBox)d.findViewById(R.id.key_dn);
269 | if (type > 1) cb.setVisibility(View.GONE);
270 | else cb.setChecked(k.dn);
271 | ((SeekBar)d.findViewById(R.id.key_dl)).setProgress(k.dl / 50);
272 | final ToggleButton tb = (ToggleButton)d.findViewById(R.id.tgl_itc);
273 | tb.setChecked(false);
274 | tb.setOnCheckedChangeListener(new OnCheckedChangeListener()
275 | {
276 | @Override
277 | public final void onCheckedChanged(final CompoundButton cb, final boolean f)
278 | {
279 | pb.requestIntercept(f);
280 | }
281 | });
282 | }
283 | });
284 | d.setOnDismissListener(new OnDismissListener()
285 | {
286 | @Override
287 | public final void onDismiss(final DialogInterface di)
288 | {
289 | d = null;
290 | pb.requestIntercept(false);
291 | }
292 | });
293 | d.show();
294 | }
295 |
296 | private final void updateKey(final int dl, final Key k, final int type)
297 | {
298 | if (type > 1)
299 | {
300 | pa.edit.setEz(type - 2, lk, dl);
301 | }
302 | else
303 | {
304 | k.code = lk;
305 | k.dn = ((CheckBox)d.findViewById(R.id.key_dn)).isChecked();
306 | k.dl = dl;
307 | if (type == 1) pa.edit.ks.add(k);
308 | }
309 | PBMain.populateKeys((ViewGroup)getView().findViewById(R.id.keys), LayoutInflater.from(pb), pa.edit, ChainEditFragment.this);
310 | onChange(false);
311 | }
312 |
313 | public final void updateEdit()
314 | {
315 | if (pb == null) return;
316 | layout = true;
317 | final ViewGroup vg = (ViewGroup)getView();
318 | if (vg == null) return;
319 | ((AutoCompleteTextView)vg.findViewById(R.id.ch_nm)).setText(pa.edit.nm);
320 | PBMain.populateKeys((ViewGroup)vg.findViewById(R.id.keys), LayoutInflater.from(pb), pa.edit, ChainEditFragment.this);
321 | ((Button)vg.findViewById(R.id.ch_act)).setText(PBMain.action(pa.edit.act));
322 | ((Button)vg.findViewById(R.id.ch_md)).setText(pb.btnTxt(R.array.md_items, pa.edit.md));
323 | ((Button)vg.findViewById(R.id.ch_au)).setText(pb.btnTxt(R.array.au_items, pa.edit.au));
324 | ((Button)vg.findViewById(R.id.ch_pl)).setText(pb.music(pa.edit.pl));
325 | ((Button)vg.findViewById(R.id.ch_tel)).setText(pb.btnTxt(R.array.tel_items, pa.edit.tel));
326 | ((Button)vg.findViewById(R.id.ch_not)).setText(pb.notify(pa.edit.not));
327 | ((Button)vg.findViewById(R.id.ch_adv_cnv)).setVisibility(pa.edit.isEz() ? View.VISIBLE : View.GONE);
328 | ((CheckBox)vg.findViewById(R.id.ch_ccl)).setChecked(pa.edit.ccl);
329 | ((CheckBox)vg.findViewById(R.id.ch_scr)).setChecked(pa.edit.scr);
330 | ((CheckBox)vg.findViewById(R.id.ch_rep_md)).setChecked(pa.edit.rep == -1);
331 | final SeekBar sb = (SeekBar)vg.findViewById(R.id.ch_rep);
332 | sb.setProgress(pa.edit.rep == -1 ? 0 : pa.edit.rep);
333 | sb.setVisibility(pa.edit.rep == -1 ? View.GONE : View.VISIBLE);
334 | ((SeekBar)vg.findViewById(R.id.ch_vib)).setProgress(pa.edit.vib / 10);
335 | layout = false;
336 | }
337 |
338 | @Override
339 | public final void onFocusChange(final View v, final boolean f)
340 | {
341 | final TextView tv = (TextView)v;
342 | if (!f && !pa.edit.nm.equals(tv.getText().toString()))
343 | {
344 | final String nnm = tv.getText().toString();
345 | final ListIterator li = pa.getIterator();
346 | while (li.hasNext())
347 | {
348 | final Chain lch = li.next();
349 | if (lch.nm.equals(nnm))
350 | {
351 | tv.setText(pa.edit.nm);
352 | Toast.makeText(getContext(), R.string.diag_nm_exs, Toast.LENGTH_LONG).show();
353 | return;
354 | }
355 | }
356 | pa.edit.nm = nnm;
357 | onChange(true);
358 | }
359 | }
360 |
361 | @Override
362 | public final void onCheckedChanged(final CompoundButton cb, final boolean c)
363 | {
364 | if (cb.getId() == R.id.ch_ccl) pa.edit.ccl = c;
365 | else if (cb.getId() == R.id.ch_scr) pa.edit.scr = c;
366 | else if (cb.getId() == R.id.ch_rep_md)
367 | {
368 | getView().findViewById(R.id.ch_rep).setVisibility(c ? View.GONE : View.VISIBLE);
369 | pa.edit.rep = c ? -1 : 0;
370 | onChange(false);
371 | }
372 | onChange(false);
373 | }
374 |
375 | @Override
376 | public final void onProgressChanged(final SeekBar sb, final int v, final boolean u)
377 | {
378 | if (sb.getId() == R.id.ch_rep) pa.edit.rep = v;
379 | else pa.edit.vib = v * 10;
380 | onChange(false);
381 | }
382 |
383 | private final void onChange(final boolean big)
384 | {
385 | if (!layout) pa.chainChanged(big);
386 | }
387 |
388 | @Override
389 | public final void onStartTrackingTouch(final SeekBar seekBar) { }
390 |
391 | @Override
392 | public final void onStopTrackingTouch(final SeekBar sb) { }
393 | }
394 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/ui/ChainListFragment.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.ui;
2 |
3 | import com.mobeta.android.dslv.DragSortListView;
4 | import com.mobeta.android.dslv.DragSortListView.DragSortListener;
5 |
6 | import android.content.*;
7 | import android.content.DialogInterface.OnDismissListener;
8 | import android.os.Bundle;
9 | import android.support.v4.app.Fragment;
10 | import android.view.*;
11 | import android.widget.*;
12 | import android.widget.AdapterView.OnItemClickListener;
13 | import xeed.library.ui.BaseSettings;
14 | import xeed.library.ui.SimpleDialog;
15 | import xeed.xposed.cbppmod.*;
16 |
17 | public final class ChainListFragment extends Fragment implements DragSortListener, OnItemClickListener
18 | {
19 | private final ChainAdapter ca = new ChainAdapter();
20 | private PBMain pb = null;
21 | private PagerAdapter pa = null;
22 |
23 | @Override
24 | public final void onCreate(final Bundle b)
25 | {
26 | super.onCreate(b);
27 | pb = (PBMain)getActivity();
28 | pa = pb.getPager();
29 | setRetainInstance(true);
30 | }
31 |
32 | @Override
33 | public final View onCreateView(final LayoutInflater li, final ViewGroup vg, final Bundle b)
34 | {
35 | if (pa == null) return null;
36 | if (!pa.getIterator().hasNext() && PBMain.getActiveVerCode() != 0)
37 | {
38 | SimpleDialog.create(getContext(), BaseSettings.getDiagTh(), R.string.diag_yes, R.string.diag_no, R.string.diag_cnf_t, R.string.diag_no_chs, new DialogInterface.OnClickListener()
39 | {
40 | @Override
41 | public void onClick(final DialogInterface di, final int which)
42 | {
43 | Chain ch = new Chain(pb.sp, "Original camera");
44 | ch.act = new Action(Action.ACTION_KEY, KeyEvent.KEYCODE_CAMERA);
45 | ch.vib = 0;
46 | ch.setEz(3, KeyEvent.KEYCODE_CAMERA, 3000);
47 | pa.addChain(ch);
48 |
49 | ch = new Chain(pb.sp, "Play pause");
50 | ch.act = new Action(Action.ACTION_MEDIA, Action.MEDIA_PLAY);
51 | ch.setEz(0, KeyEvent.KEYCODE_CAMERA, 0);
52 | pa.addChain(ch);
53 |
54 | ch = new Chain(pb.sp, "Next track");
55 | ch.act = new Action(Action.ACTION_MEDIA, Action.MEDIA_NEXT);
56 | ch.setEz(3, KeyEvent.KEYCODE_VOLUME_UP, 500);
57 | pa.addChain(ch);
58 |
59 | ch = new Chain(pb.sp, "Original vol-up");
60 | ch.act = new Action(Action.ACTION_KEY, KeyEvent.KEYCODE_VOLUME_UP);
61 | ch.vib = 0;
62 | ch.setEz(0, KeyEvent.KEYCODE_VOLUME_UP, 0);
63 | pa.addChain(ch);
64 |
65 | ch = new Chain(pb.sp, "Previous track");
66 | ch.act = new Action(Action.ACTION_MEDIA, Action.MEDIA_PREV);
67 | ch.setEz(3, KeyEvent.KEYCODE_VOLUME_DOWN, 500);
68 | pa.addChain(ch);
69 |
70 | ch = new Chain(pb.sp, "Original vol-dn");
71 | ch.act = new Action(Action.ACTION_KEY, KeyEvent.KEYCODE_VOLUME_DOWN);
72 | ch.vib = 0;
73 | ch.setEz(0, KeyEvent.KEYCODE_VOLUME_DOWN, 0);
74 | pa.addChain(ch);
75 |
76 | changed(false);
77 | }
78 | }).show();
79 | }
80 | final LinearLayout ll = (LinearLayout)li.inflate(R.layout.chainlist, vg, false);
81 | ((TextView)ll.findViewById(R.id.status)).setText(getString(R.string.diag_sts) + ": " + getString(R.string.diag_sav));
82 | final DragSortListView dlv = (DragSortListView)ll.findViewById(R.id.chainlist);
83 | dlv.setAdapter(ca);
84 | dlv.setDragSortListener(this);
85 | dlv.setOnItemClickListener(this);
86 | return ll;
87 | }
88 |
89 | @Override
90 | public final void onResume()
91 | {
92 | super.onResume();
93 | changed(pa.saved);
94 | }
95 |
96 | @Override
97 | public final void drop(final int from, final int to)
98 | {
99 | if (from != to)
100 | {
101 | final Chain ch = pa.getChains().remove(from);
102 | pa.getChains().add(to, ch);
103 | changed(false);
104 | }
105 | }
106 |
107 | final void changed(final boolean save)
108 | {
109 | pa.saved = save;
110 | ca.notifyDataSetChanged();
111 | final LinearLayout ll = (LinearLayout)getView();
112 | if (ll != null)
113 | {
114 | final TextView tv = (TextView)ll.findViewById(R.id.status);
115 | tv.setText(getString(R.string.diag_sts) + ": " + getString(save ? R.string.diag_sav : R.string.diag_nsav));
116 | tv.setTextColor(save ? 0xff00ff00 : 0xffff0000);
117 | }
118 | }
119 |
120 | private final class ChainAdapter extends BaseAdapter
121 | {
122 | @Override
123 | public final int getCount() { return pa.getChains().size(); }
124 |
125 | @Override
126 | public final Object getItem(int i) { return pa.getChains().get(i); }
127 |
128 | @Override
129 | public final long getItemId(int i) { return pa.getChains().get(i).hashCode(); }
130 |
131 | @Override
132 | public final View getView(final int pos, final View reuse, final ViewGroup vg)
133 | {
134 | final LayoutInflater li = LayoutInflater.from(pb);
135 | final Chain ch = pa.getChains().get(pos);
136 | final LinearLayout ll;
137 | if (reuse != null) ll = (LinearLayout)reuse;
138 | else ll = (LinearLayout)li.inflate(R.layout.chainitem, vg, false);
139 | final ViewGroup keys = (ViewGroup)ll.findViewById(R.id.keys);
140 | PBMain.populateKeys(keys, li, ch, null);
141 | ((TextView)ll.findViewById(R.id.name)).setText(ch.nm);
142 | ((TextView)ll.findViewById(R.id.desc)).setText(chainDesc(ch));
143 | return ll;
144 | }
145 | }
146 |
147 | public final String chainDesc(final Chain ch)
148 | {
149 | String ret = getString(R.string.diag_md) + ": " + pb.btnTxt(R.array.md_items, ch.md);
150 | ret += ", " + getString(R.string.diag_au) + ": " + pb.btnTxt(R.array.au_items, ch.au);
151 | ret += ", " + getString(R.string.diag_pl) + ": " + pb.music(ch.pl);
152 | ret += ", " + getString(R.string.diag_tel) + ": " + pb.btnTxt(R.array.tel_items, ch.tel);
153 | return ret;
154 | }
155 |
156 | @Override
157 | public final void onItemClick(final AdapterView> av, final View v, final int pos, final long id)
158 | {
159 | pa.setEdit(pa.getChains().get(pos));
160 | }
161 |
162 | @Override
163 | public void drag(int from, int to) { }
164 |
165 | @Override
166 | public final void remove(final int pos)
167 | {
168 | SimpleDialog.create(getContext(), BaseSettings.getDiagTh(), R.string.diag_yes, R.string.diag_no, R.string.diag_cnf_t, R.string.diag_cnf_rmv, new DialogInterface.OnClickListener()
169 | {
170 | @Override
171 | public final void onClick(final DialogInterface di, final int i)
172 | {
173 | if (pa.getChains().get(pos) == pa.edit) pa.setEdit(null);
174 | pa.getChains().remove(pos);
175 | changed(false);
176 | }
177 | }, new OnDismissListener()
178 | {
179 | @Override
180 | public final void onDismiss(final DialogInterface di)
181 | {
182 | ca.notifyDataSetChanged();
183 | }
184 | }).show();
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/ui/KeyTestFragment.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.ui;
2 |
3 | import java.util.Iterator;
4 | import java.util.LinkedList;
5 |
6 | import android.content.*;
7 | import android.os.Bundle;
8 | import android.os.SystemClock;
9 | import android.support.v4.app.Fragment;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.View.OnClickListener;
13 | import android.view.ViewGroup;
14 | import android.widget.CompoundButton;
15 | import android.widget.CompoundButton.OnCheckedChangeListener;
16 | import android.widget.ToggleButton;
17 | import xeed.xposed.cbppmod.*;
18 |
19 | public final class KeyTestFragment extends Fragment implements OnCheckedChangeListener, OnClickListener
20 | {
21 | private static final int maxlen = 9;
22 | private static final LinkedList chain = new LinkedList();
23 | private final Chain ch = new Chain(null, "");
24 | private PBMain pb = null;
25 | private BroadcastReceiver br = null;
26 | private ToggleButton tb = null;
27 |
28 | public final void onCreate(final Bundle b)
29 | {
30 | super.onCreate(b);
31 | pb = (PBMain)getActivity();
32 | br = new BroadcastReceiver()
33 | {
34 | @Override
35 | public final void onReceive(final Context c, final Intent i)
36 | {
37 | final int key = i.getIntExtra("xeed.xposed.cbppmod.Key", -1);
38 | if (key != -1)
39 | {
40 | final boolean down = i.getBooleanExtra("xeed.xposed.cbppmod.Down", true);
41 | keyHook(key, down);
42 | keysChanged();
43 | }
44 | }
45 | };
46 | }
47 |
48 | private final void keysChanged()
49 | {
50 | ch.ks.clear();
51 | ch.ks.addAll(chain);
52 | PBMain.populateKeys((ViewGroup)getView().findViewById(R.id.keys), LayoutInflater.from(pb), ch, null);
53 | }
54 |
55 | @Override
56 | public final View onCreateView(final LayoutInflater li, final ViewGroup vg, final Bundle b)
57 | {
58 | final ViewGroup ret = (ViewGroup)li.inflate(R.layout.test, vg, false);
59 | tb = (ToggleButton)ret.findViewById(R.id.tgl_itc);
60 | tb.setOnCheckedChangeListener(this);
61 | ch.ks.clear();
62 | ch.ks.addAll(chain);
63 | PBMain.populateKeys((ViewGroup)ret.findViewById(R.id.keys), li, ch, null);
64 | ret.findViewById(R.id.btn_clr).setOnClickListener(this);
65 | return ret;
66 | }
67 |
68 | private final void keyHook(final int key, final boolean down)
69 | {
70 | final long t = SystemClock.elapsedRealtime();
71 | if (!chain.isEmpty())
72 | {
73 | final Iterator it = chain.descendingIterator();
74 | while (it.hasNext())
75 | {
76 | final Key k = it.next();
77 | if (k.code == key)
78 | {
79 | k.dl = ((int)(t - k.sw) / 50) * 50;
80 | break;
81 | }
82 | }
83 | }
84 | chain.add(new Key(key, down, 0));
85 | while (chain.size() > maxlen) chain.removeFirst();
86 | }
87 |
88 | @Override
89 | public final void setUserVisibleHint(final boolean vis)
90 | {
91 | super.setUserVisibleHint(vis);
92 | if (!vis && pb != null) tb.setChecked(false);
93 | }
94 |
95 | @Override
96 | public final void onPause()
97 | {
98 | tb.setChecked(false);
99 | pb.unregisterReceiver(br);
100 | super.onPause();
101 | }
102 |
103 | @Override
104 | public final void onResume()
105 | {
106 | super.onResume();
107 | pb.registerReceiver(br, new IntentFilter("xeed.xposed.cbppmod.Key"), null, null);
108 | }
109 |
110 | @Override
111 | public final void onCheckedChanged(final CompoundButton cb, final boolean f)
112 | {
113 | pb.requestIntercept(f);
114 | }
115 |
116 | @Override
117 | public final void onClick(final View v)
118 | {
119 | if (v.getId() == R.id.btn_clr)
120 | {
121 | chain.clear();
122 | keysChanged();
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/ui/PagerAdapter.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.ui;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.ListIterator;
6 | import android.annotation.SuppressLint;
7 | import android.content.*;
8 | import android.support.v4.app.*;
9 | import android.support.v4.view.ViewPager;
10 | import xeed.xposed.cbppmod.*;
11 |
12 | public final class PagerAdapter extends FragmentStatePagerAdapter
13 | {
14 | private final ArrayList chs = new ArrayList();
15 | private final ViewPager vp;
16 | private ChainListFragment clf = null;
17 | private ChainEditFragment cef = null;
18 | private KeyTestFragment ktf = null;
19 | public Chain edit;
20 | public boolean saved;
21 |
22 | @SuppressLint("WorldReadableFiles")
23 | @SuppressWarnings("deprecation")
24 | public PagerAdapter(final ViewPager pager, final FragmentManager fm)
25 | {
26 | super(fm);
27 | vp = pager;
28 | final SharedPreferences sp = pager.getContext().getSharedPreferences("pbmcsettings", Context.MODE_WORLD_READABLE);
29 | final int n = sp.getInt("chainlist.count", 0);
30 | for (int i = 0; i < n; ++i)
31 | {
32 | final String name = sp.getString("chainlist." + i, "");
33 | if (name.length() > 0) addChain(new Chain(sp, name));
34 | }
35 | saved = true;
36 | }
37 |
38 | public final List getChains() { return chs; }
39 |
40 | public final ListIterator getIterator() { return chs.listIterator(); }
41 |
42 | public final void addChain(final Chain ch) { chs.add(ch); }
43 |
44 | @Override
45 | public final Fragment getItem(final int i)
46 | {
47 | if (i == 0) return getList();
48 | else if (i == 1) return getTest();
49 | else return getEdit();
50 | }
51 |
52 | public final ChainListFragment getList()
53 | {
54 | return clf == null ? (clf = new ChainListFragment()) : clf;
55 | }
56 |
57 | public final ChainEditFragment getEdit()
58 | {
59 | return cef == null ? (cef = new ChainEditFragment()) : cef;
60 | }
61 |
62 | public final KeyTestFragment getTest()
63 | {
64 | return ktf == null ? (ktf = new KeyTestFragment()) : ktf;
65 | }
66 |
67 | @Override
68 | public final int getCount()
69 | {
70 | return edit == null ? 2 : 3;
71 | }
72 |
73 | @Override
74 | public final String getPageTitle(final int i)
75 | {
76 | if (i == 0) return PBMain.r.getString(R.string.tab_chns);
77 | else if (i == 1) return PBMain.r.getString(R.string.tab_test);
78 | else return PBMain.r.getString(R.string.tab_edit) + " " + edit.nm;
79 | }
80 |
81 | public final void setEdit(final Chain ch)
82 | {
83 | edit = ch;
84 | notifyDataSetChanged();
85 | if (ch != null)
86 | {
87 | getEdit().updateEdit();
88 | vp.setCurrentItem(2);
89 | }
90 | }
91 |
92 | public final void chainsSaved()
93 | {
94 | final Intent i = new Intent("xeed.xposed.cbppmod.Update");
95 | i.putExtra("xeed.xposed.cbppmod.Chains", true);
96 | vp.getContext().sendBroadcast(i);
97 | getList().changed(true);
98 | }
99 |
100 | public final void chainChanged(final boolean big)
101 | {
102 | if (big) notifyDataSetChanged();
103 | getList().changed(false);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/xeed/xposed/cbppmod/viw/CustomListView.java:
--------------------------------------------------------------------------------
1 | package xeed.xposed.cbppmod.viw;
2 |
3 | import com.mobeta.android.dslv.*;
4 |
5 | import android.annotation.SuppressLint;
6 | import android.content.Context;
7 | import android.support.v4.view.GestureDetectorCompat;
8 | import android.view.GestureDetector;
9 | import android.util.AttributeSet;
10 | import android.view.MotionEvent;
11 |
12 | @SuppressLint("ClickableViewAccessibility")
13 | public final class CustomListView extends DragSortListView implements GestureDetector.OnGestureListener
14 | {
15 | private final GestureDetectorCompat gd_i, gd_it;
16 |
17 | public CustomListView(final Context c, final AttributeSet as)
18 | {
19 | super(c, as);
20 | gd_i = new GestureDetectorCompat(c, this);
21 | gd_i.setIsLongpressEnabled(false);
22 | gd_it = new GestureDetectorCompat(c, this);
23 | gd_it.setIsLongpressEnabled(false);
24 | }
25 |
26 | @Override
27 | public final boolean onDown(final MotionEvent e) { return false; }
28 |
29 | @Override
30 | public final void onShowPress(final MotionEvent e) { }
31 |
32 | @Override
33 | public final boolean onSingleTapUp(final MotionEvent e)
34 | {
35 | final int pos = pointToPosition((int)e.getX(), (int)e.getY());
36 | if (pos != INVALID_POSITION && pos >= getHeaderViewsCount() && pos < (getCount() - getFooterViewsCount()))
37 | {
38 | performItemClick(getChildAt(pos), pos, getItemIdAtPosition(pos));
39 | return true;
40 | }
41 | return false;
42 | }
43 |
44 | @Override
45 | public final boolean onTouchEvent(final MotionEvent e)
46 | {
47 | return gd_i.onTouchEvent(e) || super.onTouchEvent(e);
48 | }
49 |
50 | @Override
51 | public final boolean onInterceptTouchEvent(final MotionEvent e)
52 | {
53 | return gd_it.onTouchEvent(e) || super.onInterceptTouchEvent(e);
54 | }
55 |
56 | @Override
57 | public final boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX, final float distanceY) { return false; }
58 |
59 | @Override
60 | public final void onLongPress(final MotionEvent e) { }
61 |
62 | @Override
63 | public final boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY) { return false; }
64 | }
65 |
--------------------------------------------------------------------------------