├── LICENSE ├── README.md ├── build.gradle ├── demo ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── co │ │ └── lemonlabs │ │ └── android │ │ └── slidingdebugmenu │ │ └── demo │ │ ├── DemoActivity.java │ │ ├── DemoModule.java │ │ └── LocaleModule.java │ └── res │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── layout │ └── demo.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images └── image1.png ├── library ├── build.gradle ├── maven_push.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── co │ │ └── lemonlabs │ │ └── android │ │ └── slidingdebugmenu │ │ ├── SlidingDebugMenu.java │ │ ├── SlidingDebugMenuModule.java │ │ ├── controllers │ │ ├── LocationController.java │ │ └── NetworkController.java │ │ ├── modules │ │ ├── BuildModule.java │ │ ├── LocationModule.java │ │ ├── LogModule.java │ │ ├── MenuModule.java │ │ ├── NetworkModule.java │ │ └── events │ │ │ ├── LocationEvent.java │ │ │ └── NetworkChangeEvent.java │ │ ├── receivers │ │ └── NetworkReceiver.java │ │ ├── util │ │ └── Log.java │ │ └── views │ │ ├── ModuleSimpleProperty.java │ │ ├── ModuleSpinnerProperty.java │ │ └── ModuleTitle.java │ └── res │ ├── drawable-xxhdpi │ ├── sdm__ic_battery.png │ ├── sdm__ic_controls.png │ ├── sdm__ic_developer.png │ ├── sdm__ic_info.png │ ├── sdm__ic_locate.png │ ├── sdm__ic_location.png │ ├── sdm__ic_map.png │ ├── sdm__ic_network_bluetooth.png │ ├── sdm__ic_network_connection.png │ ├── sdm__ic_network_wifi.png │ ├── sdm__ic_settings.png │ └── sdm__ic_uninstall.png │ ├── drawable │ ├── sdm__drawer_settings_bg.xml │ ├── sdm__module_button_group_bg.xml │ ├── sdm__module_title_bg.xml │ ├── sdm__spinner_clickable_bg.xml │ └── sdm__transparent_clickable.xml │ ├── layout │ ├── sdm__drawer.xml │ ├── sdm__drawer_settings.xml │ ├── sdm__drawer_title.xml │ ├── sdm__module_location.xml │ ├── sdm__module_network.xml │ ├── sdm__module_property_simple.xml │ ├── sdm__module_property_spinner.xml │ └── sdm__spinner_dropdown_item.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2014 Lemon Labs 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SlidingDebugMenu 2 | ================== 3 | 4 | SlidingDebugMenu is a helper layout for developers that allows easy access to the state of the device and its settings 5 | from anywhere in your application. Use predefined modules or implement your own to suit your development needs! 6 | 7 | ![Example Image][1] 8 | 9 | Default modules 10 | --------------- 11 | 12 | Network module allows switching state of your wifi, mobile networks and bluetooth provided your device 13 | supports them and display their current state. 14 | 15 | Log module controls which level of log should be output, provided you use our Log wrapper class. 16 | 17 | Location module allows to easily retrieve current location and its parameters, access location settings 18 | and show your location in a map. This module uses GooglePlayServices, so it will not work on devices without it. 19 | 20 | Build module provides some basic info about the installed application. 21 | 22 | Including in your project 23 | ------------------------- 24 | 25 | Currently the library is only distributed through Maven central repository. 26 | 27 | Gradle: 28 | 29 | repositories { 30 | mavenCentral() 31 | } 32 | 33 | dependencies { 34 | compile 'co.lemonlabs:slidingdebugmenu:0.1.0' 35 | } 36 | 37 | Maven: 38 | 39 | 40 | co.lemonlabs 41 | slidingdebugmenu 42 | 0.1.0 43 | 44 | 45 | Usage 46 | ----- 47 | 48 | The library supports Android 2.3+ and is currently only compatible with ActionBarCompat. 49 | 50 | To use the default settings simply add this to your Activity's onCreate() 51 | 52 | menu = SlidingDebugMenu.attach(this) 53 | 54 | and add lifecycle callbacks in your onStop() and onStart(). 55 | 56 | @Override 57 | public void onStop() { 58 | menu.onStop(); 59 | super.onStop(); 60 | } 61 | 62 | @Override 63 | public void onStart() { 64 | super.onStart(); 65 | menu.onStart(); 66 | } 67 | 68 | Customization 69 | ------------- 70 | 71 | To create a custom module extend MenuModule class and override getTitle() and getContent() methods. Optionally, 72 | you should override onStart() and onStop() if your module depends on the lifecycle of an Activity, like registering 73 | broadcast receivers, an EventBus, etc. 74 | 75 | To attach a custom module to the debug drawer you can use one of: 76 | 77 | menu = SlidingDebugMenu.attach(this) 78 | menu.addModule(MenuModule module, boolean callOnStart) 79 | menu.addModule(int position, MenuModule module, boolean callOnStart) 80 | 81 | after attaching the drawer to an activity. Modules added this way will not persist after configuration changes or 82 | reinitialization of the menu. 83 | 84 | OR 85 | 86 | Use a static module editor before attaching it to the activity. 87 | 88 | SlidingDebugMenu.edit() 89 | .add(CustomModule.class) 90 | .remove(BuildModule.class) 91 | .commit(); 92 | SlidingDebugMenu.attach(this) 93 | 94 | Using this method will automatically reinitialize every module on reinitialization and they could be shared between 95 | multiple activities. 96 | 97 | NOTE: Reflection is used to instantiate the modules, so currently only empty constructors are allowed. A dependency 98 | injection framework like Dagger would be useful in future releases. 99 | 100 | 101 | See comments and examples for instructions of further customization of the menu. 102 | 103 | Change Log 104 | ---------- 105 | No changes so far 106 | 107 | Dependencies 108 | ------------ 109 | 110 | SlidingDebugMenu depends on 111 | 112 | * [GooglePlayServices][2] 113 | * [Google Guava][8] 114 | * [GreenRobot EventBus][9] 115 | 116 | Acknowledgements 117 | -------------------- 118 | * [jfeinstein10/SlidingMenu][3] for the core layout used in earlier versions of the project 119 | * [This presentation by Jake Wharton][4] for inspiration because we could not wait for his implementation and made our own. 120 | 121 | Developed By 122 | -------------------- 123 | [Lemon Labs][5] - 124 | 125 | License 126 | ----------- 127 | 128 | Copyright 2014 Lemon Labs 129 | 130 | Licensed under the Apache License, Version 2.0 (the "License"); 131 | you may not use this file except in compliance with the License. 132 | You may obtain a copy of the License at 133 | 134 | http://www.apache.org/licenses/LICENSE-2.0 135 | 136 | Unless required by applicable law or agreed to in writing, software 137 | distributed under the License is distributed on an "AS IS" BASIS, 138 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139 | See the License for the specific language governing permissions and 140 | limitations under the License. 141 | 142 | 143 | [Ionicons][6] is licensed under the [MIT license][7]. 144 | 145 | [1]: https://raw.github.com/lemonlabs/slidingdebugmenu/master/images/image1.png 146 | [2]: https://developer.android.com/google/play-services/index.html?hl=lt 147 | [3]: https://github.com/jfeinstein10/SlidingMenu 148 | [4]: https://speakerdeck.com/jakewharton/android-apps-with-dagger 149 | [5]: http://www.lemonlabs.co 150 | [6]: http://ionicons.com/ 151 | [7]: http://opensource.org/licenses/MIT 152 | [8]: https://code.google.com/p/guava-libraries/ 153 | [9]: https://github.com/greenrobot/EventBus 154 | [10]: https://github.com/lemonlabs/slidingdebugmenu/tree/master/aar 155 | ======= 156 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | dependencies { 6 | classpath 'com.android.tools.build:gradle:0.11.+' 7 | } 8 | } 9 | apply plugin: 'android' 10 | 11 | repositories { 12 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } 13 | mavenCentral() 14 | } 15 | 16 | android { 17 | compileSdkVersion 19 18 | buildToolsVersion "19.1.0" 19 | 20 | defaultConfig { 21 | minSdkVersion 9 22 | targetSdkVersion 19 23 | versionCode 1 24 | versionName "1.0" 25 | } 26 | 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_7 29 | targetCompatibility JavaVersion.VERSION_1_7 30 | } 31 | buildTypes { 32 | release { 33 | runProguard false 34 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 35 | } 36 | } 37 | } 38 | 39 | dependencies { 40 | provided 'com.squareup.dagger:dagger-compiler:1.2.1' 41 | compile 'com.squareup.dagger:dagger:1.2.1' 42 | compile 'com.android.support:appcompat-v7:19.1.+' 43 | 44 | compile project(':library') 45 | } 46 | -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /demo/src/main/java/co/lemonlabs/android/slidingdebugmenu/demo/DemoActivity.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.demo; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.v4.widget.DrawerLayout; 6 | import co.lemonlabs.android.slidingdebugmenu.SlidingDebugMenu; 7 | import dagger.ObjectGraph; 8 | 9 | import javax.inject.Inject; 10 | 11 | public class DemoActivity extends Activity { 12 | 13 | @Inject SlidingDebugMenu menu; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.demo); 19 | 20 | ObjectGraph og = ObjectGraph.create(new DemoModule(this)); 21 | og.inject(this); 22 | 23 | // show/hide the settings at the bottom of the drawer 24 | menu.setDrawerSettingsVisible(true); 25 | 26 | DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 27 | drawerLayout.addView(menu); 28 | } 29 | 30 | @Override 31 | public void onStop() { 32 | menu.onStop(); 33 | super.onStop(); 34 | } 35 | 36 | @Override 37 | public void onStart() { 38 | super.onStart(); 39 | menu.onStart(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /demo/src/main/java/co/lemonlabs/android/slidingdebugmenu/demo/DemoModule.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.demo; 2 | 3 | import android.content.Context; 4 | import co.lemonlabs.android.slidingdebugmenu.SlidingDebugMenuModule; 5 | import co.lemonlabs.android.slidingdebugmenu.modules.BuildModule; 6 | import co.lemonlabs.android.slidingdebugmenu.modules.LocationModule; 7 | import co.lemonlabs.android.slidingdebugmenu.modules.LogModule; 8 | import co.lemonlabs.android.slidingdebugmenu.modules.MenuModule; 9 | import co.lemonlabs.android.slidingdebugmenu.modules.NetworkModule; 10 | import dagger.Module; 11 | import dagger.Provides; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | @Module( 17 | includes = { 18 | SlidingDebugMenuModule.class 19 | }, 20 | injects = { 21 | DemoActivity.class 22 | } 23 | ) 24 | public class DemoModule { 25 | 26 | private final Context context; 27 | 28 | public DemoModule(Context context) { 29 | this.context = context; 30 | } 31 | 32 | @Provides Context provideContext() { 33 | return context; 34 | } 35 | 36 | @Provides List provideMenuModules(BuildModule build, LocationModule location, LogModule log, NetworkModule network) { 37 | List modules = new ArrayList<>(); 38 | 39 | // Custom, app specific module 40 | modules.add(new LocaleModule()); 41 | 42 | modules.add(build); 43 | modules.add(location); 44 | modules.add(log); 45 | modules.add(network); 46 | 47 | return modules; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /demo/src/main/java/co/lemonlabs/android/slidingdebugmenu/demo/LocaleModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.demo; 18 | 19 | import android.content.Context; 20 | import android.view.View; 21 | import android.widget.LinearLayout; 22 | import co.lemonlabs.android.slidingdebugmenu.modules.MenuModule; 23 | import co.lemonlabs.android.slidingdebugmenu.views.ModuleSimpleProperty; 24 | 25 | import java.util.Calendar; 26 | import java.util.Locale; 27 | 28 | /** 29 | * Demo custom module 30 | */ 31 | public class LocaleModule extends MenuModule { 32 | 33 | private static final String TITLE = "Locale Information"; 34 | 35 | @Override 36 | public String getTitle() { 37 | return TITLE; 38 | } 39 | 40 | @Override 41 | public View getContent(Context context) { 42 | LinearLayout v = new LinearLayout(context); 43 | v.setOrientation(LinearLayout.VERTICAL); 44 | 45 | Locale defaultLocale = context.getResources().getConfiguration().locale; 46 | 47 | ModuleSimpleProperty locale = new ModuleSimpleProperty(context, "Locale"); 48 | locale.setPropertyValue(defaultLocale.toString()); 49 | v.addView(locale); 50 | 51 | ModuleSimpleProperty date = new ModuleSimpleProperty(context, "Date"); 52 | date.setPropertyValue(Calendar.getInstance(defaultLocale).getTime().toString()); 53 | v.addView(date); 54 | 55 | return v; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/demo/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /demo/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SlidingDebugMenu Demo 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | VERSION_NAME=0.1.0 2 | VERSION_CODE=1 3 | GROUP=co.lemonlabs 4 | 5 | POM_NAME=Sliding Debug Menu 6 | POM_ARTIFACT_ID=slidingdebugmenu 7 | POM_PACKAGING=aar 8 | POM_DESCRIPTION=Android library that eases access to developer settings and device state 9 | POM_URL=https://github.com/lemonlabs/slidingdebugmenu 10 | POM_SCM_URL=https://github.com/lemonlabs/slidingdebugmenu 11 | POM_SCM_CONNECTION=scm:git@github.com:lemonlabs/slidingdebugmenu.git 12 | POM_SCM_DEV_CONNECTION=scm:git@github.com:lemonlabs/slidingdebugmenu.git 13 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 14 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 15 | POM_LICENCE_DIST=repo 16 | POM_DEVELOPER_ID=lemonlabs 17 | POM_DEVELOPER_NAME=Lemon Labs 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jan 14 11:51:52 EET 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/images/image1.png -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | dependencies { 6 | classpath 'com.android.tools.build:gradle:0.11.+' 7 | } 8 | } 9 | apply plugin: 'android-library' 10 | apply plugin: 'maven' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | android { 17 | compileSdkVersion 19 18 | buildToolsVersion "19.1.0" 19 | 20 | defaultConfig { 21 | minSdkVersion 9 22 | targetSdkVersion 19 23 | versionCode 1 24 | versionName "0.1.0" 25 | } 26 | 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_7 29 | targetCompatibility JavaVersion.VERSION_1_7 30 | } 31 | } 32 | 33 | dependencies { 34 | provided 'com.squareup.dagger:dagger-compiler:1.2.1' 35 | compile 'com.squareup.dagger:dagger:1.2.1' 36 | compile 'com.google.android.gms:play-services:4.4.52' 37 | compile 'com.android.support:support-v4:19.1.+' 38 | compile 'com.android.support:appcompat-v7:19.1.+' 39 | compile 'de.greenrobot:eventbus:2.2.+' 40 | } 41 | 42 | apply from: './maven_push.gradle' 43 | -------------------------------------------------------------------------------- /library/maven_push.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Chris Banes 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 | apply plugin: 'maven' 18 | apply plugin: 'signing' 19 | 20 | def isReleaseBuild() { 21 | return version.contains("SNAPSHOT") == false 22 | } 23 | 24 | def getReleaseRepositoryUrl() { 25 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL 26 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 27 | } 28 | 29 | def getSnapshotRepositoryUrl() { 30 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL 31 | : "https://oss.sonatype.org/content/repositories/snapshots/" 32 | } 33 | 34 | def getRepositoryUsername() { 35 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" 36 | } 37 | 38 | def getRepositoryPassword() { 39 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 40 | } 41 | 42 | afterEvaluate { project -> 43 | uploadArchives { 44 | repositories { 45 | mavenDeployer { 46 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 47 | 48 | pom.artifactId = POM_ARTIFACT_ID 49 | pom.groupId = GROUP 50 | pom.version = VERSION_NAME 51 | 52 | repository(url: getReleaseRepositoryUrl()) { 53 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 54 | } 55 | snapshotRepository(url: getSnapshotRepositoryUrl()) { 56 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 57 | } 58 | 59 | pom.project { 60 | name POM_NAME 61 | packaging POM_PACKAGING 62 | description POM_DESCRIPTION 63 | url POM_URL 64 | 65 | scm { 66 | url POM_SCM_URL 67 | connection POM_SCM_CONNECTION 68 | developerConnection POM_SCM_DEV_CONNECTION 69 | } 70 | 71 | licenses { 72 | license { 73 | name POM_LICENCE_NAME 74 | url POM_LICENCE_URL 75 | distribution POM_LICENCE_DIST 76 | } 77 | } 78 | 79 | developers { 80 | developer { 81 | id POM_DEVELOPER_ID 82 | name POM_DEVELOPER_NAME 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | signing { 91 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 92 | sign configurations.archives 93 | } 94 | 95 | task androidJavadocs(type: Javadoc) { 96 | source = android.sourceSets.main.java.source 97 | } 98 | 99 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 100 | classifier = 'javadoc' 101 | from androidJavadocs.destinationDir 102 | } 103 | 104 | task androidSourcesJar(type: Jar) { 105 | classifier = 'sources' 106 | from android.sourceSets.main.java.source 107 | } 108 | 109 | artifacts { 110 | archives androidSourcesJar 111 | archives androidJavadocsJar 112 | } 113 | } -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/SlidingDebugMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu; 18 | 19 | import android.content.Context; 20 | import android.content.Intent; 21 | import android.content.pm.ApplicationInfo; 22 | import android.content.pm.ResolveInfo; 23 | import android.net.Uri; 24 | import android.provider.Settings; 25 | import android.support.v4.widget.DrawerLayout; 26 | import android.util.AttributeSet; 27 | import android.view.Gravity; 28 | import android.view.LayoutInflater; 29 | import android.view.View; 30 | import android.view.ViewGroup; 31 | import android.widget.ImageView; 32 | import android.widget.LinearLayout; 33 | import android.widget.RelativeLayout; 34 | import android.widget.TextView; 35 | import android.widget.Toast; 36 | import co.lemonlabs.android.slidingdebugmenu.modules.MenuModule; 37 | import co.lemonlabs.android.slidingdebugmenu.views.ModuleTitle; 38 | 39 | import java.util.ArrayList; 40 | import java.util.HashMap; 41 | import java.util.List; 42 | import java.util.Map; 43 | 44 | public class SlidingDebugMenu extends RelativeLayout implements View.OnClickListener { 45 | 46 | private static final String TAG = "SlidingDebugMenu"; 47 | 48 | public static SlidingDebugMenu create(Context context, List modules) { 49 | SlidingDebugMenu sdm = (SlidingDebugMenu) LayoutInflater.from(context).inflate(R.layout.sdm__drawer, null); 50 | for (MenuModule module : modules) { 51 | sdm.addModule(module); 52 | } 53 | return sdm; 54 | } 55 | 56 | /** 57 | * Root layout of the menu 58 | */ 59 | private ViewGroup mContainer; 60 | 61 | /** 62 | * Drawer settings layout 63 | */ 64 | private View mDrawerSettings; 65 | 66 | /** 67 | * Drawer subtitle 68 | */ 69 | private TextView mDrawerSubtitle; 70 | 71 | /** 72 | * List of currently added and visible modules 73 | */ 74 | private List mModules; 75 | 76 | /** 77 | * Map of modules to their views in the menu 78 | */ 79 | private Map mModuleViews; 80 | 81 | public SlidingDebugMenu(Context context, AttributeSet attrs) { 82 | super(context, attrs); 83 | mModules = new ArrayList<>(); 84 | mModuleViews = new HashMap<>(); 85 | 86 | DrawerLayout.LayoutParams params = new DrawerLayout.LayoutParams(context, attrs); 87 | params.gravity = Gravity.RIGHT; 88 | setLayoutParams(params); 89 | } 90 | 91 | @Override protected void onFinishInflate() { 92 | super.onFinishInflate(); 93 | 94 | mContainer = (ViewGroup) findViewById(R.id.sdm__drawer_container); 95 | mDrawerSettings = findViewById(R.id.sdm__drawer_settings); 96 | mDrawerSubtitle = (TextView) findViewById(R.id.sdm__drawer_title_description); 97 | 98 | // Set drawer title icon and name 99 | final ApplicationInfo appInfo = getContext().getApplicationInfo(); 100 | ((ImageView) findViewById(R.id.sdm__drawer_title_icon)).setImageDrawable(appInfo.loadIcon(getContext().getPackageManager())); 101 | ((TextView) findViewById(R.id.sdm__drawer_title)).setText(appInfo.labelRes); 102 | 103 | // Init drawer settings 104 | findViewById(R.id.sdm__settings_developer).setOnClickListener(this); 105 | findViewById(R.id.sdm__settings_battery).setOnClickListener(this); 106 | findViewById(R.id.sdm__settings_drawer).setOnClickListener(this); 107 | findViewById(R.id.sdm__settings_uninstall).setOnClickListener(this); 108 | findViewById(R.id.sdm__settings_app_info).setOnClickListener(this); 109 | } 110 | 111 | /** 112 | * Add a new module to the end of the menu 113 | * 114 | * @param module module to add 115 | */ 116 | public void addModule(MenuModule module) { 117 | addModule(mModules.size(), module); 118 | } 119 | 120 | /** 121 | * Add a new module at the specified position of the menu 122 | * 123 | * @param position the index at which to insert 124 | * @param module module to add 125 | */ 126 | public void addModule(int position, MenuModule module) { 127 | mModules.add(position, module); 128 | // drawer has a title view and each module has 2 views 129 | mModuleViews.put(module, addModuleViews(module, position * 2 + 1)); 130 | } 131 | 132 | /** 133 | * Add module title and content to drawer layout at the given index 134 | * of the container and return a wrapper of the views 135 | * 136 | * @param module module to get views from 137 | * @param index position of view root at which to insert 138 | * @return 139 | */ 140 | private ModuleViewHolder addModuleViews(MenuModule module, int index) { 141 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 142 | final int botMargin = (int) getResources().getDimension(R.dimen.sdm__module_subtitle_margin); 143 | final int topMargin = (int) getResources().getDimension(R.dimen.sdm__drawer_module_margin); 144 | params.setMargins(0, topMargin, 0, botMargin); 145 | 146 | ModuleTitle title = new ModuleTitle(getContext(), module.getTitle()); 147 | View content = module.getContent(getContext()); 148 | mContainer.addView(title, index, params); 149 | mContainer.addView(content, index + 1); 150 | 151 | return new ModuleViewHolder(title, content); 152 | } 153 | 154 | /** 155 | * Remove a module from the menu 156 | * 157 | * @param module module to remove 158 | */ 159 | public void removeModule(MenuModule module) { 160 | if (mModules.remove(module)) { 161 | ModuleViewHolder holder = mModuleViews.get(module); 162 | mContainer.removeView(holder.title); 163 | mContainer.removeView(holder.content); 164 | module.onStop(); 165 | } 166 | } 167 | 168 | /** 169 | * Remove a module from the menu by its position 170 | * 171 | * @param position the index which is to be removed 172 | */ 173 | public void removeModule(int position) { 174 | MenuModule module = mModules.get(position); 175 | if (mModules.remove(module)) { 176 | ModuleViewHolder holder = mModuleViews.get(module); 177 | mContainer.removeView(holder.title); 178 | mContainer.removeView(holder.content); 179 | module.onStop(); 180 | } 181 | } 182 | 183 | /** 184 | * Set visibility of drawer settings at the bottom of the menu 185 | * 186 | * @param visible 187 | */ 188 | public void setDrawerSettingsVisible(boolean visible) { 189 | mDrawerSettings.setVisibility(visible ? VISIBLE : GONE); 190 | } 191 | 192 | /** 193 | * Set drawer subtitle 194 | * 195 | * @param text 196 | */ 197 | public void setDrawerSubtitle(String text) { 198 | mDrawerSubtitle.setText(text); 199 | } 200 | 201 | /** 202 | * Get a list of currently loaded and visible modules 203 | * 204 | * @return 205 | */ 206 | public List getLoadedModules() { 207 | return mModules; 208 | } 209 | 210 | /** 211 | * Get a module by its position in the menu 212 | * 213 | * @param position 214 | * @return 215 | */ 216 | public MenuModule getModule(int position) { 217 | return mModules.get(position); 218 | } 219 | 220 | /** 221 | * Get first occurrence of a module by given class. Returns null otherwise. 222 | * 223 | * @param moduleClass instance of module to look for 224 | * @return 225 | */ 226 | public MenuModule getModule(Class moduleClass) { 227 | for (MenuModule module : mModules) { 228 | if (moduleClass.isInstance(module)) return module; 229 | } 230 | 231 | return null; 232 | } 233 | 234 | /** 235 | * Removes all modules and calls their {@link MenuModule#onStop()} method 236 | */ 237 | public void onStop() { 238 | for (MenuModule module : mModules) { 239 | module.onStop(); 240 | } 241 | } 242 | 243 | /** 244 | * Starts all modules and calls their {@link MenuModule#onStart()} method 245 | */ 246 | public void onStart() { 247 | for (MenuModule module : mModules) { 248 | module.onStart(); 249 | } 250 | } 251 | 252 | @SuppressWarnings("ConstantConditions") 253 | @Override 254 | public void onClick(View v) { 255 | final int id = v.getId(); 256 | Context context = getContext(); 257 | 258 | if (id == R.id.sdm__settings_developer) { 259 | // open dev settings 260 | Intent devIntent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); 261 | ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(devIntent, 0); 262 | if (resolveInfo != null) context.startActivity(devIntent); 263 | else Toast.makeText(context, "Developer settings not available on device", Toast.LENGTH_SHORT).show(); 264 | 265 | } else if (id == R.id.sdm__settings_battery) { 266 | // try to find an app to handle battery settings 267 | Intent batteryIntent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); 268 | ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(batteryIntent, 0); 269 | if (resolveInfo != null) context.startActivity(batteryIntent); 270 | else Toast.makeText(context, "No app found to handle power usage intent", Toast.LENGTH_SHORT).show(); 271 | 272 | } else if (id == R.id.sdm__settings_drawer) { 273 | // open android settings 274 | context.startActivity(new Intent(Settings.ACTION_SETTINGS)); 275 | 276 | } else if (id == R.id.sdm__settings_app_info) { 277 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 278 | intent.setData(Uri.parse("package:" + context.getPackageName())); 279 | context.startActivity(intent); 280 | 281 | } else if (id == R.id.sdm__settings_uninstall) { 282 | // open dialog to uninstall app 283 | Uri packageURI = Uri.parse("package:" + context.getPackageName()); 284 | Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI); 285 | context.startActivity(uninstallIntent); 286 | } 287 | } 288 | 289 | /** 290 | * Holder for module views 291 | */ 292 | public static class ModuleViewHolder { 293 | public final ModuleTitle title; 294 | public final View content; 295 | 296 | public ModuleViewHolder(ModuleTitle title, View content) { 297 | this.title = title; 298 | this.content = content; 299 | } 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/SlidingDebugMenuModule.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu; 2 | 3 | import android.content.Context; 4 | import co.lemonlabs.android.slidingdebugmenu.modules.BuildModule; 5 | import co.lemonlabs.android.slidingdebugmenu.modules.LocationModule; 6 | import co.lemonlabs.android.slidingdebugmenu.modules.LogModule; 7 | import co.lemonlabs.android.slidingdebugmenu.modules.MenuModule; 8 | import co.lemonlabs.android.slidingdebugmenu.modules.NetworkModule; 9 | import dagger.Module; 10 | import dagger.Provides; 11 | 12 | import java.util.List; 13 | 14 | @Module( 15 | library = true, 16 | complete = false 17 | ) 18 | public class SlidingDebugMenuModule { 19 | 20 | @Provides SlidingDebugMenu provideSlidingDebugMenu(Context context, List modules) { 21 | return SlidingDebugMenu.create(context, modules); 22 | } 23 | 24 | @Provides BuildModule provideBuildModule() { 25 | return new BuildModule(); 26 | } 27 | 28 | @Provides LocationModule provideLocationModule() { 29 | return new LocationModule(); 30 | } 31 | 32 | @Provides LogModule provideLogModule() { 33 | return new LogModule(); 34 | } 35 | 36 | @Provides NetworkModule provideNetworkModule() { 37 | return new NetworkModule(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/controllers/LocationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.controllers; 18 | 19 | import android.content.Context; 20 | import android.location.Location; 21 | import android.os.Bundle; 22 | 23 | import com.google.android.gms.common.ConnectionResult; 24 | import com.google.android.gms.common.GooglePlayServicesClient; 25 | import com.google.android.gms.common.GooglePlayServicesUtil; 26 | import com.google.android.gms.location.LocationClient; 27 | import com.google.android.gms.location.LocationListener; 28 | import com.google.android.gms.location.LocationRequest; 29 | 30 | import de.greenrobot.event.EventBus; 31 | import co.lemonlabs.android.slidingdebugmenu.modules.events.LocationEvent; 32 | 33 | /** 34 | * Created by balysv on 14/01/14. 35 | * www.lemonlabs.co 36 | */ 37 | public class LocationController implements GooglePlayServicesClient.ConnectionCallbacks, 38 | GooglePlayServicesClient.OnConnectionFailedListener { 39 | 40 | private static LocationController instance; 41 | 42 | private LocationClient mLocationClient; 43 | 44 | public static LocationController newInstance(Context context) { 45 | if (instance == null) 46 | instance = new LocationController(context); 47 | return instance; 48 | } 49 | 50 | private LocationController(Context context) { 51 | if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS) 52 | mLocationClient = new LocationClient(context, this, this); 53 | else EventBus.getDefault().post(new LocationEvent(null)); 54 | } 55 | 56 | @Override 57 | public void onConnected(Bundle bundle) { 58 | final Location location = mLocationClient.getLastLocation(); 59 | EventBus.getDefault().post(new LocationEvent(location)); 60 | } 61 | 62 | @Override 63 | public void onDisconnected() { 64 | mLocationClient.removeLocationUpdates(mLocationListener); 65 | } 66 | 67 | @Override 68 | public void onConnectionFailed(ConnectionResult connectionResult) { 69 | EventBus.getDefault().post(new LocationEvent(null)); 70 | } 71 | 72 | /** 73 | * Connect to GooglePlayServices location client 74 | */ 75 | public void connect() { 76 | if (mLocationClient != null) mLocationClient.connect(); 77 | } 78 | 79 | /** 80 | * Disconnect from GooglePlayServices location client 81 | */ 82 | public void disconnect() { 83 | if (mLocationClient != null) mLocationClient.disconnect(); 84 | 85 | } 86 | 87 | /** 88 | * Get last known location 89 | * 90 | * @return 91 | */ 92 | public Location getLastLocation() { 93 | return mLocationClient != null ? mLocationClient.getLastLocation() : null; 94 | } 95 | 96 | /** 97 | * Request for a new location. Callbacks can be received by handling 98 | * {@link co.lemonlabs.android.slidingdebugmenu.modules.events.LocationEvent} using 99 | * {@link de.greenrobot.event.EventBus}. 100 | */ 101 | public void requestLocation() { 102 | if (mLocationClient != null) 103 | mLocationClient.requestLocationUpdates(new LocationRequest(), mLocationListener); 104 | } 105 | 106 | /** 107 | * Simple location listener that pushes an event on location updates 108 | */ 109 | private LocationListener mLocationListener = new LocationListener() { 110 | @Override 111 | public void onLocationChanged(Location location) { 112 | EventBus.getDefault().post(new LocationEvent(location)); 113 | } 114 | }; 115 | } 116 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/controllers/NetworkController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.controllers; 18 | 19 | import android.bluetooth.BluetoothAdapter; 20 | import android.content.Context; 21 | import android.content.IntentFilter; 22 | import android.net.ConnectivityManager; 23 | import android.net.NetworkInfo; 24 | import android.net.wifi.WifiManager; 25 | 26 | import java.lang.reflect.Field; 27 | import java.lang.reflect.InvocationTargetException; 28 | import java.lang.reflect.Method; 29 | 30 | import co.lemonlabs.android.slidingdebugmenu.receivers.NetworkReceiver; 31 | 32 | /** 33 | * Created by balysv on 10/01/14. 34 | * www.lemonlabs.co 35 | */ 36 | 37 | public class NetworkController { 38 | 39 | public enum BluetoothState { 40 | On, Off, Turning_On, Turning_Off, Unknown 41 | } 42 | 43 | private static NetworkController instance; 44 | 45 | private WifiManager mWifiManager; 46 | private ConnectivityManager mConnectivityManager; 47 | private BluetoothAdapter mBluetoothAdapter; 48 | 49 | private NetworkReceiver mReceiver; 50 | 51 | private transient Context mContext; 52 | 53 | public static NetworkController newInstance(Context context) { 54 | if (instance == null) 55 | instance = new NetworkController(context); 56 | return instance; 57 | } 58 | 59 | /** 60 | * Controller responsible for switching states related to networks. 61 | * E.g. wifi, mobile networks 62 | * 63 | * @param context 64 | */ 65 | private NetworkController(Context context) { 66 | mContext = context.getApplicationContext(); 67 | mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 68 | mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 69 | mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 70 | } 71 | 72 | 73 | /** 74 | * True if WiFi enabled 75 | * 76 | * @return 77 | */ 78 | public boolean isWifiEnabled() { 79 | return mWifiManager.isWifiEnabled(); 80 | } 81 | 82 | /** 83 | * Set WiFi state 84 | * 85 | * @param enabled 86 | */ 87 | public void setWifiEnabled(boolean enabled) { 88 | mWifiManager.setWifiEnabled(enabled); 89 | } 90 | 91 | /** 92 | * True if mobile network enabled 93 | * 94 | * @return 95 | */ 96 | public boolean isMobileNetworkEnabled() { 97 | final NetworkInfo info = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 98 | return (info != null && info.isConnected()); 99 | } 100 | 101 | /** 102 | * Try to enabled/disable mobile network state using reflection. 103 | * Returns true if succeeded 104 | * 105 | * @param enabled 106 | * @return 107 | */ 108 | public boolean setMobileNetworkEnabled(boolean enabled) { 109 | try { 110 | final Class conmanClass = Class.forName(mConnectivityManager.getClass().getName()); 111 | final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService"); 112 | iConnectivityManagerField.setAccessible(true); 113 | final Object iConnectivityManager = iConnectivityManagerField.get(mConnectivityManager); 114 | final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName()); 115 | final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE); 116 | setMobileDataEnabledMethod.setAccessible(true); 117 | setMobileDataEnabledMethod.invoke(iConnectivityManager, enabled); 118 | return true; 119 | } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | IllegalAccessException | NoSuchFieldException e) { 120 | } 121 | return false; 122 | } 123 | 124 | /** 125 | * True if bluetooth is enabled 126 | */ 127 | public boolean isBluetoothEnabled() { 128 | return mBluetoothAdapter.isEnabled(); 129 | } 130 | 131 | /** 132 | * Try to enable/disabled bluetooth. Returns false if immediate 133 | * error occurs 134 | * 135 | * @param enabled 136 | * @return 137 | */ 138 | public boolean setBluetoothEnabled(boolean enabled) { 139 | return enabled ? mBluetoothAdapter.enable() : mBluetoothAdapter.disable(); 140 | } 141 | 142 | 143 | /** 144 | * Unregister network state broadcast receiver 145 | */ 146 | public void unregisterReceiver() { 147 | try { 148 | mContext.unregisterReceiver(mReceiver); 149 | } catch (IllegalArgumentException e) { 150 | } 151 | } 152 | 153 | /** 154 | * Register network state broadcast receiver 155 | */ 156 | public void registerReceiver() { 157 | if (mReceiver == null) 158 | mReceiver = new NetworkReceiver(); 159 | IntentFilter filter = new IntentFilter(); 160 | filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 161 | filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 162 | mContext.registerReceiver(mReceiver, filter); 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/modules/BuildModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.modules; 18 | 19 | import android.content.Context; 20 | import android.content.pm.PackageInfo; 21 | import android.content.pm.PackageManager; 22 | import android.view.View; 23 | import android.widget.LinearLayout; 24 | 25 | import co.lemonlabs.android.slidingdebugmenu.R; 26 | import co.lemonlabs.android.slidingdebugmenu.views.ModuleSimpleProperty; 27 | 28 | /** 29 | * Module that provides basic information about 30 | * the running application. 31 | */ 32 | public class BuildModule extends MenuModule { 33 | 34 | private static final String TITLE = "Build Information"; 35 | 36 | @Override 37 | public String getTitle() { 38 | return TITLE; 39 | } 40 | 41 | @Override 42 | public View getContent(Context context) { 43 | LinearLayout v = new LinearLayout(context); 44 | v.setOrientation(LinearLayout.VERTICAL); 45 | 46 | 47 | ModuleSimpleProperty name = new ModuleSimpleProperty(context, R.string.sdm__module_build_name); 48 | v.addView(name); 49 | 50 | ModuleSimpleProperty version = new ModuleSimpleProperty(context, R.string.sdm__module_build_version); 51 | v.addView(version); 52 | 53 | ModuleSimpleProperty packageName = new ModuleSimpleProperty(context, R.string.sdm__module_build_package); 54 | v.addView(packageName); 55 | 56 | try { 57 | final PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 58 | version.setPropertyValue(String.valueOf(info.versionCode)); 59 | name.setPropertyValue(info.versionName); 60 | packageName.setPropertyValue(info.packageName); 61 | } catch (PackageManager.NameNotFoundException e) { 62 | 63 | } 64 | 65 | return v; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/modules/LocationModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.modules; 18 | 19 | import android.content.ActivityNotFoundException; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import android.location.Location; 23 | import android.net.Uri; 24 | import android.provider.Settings; 25 | import android.view.LayoutInflater; 26 | import android.view.View; 27 | import android.view.ViewGroup; 28 | import android.widget.TextView; 29 | import android.widget.Toast; 30 | import co.lemonlabs.android.slidingdebugmenu.R; 31 | import co.lemonlabs.android.slidingdebugmenu.controllers.LocationController; 32 | import co.lemonlabs.android.slidingdebugmenu.modules.events.LocationEvent; 33 | import co.lemonlabs.android.slidingdebugmenu.views.ModuleSimpleProperty; 34 | import com.google.android.gms.common.ConnectionResult; 35 | import com.google.android.gms.common.GooglePlayServicesUtil; 36 | import de.greenrobot.event.EventBus; 37 | 38 | import java.text.SimpleDateFormat; 39 | import java.util.Date; 40 | 41 | /** 42 | * Module that provides information about the current 43 | * location of the device, allows to get new locations, 44 | * go to settings and open maps. 45 | * GooglePlayServices {@link com.google.android.gms.location.LocationClient} is used, 46 | * so be sure to call {@link #onStop() onStop} and {@link #onStart() onStart}. 47 | * Module will not work in devices without GooglePlayServices installed. 48 | */ 49 | public class LocationModule extends MenuModule { 50 | 51 | private static final String TITLE = "Location"; 52 | 53 | private LocationController mLocationController; 54 | 55 | private ModuleSimpleProperty latitude; 56 | private ModuleSimpleProperty longitude; 57 | private ModuleSimpleProperty accuracy; 58 | private ModuleSimpleProperty time; 59 | private ModuleSimpleProperty provider; 60 | 61 | private Location mLocation; 62 | 63 | private boolean mPlayServicesAvailable; 64 | 65 | @Override 66 | public String getTitle() { 67 | return TITLE; 68 | } 69 | 70 | @Override 71 | public View getContent(final Context context) { 72 | mPlayServicesAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS; 73 | // add module contents only if Google Play Services are available 74 | if (mPlayServicesAvailable) { 75 | mLocationController = LocationController.newInstance(context); 76 | 77 | ViewGroup v = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.sdm__module_location, null); 78 | assert v != null; 79 | 80 | final View.OnClickListener onClickListener = new View.OnClickListener() { 81 | @Override 82 | public void onClick(View v) { 83 | final int id = v.getId(); 84 | if (id == R.id.sdm__location_map) { 85 | openMaps(context); 86 | } else if (id == R.id.sdm__location_get) { 87 | mLocationController.requestLocation(); 88 | } else if (id == R.id.sdm__location_settings) { 89 | context.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); 90 | } 91 | } 92 | }; 93 | 94 | v.findViewById(R.id.sdm__location_get).setOnClickListener(onClickListener); 95 | v.findViewById(R.id.sdm__location_settings).setOnClickListener(onClickListener); 96 | v.findViewById(R.id.sdm__location_map).setOnClickListener(onClickListener); 97 | 98 | latitude = new ModuleSimpleProperty(context, R.string.sdm__module_location_latitide); 99 | v.addView(latitude); 100 | 101 | longitude = new ModuleSimpleProperty(context, R.string.sdm__module_location_longitude); 102 | v.addView(longitude); 103 | 104 | accuracy = new ModuleSimpleProperty(context, R.string.sdm__module_location_accuracy); 105 | v.addView(accuracy); 106 | 107 | time = new ModuleSimpleProperty(context, R.string.sdm__module_location_time); 108 | v.addView(time); 109 | 110 | provider = new ModuleSimpleProperty(context, R.string.sdm__module_location_provider); 111 | v.addView(provider); 112 | return v; 113 | } else { 114 | TextView errorText = new TextView(context); 115 | errorText.setTextAppearance(context, R.style.Widget_Sdm_TextView_PropertyValue); 116 | errorText.setText(R.string.sdm__module_location_play_unavailable); 117 | return errorText; 118 | } 119 | } 120 | 121 | /** 122 | * Receive location update events 123 | * 124 | * @param e 125 | */ 126 | public void onEventMainThread(LocationEvent e) { 127 | updateLocation(e.location); 128 | } 129 | 130 | @Override 131 | public void onStart() { 132 | if (mPlayServicesAvailable) { 133 | EventBus.getDefault().register(this); 134 | mLocationController.connect(); 135 | } 136 | } 137 | 138 | @Override 139 | public void onStop() { 140 | if (mPlayServicesAvailable) { 141 | mLocationController.disconnect(); 142 | EventBus.getDefault().unregister(this); 143 | } 144 | } 145 | 146 | /** 147 | * Update the module UI 148 | * 149 | * @param location 150 | */ 151 | private void updateLocation(Location location) { 152 | mLocation = location; 153 | if (location != null) { 154 | latitude.setPropertyValue(String.valueOf(location.getLatitude())); 155 | longitude.setPropertyValue(String.valueOf(location.getLongitude())); 156 | accuracy.setPropertyValue(String.valueOf(location.getAccuracy()) + "m"); 157 | 158 | Date date = new Date(location.getTime()); 159 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 160 | time.setPropertyValue(sdf.format(date)); 161 | 162 | provider.setPropertyValue(location.getProvider()); 163 | } else { 164 | latitude.setPropertyValue(R.string.sdm__module_location_empty); 165 | longitude.setPropertyValue(R.string.sdm__module_location_empty); 166 | accuracy.setPropertyValue(R.string.sdm__module_location_empty); 167 | time.setPropertyValue(R.string.sdm__module_location_empty); 168 | provider.setPropertyValue(R.string.sdm__module_location_no_provider); 169 | } 170 | } 171 | 172 | 173 | /** 174 | * Tries to open an activity that handles geo coordinates 175 | * 176 | * @param context 177 | */ 178 | private void openMaps(Context context) { 179 | try { 180 | if (mLocation != null) { 181 | String uri = "geo:" + mLocation.getLatitude() + "," + mLocation.getLongitude(); 182 | context.startActivity(new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(uri))); 183 | } else { 184 | Toast.makeText(context, R.string.sdm__module_location_not_found, Toast.LENGTH_SHORT).show(); 185 | } 186 | } catch (ActivityNotFoundException e) { 187 | Toast.makeText(context, R.string.sdm__module_location_map_not_found, Toast.LENGTH_SHORT).show(); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/modules/LogModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.modules; 18 | 19 | import android.content.Context; 20 | import android.view.View; 21 | import android.widget.AdapterView; 22 | import android.widget.ArrayAdapter; 23 | import android.widget.LinearLayout; 24 | 25 | import co.lemonlabs.android.slidingdebugmenu.R; 26 | import co.lemonlabs.android.slidingdebugmenu.util.Log; 27 | import co.lemonlabs.android.slidingdebugmenu.views.ModuleSpinnerProperty; 28 | 29 | /** 30 | * Module to change Log level during runtime using 31 | * {@link co.lemonlabs.android.slidingdebugmenu.util.Log}. 32 | */ 33 | public class LogModule extends MenuModule { 34 | 35 | private static final String[] LOG_LEVELS = new String[]{"Verbose", "Debug", "Info", "Warn", "Error", "WTF"}; 36 | private static final String TITLE = "Logging"; 37 | 38 | @Override 39 | public String getTitle() { 40 | return TITLE; 41 | } 42 | 43 | @Override 44 | public View getContent(Context context) { 45 | LinearLayout v = new LinearLayout(context); 46 | v.setOrientation(LinearLayout.VERTICAL); 47 | 48 | ModuleSpinnerProperty levelProperty = new ModuleSpinnerProperty(context, R.string.sdm__module_log_level); 49 | v.addView(levelProperty); 50 | 51 | ArrayAdapter levelAdapter = new ArrayAdapter<>( 52 | context, 53 | R.layout.sdm__spinner_dropdown_item, 54 | LOG_LEVELS 55 | ); 56 | 57 | levelProperty.setSpinnerAdapter(levelAdapter); 58 | levelProperty.setOnSpinnerItemSelectedListener(new AdapterView.OnItemSelectedListener() { 59 | @Override 60 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 61 | // const value for VERBOSE is 2 62 | Log.LOG_LEVEL = position + 2; 63 | } 64 | 65 | @Override 66 | public void onNothingSelected(AdapterView parent) { 67 | } 68 | }); 69 | 70 | 71 | return v; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/modules/MenuModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.modules; 18 | 19 | import android.content.Context; 20 | import android.view.View; 21 | 22 | /** 23 | * Base class for SlidingDebugMenu modules. 24 | *

25 | * Created by balysv on 10/01/14. 26 | * www.lemonlabs.co 27 | */ 28 | public abstract class MenuModule { 29 | 30 | public MenuModule() {} 31 | 32 | public abstract String getTitle(); 33 | 34 | public abstract View getContent(Context context); 35 | 36 | /** 37 | * Override this method if you need to do 38 | * some clean up when activity goes to foreground. 39 | * E.g. unregister receivers 40 | */ 41 | public void onStop() { 42 | // do clean up 43 | } 44 | 45 | /** 46 | * Override this method if you need to start 47 | * some processes that would be killed when 48 | * onStop() is called 49 | * E.g. register receivers 50 | */ 51 | public void onStart() { 52 | // reinitialize stuff 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/modules/NetworkModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Lemon Labs 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 co.lemonlabs.android.slidingdebugmenu.modules; 18 | 19 | import android.content.Context; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | 24 | import de.greenrobot.event.EventBus; 25 | import co.lemonlabs.android.slidingdebugmenu.R; 26 | import co.lemonlabs.android.slidingdebugmenu.controllers.NetworkController; 27 | import co.lemonlabs.android.slidingdebugmenu.modules.events.NetworkChangeEvent; 28 | import co.lemonlabs.android.slidingdebugmenu.views.ModuleSimpleProperty; 29 | 30 | /** 31 | * Module that provides an interface allowing to switch 32 | * and view the state of Wifi, Mobile network and Bluetooth. 33 | * A manually registered broadcast receiver is used, so be 34 | * sure to call {@link #onStop() onStop} and {@link #onStart() onStart}. 35 | */ 36 | public class NetworkModule extends MenuModule implements View.OnClickListener { 37 | 38 | private static final String TITLE = "Network"; 39 | 40 | private NetworkController networkController; 41 | 42 | private ModuleSimpleProperty wifiState; 43 | private ModuleSimpleProperty mobileState; 44 | private ModuleSimpleProperty bluetoothState; 45 | 46 | @Override 47 | public String getTitle() { 48 | return TITLE; 49 | } 50 | 51 | @Override 52 | public View getContent(Context context) { 53 | 54 | networkController = NetworkController.newInstance(context); 55 | 56 | ViewGroup v = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.sdm__module_network, null); 57 | assert v != null; 58 | 59 | v.findViewById(R.id.sdm__network_wifi_toggle).setOnClickListener(this); 60 | v.findViewById(R.id.sdm__network_mobile_toggle).setOnClickListener(this); 61 | v.findViewById(R.id.sdm__network_bluetooth_toggle).setOnClickListener(this); 62 | 63 | wifiState = new ModuleSimpleProperty(context, R.string.sdm__module_network_wifi); 64 | v.addView(wifiState); 65 | 66 | mobileState = new ModuleSimpleProperty(context, R.string.sdm__module_network_mobile); 67 | v.addView(mobileState); 68 | 69 | bluetoothState = new ModuleSimpleProperty(context, R.string.sdm__module_network_bluetooth); 70 | v.addView(bluetoothState); 71 | 72 | return v; 73 | } 74 | 75 | /** 76 | * Receive events from broadcast receiver and update UI 77 | * 78 | * @param e 79 | */ 80 | public void onEventMainThread(NetworkChangeEvent e) { 81 | final String wifiStateString = e.wifiState.name().toLowerCase(); 82 | final String mobileStateString = e.mobileState.name().toLowerCase(); 83 | 84 | wifiState.setPropertyValue(Character.toUpperCase(wifiStateString.charAt(0)) + wifiStateString.substring(1)); 85 | mobileState.setPropertyValue(Character.toUpperCase(mobileStateString.charAt(0)) + mobileStateString.substring(1)); 86 | bluetoothState.setPropertyValue(e.bluetoothState.name().replace("_", " ")); 87 | } 88 | 89 | @Override 90 | public void onStop() { 91 | networkController.unregisterReceiver(); 92 | EventBus.getDefault().unregister(this); 93 | } 94 | 95 | @Override 96 | public void onStart() { 97 | EventBus.getDefault().register(this); 98 | networkController.registerReceiver(); 99 | } 100 | 101 | @Override 102 | public void onClick(View v) { 103 | final int id = v.getId(); 104 | if (id == R.id.sdm__network_wifi_toggle) { 105 | networkController.setWifiEnabled(!networkController.isWifiEnabled()); 106 | } else if (id == R.id.sdm__network_mobile_toggle) { 107 | networkController.setMobileNetworkEnabled(!networkController.isMobileNetworkEnabled()); 108 | } else if (id == R.id.sdm__network_bluetooth_toggle) { 109 | networkController.setBluetoothEnabled(!networkController.isBluetoothEnabled()); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/modules/events/LocationEvent.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.modules.events; 2 | 3 | import android.location.Location; 4 | 5 | /** 6 | * Created by balysv on 14/01/14. 7 | * www.lemonlabs.co 8 | */ 9 | public class LocationEvent { 10 | 11 | public final Location location; 12 | 13 | public LocationEvent(Location location) { 14 | this.location = location; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/modules/events/NetworkChangeEvent.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.modules.events; 2 | 3 | import android.net.NetworkInfo; 4 | 5 | import static co.lemonlabs.android.slidingdebugmenu.controllers.NetworkController.BluetoothState; 6 | 7 | /** 8 | * Created by balysv on 10/01/14. 9 | * www.lemonlabs.co 10 | */ 11 | public class NetworkChangeEvent { 12 | 13 | public final NetworkInfo.State wifiState; 14 | public final NetworkInfo.State mobileState; 15 | public final BluetoothState bluetoothState; 16 | 17 | public NetworkChangeEvent(NetworkInfo.State wifiState, NetworkInfo.State mobileState, BluetoothState bluetoothState) { 18 | this.wifiState = wifiState; 19 | this.mobileState = mobileState; 20 | this.bluetoothState = bluetoothState; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/receivers/NetworkReceiver.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.receivers; 2 | 3 | import android.bluetooth.BluetoothAdapter; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.net.ConnectivityManager; 8 | import android.net.NetworkInfo; 9 | 10 | import de.greenrobot.event.EventBus; 11 | import co.lemonlabs.android.slidingdebugmenu.modules.events.NetworkChangeEvent; 12 | 13 | import static co.lemonlabs.android.slidingdebugmenu.controllers.NetworkController.BluetoothState; 14 | 15 | /** 16 | * Receiver that handles wifi, mobile networks and 17 | * Bluetooth connectivity change intents and sends 18 | * a NetworkChangeEvent using EventBus 19 | *

20 | * Created by balysv on 10/01/14. 21 | * www.lemonlabs.co 22 | */ 23 | public class NetworkReceiver extends BroadcastReceiver { 24 | 25 | 26 | @Override 27 | public void onReceive(Context context, Intent intent) { 28 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 29 | 30 | NetworkInfo wifiInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 31 | NetworkInfo mobileInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 32 | 33 | final int bluetoothState = BluetoothAdapter.getDefaultAdapter().getState(); 34 | 35 | 36 | EventBus.getDefault().post(new NetworkChangeEvent( 37 | (wifiInfo != null) ? wifiInfo.getState() : NetworkInfo.State.UNKNOWN, 38 | (mobileInfo != null) ? mobileInfo.getState() : NetworkInfo.State.UNKNOWN, 39 | getBluetoothState(bluetoothState)) 40 | ); 41 | } 42 | 43 | /** 44 | * Converts Bluetooth state representation to an Enum 45 | * 46 | * @param state 47 | * @return 48 | */ 49 | private BluetoothState getBluetoothState(int state) { 50 | switch (state) { 51 | case BluetoothAdapter.STATE_ON: 52 | return BluetoothState.On; 53 | case BluetoothAdapter.STATE_OFF: 54 | return BluetoothState.Off; 55 | case BluetoothAdapter.STATE_TURNING_ON: 56 | return BluetoothState.Turning_On; 57 | case BluetoothAdapter.STATE_TURNING_OFF: 58 | return BluetoothState.Turning_Off; 59 | } 60 | 61 | return BluetoothState.Unknown; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/util/Log.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.util; 2 | 3 | import org.json.JSONObject; 4 | 5 | /** 6 | * Wrapper of core {@link android.util.Log} functions 7 | * to allow control using SlidingDebugMenu 8 | *

9 | * Created by balysv on 13/01/14. 10 | * www.lemonlabs.co 11 | */ 12 | public class Log { 13 | 14 | public static int LOG_LEVEL = 2; 15 | 16 | // VERBOSE 17 | 18 | public static void v(String tag, String message) { 19 | if (LOG_LEVEL <= android.util.Log.VERBOSE) 20 | android.util.Log.v(tag, message); 21 | } 22 | 23 | public static void v(String tag, boolean b) { 24 | v(tag, String.valueOf(b)); 25 | } 26 | 27 | public static void v(String tag, int i) { 28 | v(tag, String.valueOf(i)); 29 | } 30 | 31 | public static void v(String tag, JSONObject json) { 32 | v(tag, json.toString()); 33 | } 34 | 35 | // DEBUG 36 | 37 | public static void d(String tag, String message) { 38 | if (LOG_LEVEL <= android.util.Log.DEBUG) 39 | android.util.Log.d(tag, message); 40 | } 41 | 42 | public static void d(String tag, boolean b) { 43 | d(tag, String.valueOf(b)); 44 | } 45 | 46 | public static void d(String tag, int i) { 47 | d(tag, String.valueOf(i)); 48 | } 49 | 50 | public static void d(String tag, JSONObject json) { 51 | d(tag, json.toString()); 52 | } 53 | 54 | // INFO 55 | 56 | public static void i(String tag, String message) { 57 | if (LOG_LEVEL <= android.util.Log.INFO) 58 | android.util.Log.i(tag, message); 59 | } 60 | 61 | // WARN 62 | 63 | public static void w(String tag, String message) { 64 | if (LOG_LEVEL <= android.util.Log.WARN) 65 | android.util.Log.w(tag, message); 66 | } 67 | 68 | // ERROR 69 | public static void e(String tag, String message) { 70 | if (LOG_LEVEL <= android.util.Log.ERROR) 71 | android.util.Log.e(tag, message); 72 | } 73 | 74 | public static void e(String tag, String message, Throwable error) { 75 | if (LOG_LEVEL <= android.util.Log.ERROR) 76 | android.util.Log.e(tag, message, error); 77 | } 78 | 79 | public static void e(String tag, JSONObject json) { 80 | e(tag, json.toString()); 81 | } 82 | 83 | // WTF 84 | public static void wtf(String tag, String message) { 85 | if (LOG_LEVEL <= android.util.Log.ASSERT) 86 | android.util.Log.wtf(tag, message); 87 | } 88 | 89 | public static void wtf(String tag, String message, Throwable error) { 90 | if (LOG_LEVEL <= android.util.Log.ASSERT) 91 | android.util.Log.wtf(tag, message, error); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/views/ModuleSimpleProperty.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.views; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.widget.FrameLayout; 6 | import android.widget.TextView; 7 | 8 | import co.lemonlabs.android.slidingdebugmenu.R; 9 | 10 | /** 11 | * Simple module property containing 12 | * two text views 13 | *

14 | * Created by balysv on 10/01/14. 15 | * www.lemonlabs.co 16 | */ 17 | public class ModuleSimpleProperty extends FrameLayout { 18 | 19 | private TextView mPropertyName; 20 | private TextView mPropertyValue; 21 | 22 | public ModuleSimpleProperty(Context context, String propertyName) { 23 | this(context); 24 | setPropertyName(propertyName); 25 | } 26 | 27 | public ModuleSimpleProperty(Context context, int propertyResId) { 28 | this(context); 29 | setPropertyName(propertyResId); 30 | } 31 | 32 | public ModuleSimpleProperty(Context context) { 33 | super(context); 34 | inflate(); 35 | } 36 | 37 | private void inflate() { 38 | LayoutInflater.from(getContext()).inflate(R.layout.sdm__module_property_simple, this, true); 39 | mPropertyName = (TextView) findViewById(R.id.sdm__module_property_name); 40 | mPropertyValue = (TextView) findViewById(R.id.sdm__module_property_value); 41 | } 42 | 43 | /** 44 | * Set name of property 45 | * 46 | * @param name 47 | */ 48 | public void setPropertyName(String name) { 49 | mPropertyName.setText(name); 50 | } 51 | 52 | /** 53 | * Set name of property 54 | * 55 | * @param resId 56 | */ 57 | public void setPropertyName(int resId) { 58 | mPropertyName.setText(resId); 59 | } 60 | 61 | /** 62 | * Set property value 63 | * 64 | * @param name 65 | */ 66 | public void setPropertyValue(String name) { 67 | mPropertyValue.setText(name); 68 | } 69 | 70 | /** 71 | * Set property value 72 | * 73 | * @param resId 74 | */ 75 | public void setPropertyValue(int resId) { 76 | mPropertyValue.setText(resId); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/views/ModuleSpinnerProperty.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.views; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.widget.AdapterView; 6 | import android.widget.FrameLayout; 7 | import android.widget.Spinner; 8 | import android.widget.SpinnerAdapter; 9 | import android.widget.TextView; 10 | 11 | import co.lemonlabs.android.slidingdebugmenu.R; 12 | 13 | /** 14 | * A ModuleProperty containing a TextView label 15 | * and a Spinner 16 | *

17 | * Created by balysv on 13/01/14. 18 | * www.lemonlabs.co 19 | */ 20 | public class ModuleSpinnerProperty extends FrameLayout { 21 | 22 | private TextView mPropertyName; 23 | private Spinner mPropertySpinner; 24 | 25 | public ModuleSpinnerProperty(Context context, String propertyName) { 26 | this(context); 27 | setPropertyName(propertyName); 28 | } 29 | 30 | public ModuleSpinnerProperty(Context context, int propertyResId) { 31 | this(context); 32 | setPropertyName(propertyResId); 33 | } 34 | 35 | public ModuleSpinnerProperty(Context context) { 36 | super(context); 37 | inflate(); 38 | } 39 | 40 | private void inflate() { 41 | LayoutInflater.from(getContext()).inflate(R.layout.sdm__module_property_spinner, this, true); 42 | mPropertyName = (TextView) findViewById(R.id.sdm__module_property_name); 43 | mPropertySpinner = (Spinner) findViewById(R.id.sdm__module_property_spinner); 44 | } 45 | 46 | /** 47 | * Set name of property 48 | * 49 | * @param name 50 | */ 51 | public void setPropertyName(String name) { 52 | mPropertyName.setText(name); 53 | } 54 | 55 | /** 56 | * Set name of property 57 | * 58 | * @param resId 59 | */ 60 | public void setPropertyName(int resId) { 61 | mPropertyName.setText(resId); 62 | } 63 | 64 | /** 65 | * Set Adapter for Spinner 66 | * 67 | * @param adapter 68 | */ 69 | public void setSpinnerAdapter(SpinnerAdapter adapter) { 70 | mPropertySpinner.setAdapter(adapter); 71 | } 72 | 73 | /** 74 | * Set Spinner Item Selected callback 75 | * 76 | * @param listener 77 | */ 78 | public void setOnSpinnerItemSelectedListener(AdapterView.OnItemSelectedListener listener) { 79 | mPropertySpinner.setOnItemSelectedListener(listener); 80 | } 81 | 82 | /** 83 | * Get the Spinner associated with this property 84 | * 85 | * @return 86 | */ 87 | public Spinner getPropertySpinner() { 88 | return mPropertySpinner; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /library/src/main/java/co/lemonlabs/android/slidingdebugmenu/views/ModuleTitle.java: -------------------------------------------------------------------------------- 1 | package co.lemonlabs.android.slidingdebugmenu.views; 2 | 3 | import android.content.Context; 4 | import android.widget.TextView; 5 | 6 | import co.lemonlabs.android.slidingdebugmenu.R; 7 | 8 | /** 9 | * Created by balysv on 10/01/14. 10 | * www.lemonlabs.co 11 | */ 12 | public class ModuleTitle extends TextView { 13 | 14 | public ModuleTitle(Context context, String title) { 15 | super(context); 16 | setTextAppearance(context, R.style.Widget_Sdm_TextView_ModuleTitle); 17 | setBackgroundResource(R.drawable.sdm__module_title_bg); 18 | 19 | setText(title.toUpperCase()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_battery.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_controls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_controls.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_developer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_developer.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_info.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_locate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_locate.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_location.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_map.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_network_bluetooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_network_bluetooth.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_network_connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_network_connection.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_network_wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_network_wifi.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_settings.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/sdm__ic_uninstall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lemonlabs/slidingdebugmenu/eded38b6abe096a85fb58bd9eb8e0a1acd347b2d/library/src/main/res/drawable-xxhdpi/sdm__ic_uninstall.png -------------------------------------------------------------------------------- /library/src/main/res/drawable/sdm__drawer_settings_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/sdm__module_button_group_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/sdm__module_title_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/sdm__spinner_clickable_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/sdm__transparent_clickable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 11 | 12 | 18 | 19 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__drawer_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 20 | 21 | 28 | 29 | 36 | 37 | 44 | 45 | 52 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__drawer_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 24 | 25 | 36 | 37 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__module_location.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 21 | 22 | 28 | 29 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__module_network.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 21 | 22 | 28 | 29 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__module_property_simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 11 | 12 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__module_property_spinner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 12 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /library/src/main/res/layout/sdm__spinner_dropdown_item.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /library/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3C3C3C 4 | #DEDEDE 5 | 6 | #DEDEDE 7 | #ABABAB 8 | #DEDEDE 9 | #FFFF8800 10 | 11 | #ABABAB 12 | 13 | #00000000 14 | #22FFFFFF 15 | #3C3C3C 16 | #5E5E5E 17 | 18 | -------------------------------------------------------------------------------- /library/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4dp 4 | 5 | 6 | 320dp 7 | 8 | 12dp 9 | 8dp 10 | 12dp 11 | 12 | 6dp 13 | -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SlidingDebugMenu 3 | 4 | Turn Off WiFi 5 | Turn Mobile Off 6 | 7 | Debug drawer by Lemon Labs 8 | 9 | Wifi State 10 | Mobile State 11 | Bluetooth State 12 | Level 13 | Name 14 | Version 15 | Package 16 | Latitude 17 | Longitude 18 | Accuracy 19 | Time 20 | Provider 21 | Could not find app that opens a map 22 | No location set 23 | - 24 | None 25 | Google Play Services unavailable 26 | 27 | -------------------------------------------------------------------------------- /library/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 17 | 18 | 23 | 24 | 30 | 31 | 37 | 38 | 47 | 48 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':library', ':demo' 2 | --------------------------------------------------------------------------------