├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── krishna │ │ └── debug_tools_demo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── krishna │ │ │ └── debug_tools_demo │ │ │ ├── DBHelper.java │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── krishna │ └── debug_tools_demo │ └── ExampleUnitTest.java ├── build.gradle ├── debug_tools ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── krishna │ │ └── debug_tools │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── krishna │ │ │ └── debug_tools │ │ │ ├── activity │ │ │ ├── ActivityDebugTools.java │ │ │ ├── ActivitySharedPreference.java │ │ │ └── ActivityTable.java │ │ │ ├── adapter │ │ │ ├── DatabaseListAdapter.java │ │ │ ├── SharedPreferenceAdapter.java │ │ │ ├── SimpleListAdapter.java │ │ │ ├── TableContentRecyclerAdapter.java │ │ │ └── TableContentViewHolder.java │ │ │ ├── async_task │ │ │ ├── DatabaseListTask.java │ │ │ ├── FilesListTask.java │ │ │ ├── TableContentTask.java │ │ │ └── TableListTask.java │ │ │ ├── data │ │ │ ├── DBOpenHelper.java │ │ │ └── pojo │ │ │ │ ├── DBPojo.java │ │ │ │ └── Table.java │ │ │ ├── fragment │ │ │ ├── FragmentDatabaseList.java │ │ │ ├── FragmentFilesList.java │ │ │ └── FragmentTablesList.java │ │ │ ├── listener │ │ │ ├── DatabaseListListener.java │ │ │ ├── FilesListListener.java │ │ │ └── TableContentListener.java │ │ │ └── utils │ │ │ ├── DBUtils.java │ │ │ ├── FileProvider.java │ │ │ └── FixedGridLayoutManager.java │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_file.png │ │ └── ic_folder.png │ │ ├── drawable-mdpi │ │ ├── ic_file.png │ │ └── ic_folder.png │ │ ├── drawable-v21 │ │ ├── ic_menu_camera.xml │ │ ├── ic_menu_gallery.xml │ │ ├── ic_menu_manage.xml │ │ ├── ic_menu_send.xml │ │ ├── ic_menu_share.xml │ │ └── ic_menu_slideshow.xml │ │ ├── drawable-xhdpi │ │ ├── ic_file.png │ │ └── ic_folder.png │ │ ├── drawable-xxhdpi │ │ ├── ic_file.png │ │ └── ic_folder.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_file.png │ │ └── ic_folder.png │ │ ├── drawable │ │ ├── edittext_drawable.xml │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_drawer.xml │ │ ├── activity_shared_preference.xml │ │ ├── app_bar_drawer.xml │ │ ├── content_drawer.xml │ │ ├── fragment_list.xml │ │ ├── item_database_list.xml │ │ ├── item_shared_preference.xml │ │ ├── item_simple_list.xml │ │ ├── item_table_content.xml │ │ ├── main_activity.xml │ │ ├── nav_header_drawer.xml │ │ └── table_activity.xml │ │ ├── menu │ │ ├── drawer.xml │ │ └── menu_drawer.xml │ │ ├── mipmap-hdpi │ │ └── ic_android_robot.png │ │ ├── mipmap-mdpi │ │ └── ic_android_robot.png │ │ ├── mipmap-xhdpi │ │ └── ic_android_robot.png │ │ ├── mipmap-xxhdpi │ │ └── ic_android_robot.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_android_robot.png │ │ ├── values-v21 │ │ └── styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── krishna │ └── debug_tools │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── database list.png ├── drawer.png ├── sharedPreference.png ├── table content.png └── table list.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android-Debug-Tools 2 | [![Android Arsenal]( https://img.shields.io/badge/Android%20Arsenal-Android%20Debug%20Tools-green.svg?style=flat )]( https://android-arsenal.com/details/1/6828 ) [![](https://jitpack.io/v/kk121/Android-Debug-Tools.svg)](https://jitpack.io/#kk121/Android-Debug-Tools) 3 |
4 | ### Android library for debugging, Sqlite Databases, SharedPreferences and all types of files stored in internal storage directory, right from the app. 5 | 6 | ## What it does? 7 | * View all Sqlite database with version. 8 | * View all Tables and it's contents in a Database. 9 | * View all SharedPreferences. 10 | * View all files(image, pdf, json, txt etc) stored in internal directory of the app. 11 | 12 | ## Download 13 | ### Gradle: 14 | ```sh 15 | repositories { 16 | mavenCentral() 17 | maven { url 'https://jitpack.io' } 18 | } 19 | 20 | dependencies { 21 | //include in debug build only 22 | debugCompile 'com.github.kk121:Android-Debug-Tools:1.0' 23 | } 24 | 25 | ``` 26 | ### or Maven: 27 | ```sh 28 | 29 | com.github.kk121 30 | Android-Debug-Tools 31 | 1.0 32 | 33 | ``` 34 | 35 | ## Using Android-Debug-Tools in your Application? 36 | ```sh 37 | //start the ActivityDebugTools activity from your activity, that's it 38 | startActivity(new Intent(this, ActivityDebugTools.class)); 39 | ``` 40 | 41 | ## Screenshots: 42 |         43 | 44 | ### Tables 45 |         46 | 47 | ### SharedPreference 48 | 49 | 50 | ## Upcoming Features: 51 | * Edit, delete database tables 52 | * Edit sharedPreferences 53 | * Delete, add, or create files in internal storage directory 54 | 55 | ## Find this library useful ? :heart: 56 | * Support it by clicking the :star: 57 | 58 | ## License 59 | ``` 60 | Copyright (C) 2018 Krishna Kumar 61 | 62 | Licensed under the Apache License, Version 2.0 (the "License"); 63 | you may not use this file except in compliance with the License. 64 | You may obtain a copy of the License at 65 | 66 | http://www.apache.org/licenses/LICENSE-2.0 67 | 68 | Unless required by applicable law or agreed to in writing, software 69 | distributed under the License is distributed on an "AS IS" BASIS, 70 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 71 | See the License for the specific language governing permissions and 72 | limitations under the License. 73 | ``` 74 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.krishna.devtoolsdemo" 7 | minSdkVersion 14 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(include: ['*.jar'], dir: 'libs') 23 | implementation 'com.android.support:appcompat-v7:26.1.0' 24 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 28 | implementation project(':debug_tools') 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/krishna/debug_tools_demo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools_demo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.krishna.devtoolsdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/krishna/debug_tools_demo/DBHelper.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools_demo; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.sqlite.SQLiteDatabase; 6 | import android.database.sqlite.SQLiteOpenHelper; 7 | 8 | /** 9 | * Created by krishna on 05/02/18. 10 | */ 11 | public class DBHelper extends SQLiteOpenHelper { 12 | private static DBHelper sInstance; 13 | //SQL String for creating the table required 14 | private static final String CREATE_SETTINGS_TABLE 15 | = "CREATE TABLE tbl_settings(" + 16 | "_ID INTEGER PRIMARY KEY AUTOINCREMENT," + 17 | "VOIPUSERNAME TEXT," + 18 | "VOIPAUTHID TEXT," + 19 | "PASSWORD TEXT," + 20 | "VOIPDISPLAYNAME TEXT," + 21 | "SIPPROXYSERVER TEXT," + 22 | "SIPREGISTRAR TEXT," + 23 | "SIPREALM TEXT," + 24 | "EXPIRESTIME INTEGER);"; 25 | 26 | //constructor 27 | public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { 28 | super(context, name, factory, version); 29 | } 30 | 31 | public static DBHelper getInstance(Context context) { 32 | if (sInstance == null) { 33 | sInstance = new DBHelper(context, "dummy.db", null, 2); 34 | } 35 | return sInstance; 36 | } 37 | 38 | @Override 39 | public void onCreate(SQLiteDatabase db) { 40 | db.execSQL(CREATE_SETTINGS_TABLE); 41 | for (int i = 0; i < 500; i++) { 42 | ContentValues initialValues = new ContentValues(); 43 | initialValues.put("VOIPUSERNAME", "xxxxx"); 44 | initialValues.put("VOIPAUTHID", "xxxxxxxxxx"); 45 | initialValues.put("PASSWORD", "xxxxxx"); 46 | initialValues.put("VOIPDISPLAYNAME", "xxxxxxxxx"); 47 | initialValues.put("SIPPROXYSERVER", "xxxxxxxxxxxxx"); 48 | initialValues.put("SIPREGISTRAR", "xxxxxxxxxxx"); 49 | initialValues.put("SIPREALM", "xxxxxxxxxx"); 50 | initialValues.put("EXPIRESTIME", 876877587); 51 | db.insert("tbl_settings", null, initialValues); 52 | } 53 | } 54 | 55 | @Override 56 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 57 | db.execSQL("DROP TABLE IF EXISTS " + "tbl_settings"); 58 | onCreate(db); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/krishna/debug_tools_demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools_demo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | public class MainActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_main); 13 | //create a dummy db 14 | DBHelper.getInstance(this).getReadableDatabase(); 15 | 16 | startActivity(new Intent("com.krishna.debug_tools")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | DevToolsDemo 3 | com.krishna.debug_tools 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/krishna/debug_tools_demo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools_demo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.1' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /debug_tools/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /debug_tools/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | //publish to maven 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | group='com.github.kk121' 5 | 6 | android { 7 | compileSdkVersion 26 8 | 9 | defaultConfig { 10 | minSdkVersion 14 11 | targetSdkVersion 26 12 | versionCode 1 13 | versionName "1.0" 14 | vectorDrawables.useSupportLibrary true 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(include: ['*.jar'], dir: 'libs') 30 | implementation 'com.android.support:appcompat-v7:26.1.0' 31 | implementation 'com.android.support:recyclerview-v7:26.1.0' 32 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 33 | testImplementation 'junit:junit:4.12' 34 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 35 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 36 | implementation 'com.android.support:design:26.1.0' 37 | } 38 | 39 | buildscript { 40 | repositories { 41 | mavenCentral() 42 | } 43 | 44 | dependencies { 45 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' 46 | } 47 | } -------------------------------------------------------------------------------- /debug_tools/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /debug_tools/src/androidTest/java/com/krishna/debug_tools/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.krishna.devtools.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /debug_tools/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /debug_tools/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/activity/ActivityDebugTools.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.activity; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.design.widget.NavigationView; 7 | import android.support.v4.view.GravityCompat; 8 | import android.support.v4.widget.DrawerLayout; 9 | import android.support.v7.app.ActionBarDrawerToggle; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.support.v7.widget.Toolbar; 12 | import android.view.Menu; 13 | import android.view.MenuItem; 14 | 15 | import com.krishna.debug_tools.R; 16 | import com.krishna.debug_tools.data.pojo.DBPojo; 17 | import com.krishna.debug_tools.data.pojo.Table; 18 | import com.krishna.debug_tools.fragment.FragmentDatabaseList; 19 | import com.krishna.debug_tools.fragment.FragmentFilesList; 20 | import com.krishna.debug_tools.fragment.FragmentTablesList; 21 | import com.krishna.debug_tools.utils.DBUtils; 22 | 23 | import java.io.File; 24 | 25 | public class ActivityDebugTools extends AppCompatActivity 26 | implements NavigationView.OnNavigationItemSelectedListener, FragmentDatabaseList.Communicator, 27 | FragmentFilesList.Communicator, FragmentTablesList.Communicator { 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_drawer); 33 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 34 | setSupportActionBar(toolbar); 35 | 36 | changeToolbarTitle("Database"); 37 | showAllDatabaseFragment(); 38 | 39 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 40 | ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( 41 | this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 42 | drawer.addDrawerListener(toggle); 43 | toggle.syncState(); 44 | 45 | NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 46 | navigationView.setNavigationItemSelectedListener(this); 47 | navigationView.setCheckedItem(R.id.nav_database); 48 | } 49 | 50 | @Override 51 | public void onBackPressed() { 52 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 53 | if (drawer.isDrawerOpen(GravityCompat.START)) { 54 | drawer.closeDrawer(GravityCompat.START); 55 | } else { 56 | super.onBackPressed(); 57 | } 58 | } 59 | 60 | @Override 61 | public boolean onCreateOptionsMenu(Menu menu) { 62 | // Inflate the menu; this adds items to the action bar if it is present. 63 | // getMenuInflater().inflate(R.menu.drawer, menu); 64 | return true; 65 | } 66 | 67 | @Override 68 | public boolean onOptionsItemSelected(MenuItem item) { 69 | int id = item.getItemId(); 70 | if (id == R.id.action_settings) { 71 | return true; 72 | } 73 | 74 | return super.onOptionsItemSelected(item); 75 | } 76 | 77 | @SuppressWarnings("StatementWithEmptyBody") 78 | @Override 79 | public boolean onNavigationItemSelected(MenuItem item) { 80 | // Handle navigation view item clicks here. 81 | int id = item.getItemId(); 82 | 83 | if (id == R.id.nav_database) { 84 | changeToolbarTitle("Database"); 85 | getSupportFragmentManager().popBackStackImmediate(); 86 | showAllDatabaseFragment(); 87 | } else if (id == R.id.nav_shared_pref) { 88 | getSupportFragmentManager().popBackStackImmediate(); 89 | changeToolbarTitle("SharedPreference"); 90 | showAllSharedPreferencesFragment(); 91 | } else if (id == R.id.nav_files) { 92 | getSupportFragmentManager().popBackStackImmediate(); 93 | changeToolbarTitle("Files"); 94 | showAllFilesFragment(DBUtils.getFilesPath(ActivityDebugTools.this), false); 95 | } else if (id == R.id.nav_all) { 96 | getSupportFragmentManager().popBackStackImmediate(); 97 | changeToolbarTitle("All"); 98 | showOtherFiles(); 99 | } else if (id == R.id.nav_share) { 100 | 101 | } else if (id == R.id.nav_send) { 102 | 103 | } 104 | 105 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 106 | drawer.closeDrawer(GravityCompat.START); 107 | return true; 108 | } 109 | 110 | private void changeToolbarTitle(String title) { 111 | getSupportActionBar().setTitle(title); 112 | } 113 | 114 | private void showAllDatabaseFragment() { 115 | getSupportFragmentManager().beginTransaction() 116 | .replace(R.id.fragment_container, new FragmentDatabaseList()).commit(); 117 | } 118 | 119 | private void showAllSharedPreferencesFragment() { 120 | String sharedPrefPath = DBUtils.getSharedPrefsPath(this); 121 | getSupportFragmentManager().beginTransaction() 122 | .replace(R.id.fragment_container, FragmentFilesList.newInstance(FragmentFilesList.TYPE_SHARED_PREF, sharedPrefPath)).commit(); 123 | } 124 | 125 | private void showAllFilesFragment(String filePath, boolean addToBackStack) { 126 | if (addToBackStack) { 127 | getSupportFragmentManager().beginTransaction() 128 | .replace(R.id.fragment_container, FragmentFilesList.newInstance(FragmentFilesList.TYPE_FILES, filePath)).addToBackStack(FragmentFilesList.TAG).commit(); 129 | } else { 130 | getSupportFragmentManager().beginTransaction() 131 | .replace(R.id.fragment_container, FragmentFilesList.newInstance(FragmentFilesList.TYPE_FILES, filePath)).commit(); 132 | } 133 | } 134 | 135 | private void showOtherFiles() { 136 | String path = DBUtils.getAppPath(this); 137 | showAllFilesFragment(path, false); 138 | } 139 | 140 | /* 141 | Callbacks from fragments 142 | */ 143 | @Override 144 | public void showListOfTables(DBPojo dbPojo) { 145 | getSupportFragmentManager().beginTransaction() 146 | .replace(R.id.fragment_container, FragmentTablesList.newInstance(dbPojo)).addToBackStack(FragmentTablesList.TAG).commit(); 147 | changeToolbarTitle("Tables"); 148 | } 149 | 150 | @Override 151 | public void onFileClick(int fileType, File file) { 152 | if (fileType == FragmentFilesList.TYPE_FILES) { 153 | if (file.isDirectory()) { 154 | showAllFilesFragment(file.getPath(), true); 155 | } else { 156 | //handle file click 157 | openFileInExternalApp(file); 158 | } 159 | } else { 160 | //start shared preference activity 161 | Intent intent = new Intent(this, ActivitySharedPreference.class); 162 | intent.putExtra(ActivitySharedPreference.EXTRA_PATH, file.getPath()); 163 | startActivity(intent); 164 | } 165 | } 166 | 167 | @Override 168 | public void onTableSelected(Table table) { 169 | Intent intent = new Intent(this, ActivityTable.class); 170 | intent.putExtra(ActivityTable.EXTRA_TABLE, table); 171 | startActivity(intent); 172 | } 173 | 174 | private void openFileInExternalApp(File file) { 175 | Intent intent = new Intent(Intent.ACTION_VIEW); 176 | String absoluteFilePath = file.getAbsolutePath(); 177 | Uri fileUri = Uri.parse("content://" + getString(R.string.provider_authority) + "/" + absoluteFilePath); 178 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 179 | intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 180 | String mimeType = DBUtils.getMimeType(file.getPath()); 181 | intent.setDataAndType(fileUri, mimeType); 182 | startActivity(intent); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/activity/ActivitySharedPreference.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.View; 8 | import android.widget.AdapterView; 9 | import android.widget.ListView; 10 | 11 | import com.krishna.debug_tools.utils.DBUtils; 12 | import com.krishna.debug_tools.R; 13 | import com.krishna.debug_tools.adapter.SharedPreferenceAdapter; 14 | 15 | import java.io.File; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * Created by krishna on 04/02/18. 21 | */ 22 | 23 | public class ActivitySharedPreference extends AppCompatActivity implements AdapterView.OnItemClickListener { 24 | public static final String EXTRA_PATH = "file_path"; 25 | 26 | @Override 27 | protected void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_shared_preference); 30 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 31 | setSupportActionBar(toolbar); 32 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 33 | 34 | ListView listView = findViewById(R.id.listview); 35 | listView.setOnItemClickListener(this); 36 | listView.setEmptyView(findViewById(R.id.tv_empty_state)); 37 | 38 | String sharedPrefFilePath = getIntent().getStringExtra(EXTRA_PATH); 39 | getSupportActionBar().setTitle(new File(sharedPrefFilePath).getName()); 40 | 41 | List> data = DBUtils.getSharedPreferences(sharedPrefFilePath); 42 | SharedPreferenceAdapter adapter = new SharedPreferenceAdapter(data); 43 | listView.setAdapter(adapter); 44 | } 45 | 46 | @Override 47 | public boolean onSupportNavigateUp() { 48 | finish(); 49 | return super.onSupportNavigateUp(); 50 | } 51 | 52 | @Override 53 | public void onItemClick(AdapterView parent, View view, int position, long id) { 54 | // Toast.makeText(this, "Position: " + position, Toast.LENGTH_SHORT).show(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/activity/ActivityTable.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.activity; 2 | 3 | import android.database.Cursor; 4 | import android.graphics.Color; 5 | import android.graphics.Typeface; 6 | import android.os.AsyncTask; 7 | import android.os.Bundle; 8 | import android.support.annotation.Nullable; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.support.v7.widget.LinearLayoutManager; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.support.v7.widget.Toolbar; 13 | import android.util.TypedValue; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.widget.LinearLayout; 17 | import android.widget.TextView; 18 | 19 | import com.krishna.debug_tools.R; 20 | import com.krishna.debug_tools.adapter.TableContentRecyclerAdapter; 21 | import com.krishna.debug_tools.adapter.TableContentViewHolder; 22 | import com.krishna.debug_tools.async_task.TableContentTask; 23 | import com.krishna.debug_tools.data.pojo.Table; 24 | import com.krishna.debug_tools.listener.TableContentListener; 25 | 26 | /** 27 | * Created by krishna on 14/01/18. 28 | */ 29 | 30 | public class ActivityTable extends AppCompatActivity implements TableContentListener { 31 | public static final String EXTRA_TABLE = "table"; 32 | private RecyclerView recyclerView; 33 | 34 | @Override 35 | protected void onCreate(@Nullable Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.table_activity); 38 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 39 | setSupportActionBar(toolbar); 40 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 41 | recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 42 | recyclerView.setHasFixedSize(true); 43 | fetchContentOfTable(); 44 | } 45 | 46 | private void fetchContentOfTable() { 47 | Table table = (Table) getIntent().getSerializableExtra(EXTRA_TABLE); 48 | if (table != null) { 49 | getSupportActionBar().setTitle(table.getTableName()); 50 | new TableContentTask(this, table, this) 51 | .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 52 | } 53 | } 54 | 55 | @Override 56 | public boolean onSupportNavigateUp() { 57 | finish(); 58 | return super.onSupportNavigateUp(); 59 | } 60 | 61 | @Override 62 | public void onTableContentFetched(Cursor cursor) { 63 | if (cursor != null) { 64 | addTableHeaders(cursor); 65 | TableContentRecyclerAdapter adapter = new TableContentRecyclerAdapter(cursor); 66 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 67 | recyclerView.setAdapter(adapter); 68 | } else { 69 | findViewById(R.id.tv_empty_state).setVisibility(View.VISIBLE); 70 | } 71 | } 72 | 73 | private void addTableHeaders(Cursor cursor) { 74 | cursor.moveToFirst(); 75 | ViewGroup headerLayout = findViewById(R.id.table_header); 76 | int margin = (int) getResources().getDimension(R.dimen.margin_4dp); 77 | for (int i = 0; i < cursor.getColumnCount(); i++) { 78 | TextView textView = new TextView(this); 79 | textView.setText(cursor.getColumnName(i)); 80 | textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12); 81 | textView.setTextColor(Color.BLACK); 82 | textView.setTypeface(textView.getTypeface(), Typeface.BOLD); 83 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(TableContentViewHolder.getColumnWidth(this, cursor.getType(i)), ViewGroup.LayoutParams.WRAP_CONTENT); 84 | lp.setMargins(margin, 0, margin, 0); 85 | headerLayout.addView(textView, lp); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/adapter/DatabaseListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.adapter; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.BaseAdapter; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import com.krishna.debug_tools.data.pojo.DBPojo; 11 | import com.krishna.debug_tools.R; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Created by krishna on 12/01/18. 17 | */ 18 | 19 | public class DatabaseListAdapter extends BaseAdapter { 20 | public static final int SHOW_DATABASE_LIST = 1; 21 | public static final int SHOW_TABLES_LIST = 2; 22 | private List dbPojoList; 23 | private int itemType; 24 | 25 | public DatabaseListAdapter(List dbPojoList, int itemType) { 26 | this.dbPojoList = dbPojoList; 27 | this.itemType = itemType; 28 | } 29 | 30 | @Override 31 | public int getCount() { 32 | if (dbPojoList != null) 33 | return dbPojoList.size(); 34 | return 0; 35 | } 36 | 37 | @Override 38 | public DBPojo getItem(int position) { 39 | return dbPojoList.get(position); 40 | } 41 | 42 | @Override 43 | public long getItemId(int position) { 44 | return 0; 45 | } 46 | 47 | @Override 48 | public View getView(int position, View convertView, ViewGroup parent) { 49 | View view = convertView; 50 | if (view == null) { 51 | view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_database_list, parent, false); 52 | } 53 | TextView tvName = view.findViewById(R.id.tv_db_name); 54 | TextView tvVersion = view.findViewById(R.id.tv_db_version); 55 | ImageView ivIcon = view.findViewById(R.id.iv_icon); 56 | tvName.setText(getItem(position).getDbName()); 57 | if (itemType == SHOW_DATABASE_LIST) { 58 | tvVersion.setText("version " + String.valueOf(getItem(position).getDbVersion())); 59 | } else { 60 | tvVersion.setVisibility(View.GONE); 61 | } 62 | ivIcon.setImageResource(R.drawable.ic_file); 63 | return view; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/adapter/SharedPreferenceAdapter.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.adapter; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.BaseAdapter; 7 | import android.widget.TextView; 8 | 9 | import com.krishna.debug_tools.R; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * Created by krishna on 12/01/18. 16 | */ 17 | 18 | public class SharedPreferenceAdapter extends BaseAdapter { 19 | private List> data; 20 | 21 | public SharedPreferenceAdapter(List> data) { 22 | this.data = data; 23 | } 24 | 25 | @Override 26 | public int getCount() { 27 | return data != null ? data.size() : 0; 28 | } 29 | 30 | @Override 31 | public Map.Entry getItem(int position) { 32 | return data.get(position); 33 | } 34 | 35 | @Override 36 | public long getItemId(int position) { 37 | return 0; 38 | } 39 | 40 | @Override 41 | public View getView(int position, View convertView, ViewGroup parent) { 42 | View view = convertView; 43 | if (view == null) { 44 | view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_shared_preference, parent, false); 45 | } 46 | TextView tvKey = view.findViewById(R.id.tv_key); 47 | TextView tvValue = view.findViewById(R.id.tv_value); 48 | tvKey.setText(getItem(position).getKey()); 49 | tvValue.setText(getItem(position).getValue()); 50 | return view; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/adapter/SimpleListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.adapter; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.BaseAdapter; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import com.krishna.debug_tools.utils.DBUtils; 11 | import com.krishna.debug_tools.fragment.FragmentFilesList; 12 | import com.krishna.debug_tools.R; 13 | 14 | import java.io.File; 15 | import java.util.List; 16 | 17 | /** 18 | * Created by krishna on 12/01/18. 19 | */ 20 | 21 | public class SimpleListAdapter extends BaseAdapter { 22 | private List data; 23 | private int fileType; 24 | 25 | public SimpleListAdapter(int fileType, List data) { 26 | this.fileType = fileType; 27 | this.data = data; 28 | } 29 | 30 | @Override 31 | public int getCount() { 32 | return data != null ? data.size() : 0; 33 | } 34 | 35 | @Override 36 | public File getItem(int position) { 37 | return data.get(position); 38 | } 39 | 40 | @Override 41 | public long getItemId(int position) { 42 | return 0; 43 | } 44 | 45 | @Override 46 | public View getView(int position, View convertView, ViewGroup parent) { 47 | View view = convertView; 48 | if (view == null) { 49 | view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_simple_list, parent, false); 50 | } 51 | TextView tvName = view.findViewById(R.id.tv_name); 52 | ImageView ivIcon = view.findViewById(R.id.iv_icon); 53 | String fileName = getItem(position).getName(); 54 | if (fileType == FragmentFilesList.TYPE_SHARED_PREF) { 55 | fileName = DBUtils.removePackageFromFileName(fileName); 56 | } 57 | tvName.setText(fileName); 58 | //set icon 59 | if (getItem(position).isDirectory()) { 60 | ivIcon.setImageResource(R.drawable.ic_folder); 61 | } else { 62 | ivIcon.setImageResource(R.drawable.ic_file); 63 | } 64 | return view; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/adapter/TableContentRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.adapter; 2 | 3 | import android.database.Cursor; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.krishna.debug_tools.R; 10 | 11 | /** 12 | * Created by krishna on 14/01/18. 13 | */ 14 | 15 | public class TableContentRecyclerAdapter extends RecyclerView.Adapter { 16 | private Cursor cursor; 17 | 18 | public TableContentRecyclerAdapter(Cursor cursor) { 19 | this.cursor = cursor; 20 | } 21 | 22 | @Override 23 | public TableContentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 24 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_table_content, parent, false); 25 | return new TableContentViewHolder(view, cursor); 26 | } 27 | 28 | @Override 29 | public void onBindViewHolder(TableContentViewHolder holder, int position) { 30 | holder.bindView(position, cursor); 31 | } 32 | 33 | @Override 34 | public int getItemCount() { 35 | if (cursor != null && cursor.moveToFirst()) 36 | return cursor.getCount(); 37 | return 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/adapter/TableContentViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.adapter; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.graphics.Color; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.text.Editable; 8 | import android.text.TextWatcher; 9 | import android.util.TypedValue; 10 | import android.view.MenuItem; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.EditText; 14 | import android.widget.LinearLayout; 15 | import android.widget.PopupMenu; 16 | import android.widget.TextView; 17 | 18 | import com.krishna.debug_tools.R; 19 | 20 | 21 | /** 22 | * Created by krishna on 14/01/18. 23 | */ 24 | 25 | public class TableContentViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, TextWatcher { 26 | private int colorWhite; 27 | private int colorLightGray; 28 | 29 | public TableContentViewHolder(View itemView, Cursor cursor) { 30 | super(itemView); 31 | colorWhite = Color.WHITE; 32 | colorLightGray = itemView.getResources().getColor(R.color.colorGrayLight); 33 | cursor.moveToFirst(); 34 | int margin = (int) itemView.getResources().getDimension(R.dimen.margin_4dp); 35 | for (int i = 0; i < cursor.getColumnCount(); i++) { 36 | TextView editText = new EditText(itemView.getContext()); 37 | editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12); 38 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(getColumnWidth(itemView.getContext(), cursor.getType(i)), ViewGroup.LayoutParams.WRAP_CONTENT); 39 | lp.setMargins(margin, 0, margin, 0); 40 | ((ViewGroup) itemView).addView(editText, lp); 41 | editText.addTextChangedListener(this); 42 | } 43 | } 44 | 45 | public static int getColumnWidth(Context context, int columnType) { 46 | switch (columnType) { 47 | case Cursor.FIELD_TYPE_INTEGER: 48 | case Cursor.FIELD_TYPE_FLOAT: 49 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90, context.getResources().getDisplayMetrics()); 50 | case Cursor.FIELD_TYPE_STRING: 51 | case Cursor.FIELD_TYPE_BLOB: 52 | case Cursor.FIELD_TYPE_NULL: 53 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200, context.getResources().getDisplayMetrics()); 54 | } 55 | return ViewGroup.LayoutParams.WRAP_CONTENT; 56 | } 57 | 58 | public void bindView(int position, Cursor cursor) { 59 | if (cursor.moveToPosition(position)) { 60 | ViewGroup row = (ViewGroup) itemView; 61 | for (int i = 0; i < cursor.getColumnCount(); i++) { 62 | TextView editText = (TextView) row.getChildAt(i); 63 | editText.setText(cursor.getString(i)); 64 | editText.setTextColor(Color.GRAY); 65 | editText.setBackgroundDrawable(null); 66 | editText.setFocusableInTouchMode(false); 67 | editText.setOnLongClickListener(this); 68 | } 69 | if (position % 2 == 0) { 70 | row.setBackgroundColor(colorWhite); 71 | } else { 72 | row.setBackgroundColor(colorLightGray); 73 | } 74 | } 75 | } 76 | 77 | @Override 78 | public boolean onLongClick(View v) { 79 | PopupMenu popupMenu = new PopupMenu(itemView.getContext(), v); 80 | popupMenu.getMenu().add(0, 1, 1, "Edit"); 81 | popupMenu.getMenu().add(0, 2, 2, "Delete"); 82 | popupMenu.setOnMenuItemClickListener(this); 83 | popupMenu.show(); 84 | return true; 85 | } 86 | 87 | @Override 88 | public boolean onMenuItemClick(MenuItem item) { 89 | if (item.getItemId() == 1) { 90 | ViewGroup row = (ViewGroup) itemView; 91 | for (int i = 0; i < row.getChildCount(); i++) { 92 | View column = row.getChildAt(i); 93 | column.setFocusableInTouchMode(true); 94 | column.setBackgroundResource(R.drawable.edittext_drawable); 95 | } 96 | } else if (item.getItemId() == 2) { 97 | 98 | } 99 | return true; 100 | } 101 | 102 | @Override 103 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 104 | 105 | } 106 | 107 | @Override 108 | public void onTextChanged(CharSequence s, int start, int before, int count) { 109 | 110 | } 111 | 112 | @Override 113 | public void afterTextChanged(Editable s) { 114 | 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/async_task/DatabaseListTask.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.async_task; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | 6 | import com.krishna.debug_tools.listener.DatabaseListListener; 7 | import com.krishna.debug_tools.data.pojo.DBPojo; 8 | import com.krishna.debug_tools.utils.DBUtils; 9 | 10 | import java.lang.ref.WeakReference; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by krishna on 12/01/18. 15 | */ 16 | public class DatabaseListTask extends AsyncTask> { 17 | private static final String TAG = "DatabaseListTask"; 18 | private WeakReference contextWeakReference; 19 | private DatabaseListListener databaseListListener; 20 | 21 | public DatabaseListTask(Context context, DatabaseListListener databaseListListener) { 22 | contextWeakReference = new WeakReference<>(context); 23 | this.databaseListListener = databaseListListener; 24 | } 25 | 26 | @Override 27 | protected List doInBackground(Void... voids) { 28 | return DBUtils.getAllDatabases(contextWeakReference.get()); 29 | } 30 | 31 | @Override 32 | protected void onPostExecute(List dbPojos) { 33 | super.onPostExecute(dbPojos); 34 | if (databaseListListener != null) 35 | databaseListListener.onDatabaseListFetched(dbPojos); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/async_task/FilesListTask.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.async_task; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | 6 | import com.krishna.debug_tools.listener.FilesListListener; 7 | 8 | import java.io.File; 9 | import java.lang.ref.WeakReference; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by krishna on 12/01/18. 14 | */ 15 | public class FilesListTask extends AsyncTask> { 16 | private WeakReference contextWeakReference; 17 | private FilesListListener filesListListener; 18 | 19 | public FilesListTask(Context context, FilesListListener filesListListener) { 20 | contextWeakReference = new WeakReference<>(context); 21 | this.filesListListener = filesListListener; 22 | } 23 | 24 | @Override 25 | protected List doInBackground(Void... voids) { 26 | // return DBUtils.getAllSharedPreferences(contextWeakReference.get()); 27 | return null; 28 | } 29 | 30 | @Override 31 | protected void onPostExecute(List dbPojos) { 32 | super.onPostExecute(dbPojos); 33 | if (filesListListener != null) 34 | filesListListener.onFilesListFetched(dbPojos); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/async_task/TableContentTask.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.async_task; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.os.AsyncTask; 6 | 7 | import com.krishna.debug_tools.listener.TableContentListener; 8 | import com.krishna.debug_tools.data.pojo.Table; 9 | import com.krishna.debug_tools.utils.DBUtils; 10 | 11 | import java.lang.ref.WeakReference; 12 | 13 | /** 14 | * Created by krishna on 12/01/18. 15 | */ 16 | public class TableContentTask extends AsyncTask { 17 | private static final String TAG = "DatabaseListTask"; 18 | private WeakReference contextWeakReference; 19 | private TableContentListener tableContentListener; 20 | private Table table; 21 | 22 | public TableContentTask(Context context, Table table, TableContentListener tableContentListener) { 23 | contextWeakReference = new WeakReference<>(context); 24 | this.tableContentListener = tableContentListener; 25 | this.table = table; 26 | } 27 | 28 | @Override 29 | protected Cursor doInBackground(Void... voids) { 30 | return DBUtils.getContentsOfTable(contextWeakReference.get(), table); 31 | } 32 | 33 | @Override 34 | protected void onPostExecute(Cursor cursor) { 35 | super.onPostExecute(cursor); 36 | if (tableContentListener != null) 37 | tableContentListener.onTableContentFetched(cursor); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/async_task/TableListTask.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.async_task; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | 6 | import com.krishna.debug_tools.listener.DatabaseListListener; 7 | import com.krishna.debug_tools.data.pojo.DBPojo; 8 | import com.krishna.debug_tools.utils.DBUtils; 9 | 10 | import java.lang.ref.WeakReference; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by krishna on 12/01/18. 15 | */ 16 | public class TableListTask extends AsyncTask> { 17 | private static final String TAG = "DatabaseListTask"; 18 | private WeakReference contextWeakReference; 19 | private DatabaseListListener databaseListListener; 20 | private DBPojo dbPojo; 21 | 22 | public TableListTask(Context context, DBPojo dbPojo, DatabaseListListener databaseListListener) { 23 | contextWeakReference = new WeakReference<>(context); 24 | this.databaseListListener = databaseListListener; 25 | this.dbPojo = dbPojo; 26 | } 27 | 28 | @Override 29 | protected List doInBackground(Void... voids) { 30 | return DBUtils.getAllTablesFromDb(contextWeakReference.get(), dbPojo); 31 | } 32 | 33 | @Override 34 | protected void onPostExecute(List dbPojos) { 35 | super.onPostExecute(dbPojos); 36 | if (databaseListListener != null) 37 | databaseListListener.onDatabaseListFetched(dbPojos); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/data/DBOpenHelper.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.data; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteOpenHelper; 6 | 7 | /** 8 | * Created by krishna on 12/01/18. 9 | */ 10 | 11 | public class DBOpenHelper extends SQLiteOpenHelper { 12 | 13 | public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { 14 | super(context, name, factory, version); 15 | } 16 | 17 | @Override 18 | public void onCreate(SQLiteDatabase db) { 19 | 20 | } 21 | 22 | @Override 23 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/data/pojo/DBPojo.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.data.pojo; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by krishna on 12/01/18. 7 | */ 8 | 9 | public class DBPojo implements Serializable { 10 | private int dbVersion; 11 | private String dbName; 12 | 13 | public DBPojo() { 14 | } 15 | 16 | public DBPojo(int dbVersion, String dbName) { 17 | this.dbVersion = dbVersion; 18 | this.dbName = dbName; 19 | } 20 | 21 | public int getDbVersion() { 22 | return dbVersion; 23 | } 24 | 25 | public void setDbVersion(int dbVersion) { 26 | this.dbVersion = dbVersion; 27 | } 28 | 29 | public String getDbName() { 30 | return dbName; 31 | } 32 | 33 | public void setDbName(String dbName) { 34 | this.dbName = dbName; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "DBPojo{" + 40 | "dbVersion=" + dbVersion + 41 | ", dbName='" + dbName + '\'' + 42 | '}'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/data/pojo/Table.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.data.pojo; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by krishna on 14/01/18. 7 | */ 8 | 9 | public class Table implements Serializable{ 10 | private String tableName; 11 | private DBPojo dbPojo; 12 | 13 | public String getTableName() { 14 | return tableName; 15 | } 16 | 17 | public void setTableName(String tableName) { 18 | this.tableName = tableName; 19 | } 20 | 21 | public DBPojo getDbPojo() { 22 | return dbPojo; 23 | } 24 | 25 | public void setDbPojo(DBPojo dbPojo) { 26 | this.dbPojo = dbPojo; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/fragment/FragmentDatabaseList.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.fragment; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.AdapterView; 12 | import android.widget.ListView; 13 | 14 | import com.krishna.debug_tools.data.pojo.DBPojo; 15 | import com.krishna.debug_tools.listener.DatabaseListListener; 16 | import com.krishna.debug_tools.async_task.DatabaseListTask; 17 | import com.krishna.debug_tools.R; 18 | import com.krishna.debug_tools.adapter.DatabaseListAdapter; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Created by krishna on 12/01/18. 24 | */ 25 | 26 | public class FragmentDatabaseList extends Fragment implements AdapterView.OnItemClickListener { 27 | private ListView listView; 28 | private Communicator communicator; 29 | 30 | @Override 31 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 32 | View view = inflater.inflate(R.layout.fragment_list, container, false); 33 | listView = view.findViewById(R.id.listview); 34 | listView.setOnItemClickListener(this); 35 | 36 | DatabaseListListener databaseListListener = new DatabaseListListener() { 37 | @Override 38 | public void onDatabaseListFetched(List dbPojoList) { 39 | DatabaseListAdapter adapter = new DatabaseListAdapter(dbPojoList, DatabaseListAdapter.SHOW_DATABASE_LIST); 40 | listView.setAdapter(adapter); 41 | } 42 | }; 43 | 44 | new DatabaseListTask(getContext(), databaseListListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 45 | 46 | return view; 47 | } 48 | 49 | @Override 50 | public void onItemClick(AdapterView parent, View view, int position, long id) { 51 | if (communicator != null) { 52 | DBPojo dbPojo = (DBPojo) parent.getItemAtPosition(position); 53 | communicator.showListOfTables(dbPojo); 54 | } 55 | } 56 | 57 | @Override 58 | public void onAttach(Context context) { 59 | super.onAttach(context); 60 | communicator = (Communicator) context; 61 | } 62 | 63 | public interface Communicator { 64 | void showListOfTables(DBPojo dbPojo); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/fragment/FragmentFilesList.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.fragment; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.AdapterView; 11 | import android.widget.ListView; 12 | 13 | import com.krishna.debug_tools.utils.DBUtils; 14 | import com.krishna.debug_tools.R; 15 | import com.krishna.debug_tools.adapter.SimpleListAdapter; 16 | 17 | import java.io.File; 18 | 19 | /** 20 | * Created by krishna on 12/01/18. 21 | */ 22 | 23 | public class FragmentFilesList extends Fragment implements AdapterView.OnItemClickListener { 24 | public static final String TAG = "FragmentFilesList"; 25 | private static final String ARG_TYPE = "type"; 26 | private static final String ARG_FILE_PATH = "file_path"; 27 | public static final int TYPE_SHARED_PREF = 1; 28 | public static final int TYPE_FILES = 2; 29 | private int fileType; 30 | private Communicator communicator; 31 | 32 | public static FragmentFilesList newInstance(int fileType, String filePath) { 33 | Bundle args = new Bundle(); 34 | args.putInt(ARG_TYPE, fileType); 35 | args.putString(ARG_FILE_PATH, filePath); 36 | FragmentFilesList fragment = new FragmentFilesList(); 37 | fragment.setArguments(args); 38 | return fragment; 39 | } 40 | 41 | @Override 42 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 43 | View view = inflater.inflate(R.layout.fragment_list, container, false); 44 | ListView listView = view.findViewById(R.id.listview); 45 | listView.setOnItemClickListener(this); 46 | listView.setEmptyView(view.findViewById(R.id.tv_empty_state)); 47 | 48 | fileType = getArguments().getInt(ARG_TYPE); 49 | String filePath = getArguments().getString(ARG_FILE_PATH); 50 | SimpleListAdapter adapter = new SimpleListAdapter(fileType, DBUtils.getAllFilesInDirectory(filePath)); 51 | listView.setAdapter(adapter); 52 | 53 | return view; 54 | } 55 | 56 | @Override 57 | public void onItemClick(AdapterView parent, View view, int position, long id) { 58 | if (communicator != null) { 59 | File file = (File) parent.getItemAtPosition(position); 60 | communicator.onFileClick(fileType, file); 61 | } 62 | } 63 | 64 | @Override 65 | public void onAttach(Context context) { 66 | super.onAttach(context); 67 | communicator = (Communicator) context; 68 | } 69 | 70 | public interface Communicator { 71 | void onFileClick(int fileType, File file); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/fragment/FragmentTablesList.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.fragment; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.AdapterView; 12 | import android.widget.ListView; 13 | 14 | import com.krishna.debug_tools.data.pojo.DBPojo; 15 | import com.krishna.debug_tools.listener.DatabaseListListener; 16 | import com.krishna.debug_tools.R; 17 | import com.krishna.debug_tools.data.pojo.Table; 18 | import com.krishna.debug_tools.async_task.TableListTask; 19 | import com.krishna.debug_tools.adapter.DatabaseListAdapter; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * Created by krishna on 12/01/18. 25 | */ 26 | 27 | public class FragmentTablesList extends Fragment implements AdapterView.OnItemClickListener { 28 | public static final String TAG = "FragmentTablesList"; 29 | private static final String ARG_NAME = "name"; 30 | private ListView listView; 31 | private Communicator communicator; 32 | private DBPojo dbPojo; 33 | 34 | public static FragmentTablesList newInstance(DBPojo dbPojo) { 35 | Bundle args = new Bundle(); 36 | args.putSerializable(ARG_NAME, dbPojo); 37 | FragmentTablesList fragment = new FragmentTablesList(); 38 | fragment.setArguments(args); 39 | return fragment; 40 | } 41 | 42 | @Override 43 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 44 | View view = inflater.inflate(R.layout.fragment_list, container, false); 45 | listView = view.findViewById(R.id.listview); 46 | listView.setOnItemClickListener(this); 47 | listView.setEmptyView(view.findViewById(R.id.tv_empty_state)); 48 | 49 | DatabaseListListener databaseListListener = new DatabaseListListener() { 50 | @Override 51 | public void onDatabaseListFetched(List dbPojoList) { 52 | DatabaseListAdapter adapter = new DatabaseListAdapter(dbPojoList, DatabaseListAdapter.SHOW_TABLES_LIST); 53 | listView.setAdapter(adapter); 54 | } 55 | }; 56 | dbPojo = (DBPojo) getArguments().getSerializable(ARG_NAME); 57 | if (dbPojo != null) { 58 | new TableListTask(getContext(), dbPojo, databaseListListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 59 | } 60 | return view; 61 | } 62 | 63 | @Override 64 | public void onItemClick(AdapterView parent, View view, int position, long id) { 65 | if (communicator != null) { 66 | DBPojo tablePojo = (DBPojo) parent.getItemAtPosition(position); 67 | Table table = new Table(); 68 | table.setDbPojo(dbPojo); 69 | table.setTableName(tablePojo.getDbName()); 70 | communicator.onTableSelected(table); 71 | } 72 | } 73 | 74 | @Override 75 | public void onAttach(Context context) { 76 | super.onAttach(context); 77 | communicator = (Communicator) context; 78 | } 79 | 80 | public interface Communicator { 81 | void onTableSelected(Table table); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/listener/DatabaseListListener.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.listener; 2 | 3 | import com.krishna.debug_tools.data.pojo.DBPojo; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by krishna on 12/01/18. 9 | */ 10 | 11 | public interface DatabaseListListener { 12 | void onDatabaseListFetched(List dbPojoList); 13 | } 14 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/listener/FilesListListener.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.listener; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by krishna on 12/01/18. 8 | */ 9 | 10 | public interface FilesListListener { 11 | void onFilesListFetched(List fileList); 12 | } 13 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/listener/TableContentListener.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.listener; 2 | 3 | import android.database.Cursor; 4 | 5 | /** 6 | * Created by krishna on 12/01/18. 7 | */ 8 | 9 | public interface TableContentListener { 10 | void onTableContentFetched(Cursor cursor); 11 | } 12 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/utils/DBUtils.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.utils; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.database.sqlite.SQLiteDatabase; 6 | import android.os.Build; 7 | import android.support.annotation.NonNull; 8 | import android.webkit.MimeTypeMap; 9 | 10 | import com.krishna.debug_tools.data.DBOpenHelper; 11 | import com.krishna.debug_tools.data.pojo.DBPojo; 12 | import com.krishna.debug_tools.data.pojo.Table; 13 | 14 | import org.w3c.dom.Document; 15 | import org.w3c.dom.Element; 16 | import org.w3c.dom.Node; 17 | import org.w3c.dom.NodeList; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.RandomAccessFile; 22 | import java.nio.ByteBuffer; 23 | import java.util.AbstractMap; 24 | import java.util.ArrayList; 25 | import java.util.Arrays; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import javax.xml.parsers.DocumentBuilder; 30 | import javax.xml.parsers.DocumentBuilderFactory; 31 | 32 | /** 33 | * Created by krishna on 12/01/18. 34 | */ 35 | 36 | public class DBUtils { 37 | private static final String PATH_DATABASE = "/databases/"; 38 | private static final String PATH_SHARED_PREFS = "/shared_prefs/"; 39 | private static final String PATH_FILES = "/files/"; 40 | 41 | public static List getAllSharedPreferences(Context context) { 42 | List sharedPrefList = new ArrayList<>(); 43 | String sharedPrefsPath = getSharedPrefsPath(context); 44 | List sharedPrefsFileList = getAllFilesInDirectory(sharedPrefsPath); 45 | sharedPrefList.addAll(sharedPrefsFileList); 46 | return sharedPrefList; 47 | } 48 | 49 | public static List> getSharedPreferences(String sharedPrefFilePath) { 50 | File prefFile = new File(sharedPrefFilePath); 51 | List> sharedPrefList = new ArrayList<>(); 52 | try { 53 | DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 54 | DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 55 | Document doc = dBuilder.parse(prefFile); 56 | doc.getDocumentElement().normalize(); 57 | 58 | NodeList prefList = doc.getChildNodes().item(0).getChildNodes(); 59 | 60 | for (int i = 0; i < prefList.getLength(); i++) { 61 | Node node = prefList.item(i); 62 | if (node.getNodeType() == Node.ELEMENT_NODE) { 63 | Element element = (Element) node; 64 | String tagName = element.getTagName(); 65 | String key = element.getAttribute("name"); 66 | String value = null; 67 | if (tagName.equals("string")) 68 | value = element.getTextContent(); 69 | else 70 | value = element.getAttribute("value"); 71 | Map.Entry entry = new AbstractMap.SimpleEntry<>(key, value); 72 | sharedPrefList.add(entry); 73 | } 74 | } 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | } 78 | return sharedPrefList; 79 | } 80 | 81 | public static List getAllDatabases(Context context) { 82 | List databaseList = new ArrayList<>(); 83 | String databasePath = getDatabasePath(context); 84 | List dbFileList = getAllFilesInDirectory(databasePath); 85 | for (File dbFile : dbFileList) { 86 | try { 87 | int dbPragmaVersion = getPragmaVersionOfSqliteDb(dbFile); 88 | DBPojo dbPojo = new DBPojo(dbPragmaVersion, dbFile.getName()); 89 | databaseList.add(dbPojo); 90 | } catch (IOException e) { 91 | //ignore this db 92 | } 93 | } 94 | return databaseList; 95 | } 96 | 97 | public static List getAllTablesFromDb(Context context, DBPojo dbPojo) { 98 | List tablesList = new ArrayList<>(); 99 | if (dbPojo.getDbVersion() <= 0) return tablesList; 100 | 101 | DBOpenHelper dbOpenHelper = new DBOpenHelper(context, dbPojo.getDbName(), null, dbPojo.getDbVersion()); 102 | SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); 103 | String columnTableName = "name"; 104 | Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null); 105 | if (cursor != null && cursor.moveToFirst()) { 106 | do { 107 | String tableName = cursor.getString(cursor.getColumnIndex(columnTableName)); 108 | tablesList.add(new DBPojo(-1, tableName)); 109 | } while (cursor.moveToNext()); 110 | cursor.close(); 111 | } 112 | return tablesList; 113 | } 114 | 115 | public static Cursor getContentsOfTable(Context context, Table table) { 116 | Cursor cursor = null; 117 | if (table.getDbPojo().getDbVersion() > 0) { 118 | DBOpenHelper dbOpenHelper = new DBOpenHelper(context, table.getDbPojo().getDbName(), null, table.getDbPojo().getDbVersion()); 119 | SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); 120 | cursor = db.rawQuery("SELECT * FROM " + table.getTableName(), null); 121 | } 122 | return cursor; 123 | } 124 | 125 | private static String getDatabasePath(Context context) { 126 | return getAppPath(context) + PATH_DATABASE; 127 | } 128 | 129 | public static String getSharedPrefsPath(Context context) { 130 | return getAppPath(context) + PATH_SHARED_PREFS; 131 | } 132 | 133 | public static String getFilesPath(Context context) { 134 | return getAppPath(context) + PATH_FILES; 135 | } 136 | 137 | public static String getAppPath(Context context) { 138 | if (Build.VERSION.SDK_INT >= 17) { 139 | return context.getApplicationInfo().dataDir; 140 | } else { 141 | return context.getFilesDir().getPath() + context.getPackageName(); 142 | } 143 | } 144 | 145 | public static List getAllFilesInDirectory(String dirPath) { 146 | List dbFileList = new ArrayList<>(); 147 | File dir = new File(dirPath); 148 | if (dir.exists()) { 149 | File[] files = dir.listFiles(); 150 | if (files != null && files.length > 0) { 151 | dbFileList.addAll(Arrays.asList(files)); 152 | } 153 | } 154 | return dbFileList; 155 | } 156 | 157 | private static int getPragmaVersionOfSqliteDb(File dbFile) throws IOException { 158 | RandomAccessFile fp = new RandomAccessFile(dbFile, "r"); 159 | fp.seek(60); 160 | byte[] buff = new byte[4]; 161 | fp.read(buff, 0, 4); 162 | return ByteBuffer.wrap(buff).getInt(); 163 | } 164 | 165 | @NonNull 166 | public static String removePackageFromFileName(String fileName) { 167 | int lastDot = fileName.lastIndexOf('.'); 168 | if (lastDot != -1) { 169 | int secondLastDot = fileName.substring(0, lastDot).lastIndexOf('.'); 170 | if (secondLastDot != -1) 171 | fileName = fileName.substring(secondLastDot + 1); 172 | } 173 | return fileName; 174 | } 175 | 176 | public static String getMimeType(String path) { 177 | String type = null; 178 | String extension = MimeTypeMap.getFileExtensionFromUrl(path); 179 | if (extension != null) { 180 | type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); 181 | } 182 | if (type == null) { 183 | type = "*/*"; 184 | } 185 | return type; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/utils/FileProvider.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.utils; 2 | 3 | import android.content.ContentProvider; 4 | import android.content.ContentValues; 5 | import android.database.Cursor; 6 | import android.net.Uri; 7 | import android.os.ParcelFileDescriptor; 8 | 9 | import java.io.File; 10 | import java.io.FileNotFoundException; 11 | 12 | /** 13 | * Created by krishna on 04/02/18. 14 | */ 15 | 16 | public class FileProvider extends ContentProvider { 17 | 18 | @Override 19 | public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 20 | File privateFile = new File(uri.getPath()); 21 | return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY); 22 | } 23 | 24 | @Override 25 | public boolean onCreate() { 26 | return false; 27 | } 28 | 29 | @Override 30 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 31 | return null; 32 | } 33 | 34 | @Override 35 | public String getType(Uri uri) { 36 | return null; 37 | } 38 | 39 | @Override 40 | public Uri insert(Uri uri, ContentValues values) { 41 | return null; 42 | } 43 | 44 | @Override 45 | public int delete(Uri uri, String selection, String[] selectionArgs) { 46 | return 0; 47 | } 48 | 49 | @Override 50 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 51 | return 0; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /debug_tools/src/main/java/com/krishna/debug_tools/utils/FixedGridLayoutManager.java: -------------------------------------------------------------------------------- 1 | package com.krishna.debug_tools.utils; 2 | 3 | import android.content.Context; 4 | import android.graphics.PointF; 5 | import android.support.v7.widget.LinearSmoothScroller; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.util.AttributeSet; 8 | import android.util.Log; 9 | import android.util.SparseArray; 10 | import android.util.SparseIntArray; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | 14 | import java.util.HashSet; 15 | import java.util.List; 16 | 17 | /** 18 | * A {@link android.support.v7.widget.RecyclerView.LayoutManager} implementation 19 | * that places children in a two-dimensional grid, sized to a fixed column count 20 | * value. User scrolling is possible in both horizontal and vertical directions 21 | * to view the data set. 22 | *

23 | *

The column count is controllable via {@link #setTotalColumnCount(int)}. The layout manager 24 | * will generate the number of rows necessary to accommodate the data set based on 25 | * the fixed column count. 26 | *

27 | *

This manager does make some assumptions to simplify the implementation: 28 | *

    29 | *
  • All child views are assumed to be the same size
  • 30 | *
  • The window of visible views is a constant
  • 31 | *
32 | */ 33 | public class FixedGridLayoutManager extends RecyclerView.LayoutManager { 34 | 35 | private static final String TAG = FixedGridLayoutManager.class.getSimpleName(); 36 | 37 | private static final int DEFAULT_COUNT = 1; 38 | 39 | /* View Removal Constants */ 40 | private static final int REMOVE_VISIBLE = 0; 41 | private static final int REMOVE_INVISIBLE = 1; 42 | 43 | /* Fill Direction Constants */ 44 | private static final int DIRECTION_NONE = -1; 45 | private static final int DIRECTION_START = 0; 46 | private static final int DIRECTION_END = 1; 47 | private static final int DIRECTION_UP = 2; 48 | private static final int DIRECTION_DOWN = 3; 49 | 50 | /* First (top-left) position visible at any point */ 51 | private int mFirstVisiblePosition; 52 | /* Consistent size applied to all child views */ 53 | private int mDecoratedChildWidth; 54 | private int mDecoratedChildHeight; 55 | /* Number of columns that exist in the grid */ 56 | private int mTotalColumnCount = DEFAULT_COUNT; 57 | /* Metrics for the visible window of our data */ 58 | private int mVisibleColumnCount; 59 | private int mVisibleRowCount; 60 | 61 | /* Used for tracking off-screen change events */ 62 | private int mFirstChangedPosition; 63 | private int mChangedPositionCount; 64 | 65 | /** 66 | * Set the number of columns the layout manager will use. This will 67 | * trigger a layout update. 68 | * 69 | * @param count Number of columns. 70 | */ 71 | public void setTotalColumnCount(int count) { 72 | mTotalColumnCount = count; 73 | requestLayout(); 74 | } 75 | 76 | /* 77 | * You must return true from this method if you want your 78 | * LayoutManager to support anything beyond "simple" item 79 | * animations. Enabling this causes onLayoutChildren() to 80 | * be called twice on each animated change; once for a 81 | * pre-layout, and again for the real layout. 82 | */ 83 | @Override 84 | public boolean supportsPredictiveItemAnimations() { 85 | return true; 86 | } 87 | 88 | /* 89 | * Called by RecyclerView when a view removal is triggered. This is called 90 | * before onLayoutChildren() in pre-layout if the views removed are not visible. We 91 | * use it in this case to inform pre-layout that a removal took place. 92 | * 93 | * This method is still called if the views removed were visible, but it will 94 | * happen AFTER pre-layout. 95 | */ 96 | @Override 97 | public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) { 98 | mFirstChangedPosition = positionStart; 99 | mChangedPositionCount = itemCount; 100 | } 101 | 102 | /* 103 | * This method is your initial call from the framework. You will receive it when you 104 | * need to start laying out the initial set of views. This method will not be called 105 | * repeatedly, so don't rely on it to continually process changes during user 106 | * interaction. 107 | * 108 | * This method will be called when the data set in the adapter changes, so it can be 109 | * used to update a layout based on a new item count. 110 | * 111 | * If predictive animations are enabled, you will see this called twice. First, with 112 | * state.isPreLayout() returning true to lay out children in their initial conditions. 113 | * Then again to lay out children in their final locations. 114 | */ 115 | @Override 116 | public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 117 | //We have nothing to show for an empty data set but clear any existing views 118 | if (getItemCount() == 0) { 119 | detachAndScrapAttachedViews(recycler); 120 | return; 121 | } 122 | if (getChildCount() == 0 && state.isPreLayout()) { 123 | //Nothing to do during prelayout when empty 124 | return; 125 | } 126 | 127 | //Clear change tracking state when a real layout occurs 128 | if (!state.isPreLayout()) { 129 | mFirstChangedPosition = mChangedPositionCount = 0; 130 | } 131 | 132 | if (getChildCount() == 0) { //First or empty layout 133 | //Scrap measure one child 134 | View scrap = recycler.getViewForPosition(0); 135 | addView(scrap); 136 | measureChildWithMargins(scrap, 0, 0); 137 | 138 | /* 139 | * We make some assumptions in this code based on every child 140 | * view being the same size (i.e. a uniform grid). This allows 141 | * us to compute the following values up front because they 142 | * won't change. 143 | */ 144 | mDecoratedChildWidth = getDecoratedMeasuredWidth(scrap); 145 | mDecoratedChildHeight = getDecoratedMeasuredHeight(scrap); 146 | 147 | detachAndScrapView(scrap, recycler); 148 | } 149 | 150 | //Always update the visible row/column counts 151 | updateWindowSizing(); 152 | 153 | SparseIntArray removedCache = null; 154 | /* 155 | * During pre-layout, we need to take note of any views that are 156 | * being removed in order to handle predictive animations 157 | */ 158 | if (state.isPreLayout()) { 159 | removedCache = new SparseIntArray(getChildCount()); 160 | for (int i = 0; i < getChildCount(); i++) { 161 | final View view = getChildAt(i); 162 | LayoutParams lp = (LayoutParams) view.getLayoutParams(); 163 | 164 | if (lp.isItemRemoved()) { 165 | //Track these view removals as visible 166 | removedCache.put(lp.getViewLayoutPosition(), REMOVE_VISIBLE); 167 | } 168 | } 169 | 170 | //Track view removals that happened out of bounds (i.e. off-screen) 171 | if (removedCache.size() == 0 && mChangedPositionCount > 0) { 172 | for (int i = mFirstChangedPosition; i < (mFirstChangedPosition + mChangedPositionCount); i++) { 173 | removedCache.put(i, REMOVE_INVISIBLE); 174 | } 175 | } 176 | } 177 | 178 | 179 | int childLeft; 180 | int childTop; 181 | if (getChildCount() == 0) { //First or empty layout 182 | //Reset the visible and scroll positions 183 | mFirstVisiblePosition = 0; 184 | childLeft = getPaddingLeft(); 185 | childTop = getPaddingTop(); 186 | } else if (!state.isPreLayout() 187 | && getVisibleChildCount() >= state.getItemCount()) { 188 | //Data set is too small to scroll fully, just reset position 189 | mFirstVisiblePosition = 0; 190 | childLeft = getPaddingLeft(); 191 | childTop = getPaddingTop(); 192 | } else { //Adapter data set changes 193 | /* 194 | * Keep the existing initial position, and save off 195 | * the current scrolled offset. 196 | */ 197 | final View topChild = getChildAt(0); 198 | childLeft = getDecoratedLeft(topChild); 199 | childTop = getDecoratedTop(topChild); 200 | 201 | /* 202 | * When data set is too small to scroll vertically, adjust vertical offset 203 | * and shift position to the first row, preserving current column 204 | */ 205 | if (!state.isPreLayout() && getVerticalSpace() > (getTotalRowCount() * mDecoratedChildHeight)) { 206 | mFirstVisiblePosition = mFirstVisiblePosition % getTotalColumnCount(); 207 | childTop = getPaddingTop(); 208 | 209 | //If the shift overscrolls the column max, back it off 210 | if ((mFirstVisiblePosition + mVisibleColumnCount) > state.getItemCount()) { 211 | mFirstVisiblePosition = Math.max(state.getItemCount() - mVisibleColumnCount, 0); 212 | childLeft = getPaddingLeft(); 213 | } 214 | } 215 | 216 | /* 217 | * Adjust the visible position if out of bounds in the 218 | * new layout. This occurs when the new item count in an adapter 219 | * is much smaller than it was before, and you are scrolled to 220 | * a location where no items would exist. 221 | */ 222 | int maxFirstRow = getTotalRowCount() - (mVisibleRowCount - 1); 223 | int maxFirstCol = getTotalColumnCount() - (mVisibleColumnCount - 1); 224 | boolean isOutOfRowBounds = getFirstVisibleRow() > maxFirstRow; 225 | boolean isOutOfColBounds = getFirstVisibleColumn() > maxFirstCol; 226 | if (isOutOfRowBounds || isOutOfColBounds) { 227 | int firstRow; 228 | if (isOutOfRowBounds) { 229 | firstRow = maxFirstRow; 230 | } else { 231 | firstRow = getFirstVisibleRow(); 232 | } 233 | int firstCol; 234 | if (isOutOfColBounds) { 235 | firstCol = maxFirstCol; 236 | } else { 237 | firstCol = getFirstVisibleColumn(); 238 | } 239 | mFirstVisiblePosition = firstRow * getTotalColumnCount() + firstCol; 240 | 241 | childLeft = getHorizontalSpace() - (mDecoratedChildWidth * mVisibleColumnCount); 242 | childTop = getVerticalSpace() - (mDecoratedChildHeight * mVisibleRowCount); 243 | 244 | //Correct cases where shifting to the bottom-right overscrolls the top-left 245 | // This happens on data sets too small to scroll in a direction. 246 | if (getFirstVisibleRow() == 0) { 247 | childTop = Math.min(childTop, getPaddingTop()); 248 | } 249 | if (getFirstVisibleColumn() == 0) { 250 | childLeft = Math.min(childLeft, getPaddingLeft()); 251 | } 252 | } 253 | } 254 | 255 | //Clear all attached views into the recycle bin 256 | detachAndScrapAttachedViews(recycler); 257 | 258 | //Fill the grid for the initial layout of views 259 | fillGrid(DIRECTION_NONE, childLeft, childTop, recycler, state, removedCache); 260 | 261 | //Evaluate any disappearing views that may exist 262 | if (!state.isPreLayout() && !recycler.getScrapList().isEmpty()) { 263 | final List scrapList = recycler.getScrapList(); 264 | final HashSet disappearingViews = new HashSet(scrapList.size()); 265 | 266 | for (RecyclerView.ViewHolder holder : scrapList) { 267 | final View child = holder.itemView; 268 | final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 269 | if (!lp.isItemRemoved()) { 270 | disappearingViews.add(child); 271 | } 272 | } 273 | 274 | for (View child : disappearingViews) { 275 | layoutDisappearingView(child); 276 | } 277 | } 278 | } 279 | 280 | @Override 281 | public void onAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter) { 282 | //Completely scrap the existing layout 283 | removeAllViews(); 284 | } 285 | 286 | /* 287 | * Rather than continuously checking how many views we can fit 288 | * based on scroll offsets, we simplify the math by computing the 289 | * visible grid as what will initially fit on screen, plus one. 290 | */ 291 | private void updateWindowSizing() { 292 | mVisibleColumnCount = (getHorizontalSpace() / mDecoratedChildWidth) + 1; 293 | if (getHorizontalSpace() % mDecoratedChildWidth > 0) { 294 | mVisibleColumnCount++; 295 | } 296 | 297 | //Allow minimum value for small data sets 298 | if (mVisibleColumnCount > getTotalColumnCount()) { 299 | mVisibleColumnCount = getTotalColumnCount(); 300 | } 301 | 302 | 303 | mVisibleRowCount = (getVerticalSpace() / mDecoratedChildHeight) + 1; 304 | if (getVerticalSpace() % mDecoratedChildHeight > 0) { 305 | mVisibleRowCount++; 306 | } 307 | 308 | if (mVisibleRowCount > getTotalRowCount()) { 309 | mVisibleRowCount = getTotalRowCount(); 310 | } 311 | } 312 | 313 | private void fillGrid(int direction, RecyclerView.Recycler recycler, RecyclerView.State state) { 314 | fillGrid(direction, 0, 0, recycler, state, null); 315 | } 316 | 317 | private void fillGrid(int direction, int emptyLeft, int emptyTop, 318 | RecyclerView.Recycler recycler, 319 | RecyclerView.State state, 320 | SparseIntArray removedPositions) { 321 | if (mFirstVisiblePosition < 0) mFirstVisiblePosition = 0; 322 | if (mFirstVisiblePosition >= getItemCount()) mFirstVisiblePosition = (getItemCount() - 1); 323 | 324 | /* 325 | * First, we will detach all existing views from the layout. 326 | * detachView() is a lightweight operation that we can use to 327 | * quickly reorder views without a full add/remove. 328 | */ 329 | SparseArray viewCache = new SparseArray(getChildCount()); 330 | int startLeftOffset = emptyLeft; 331 | int startTopOffset = emptyTop; 332 | if (getChildCount() != 0) { 333 | final View topView = getChildAt(0); 334 | startLeftOffset = getDecoratedLeft(topView); 335 | startTopOffset = getDecoratedTop(topView); 336 | switch (direction) { 337 | case DIRECTION_START: 338 | startLeftOffset -= mDecoratedChildWidth; 339 | break; 340 | case DIRECTION_END: 341 | startLeftOffset += mDecoratedChildWidth; 342 | break; 343 | case DIRECTION_UP: 344 | startTopOffset -= mDecoratedChildHeight; 345 | break; 346 | case DIRECTION_DOWN: 347 | startTopOffset += mDecoratedChildHeight; 348 | break; 349 | } 350 | 351 | //Cache all views by their existing position, before updating counts 352 | for (int i = 0; i < getChildCount(); i++) { 353 | int position = positionOfIndex(i); 354 | final View child = getChildAt(i); 355 | viewCache.put(position, child); 356 | } 357 | 358 | //Temporarily detach all views. 359 | // Views we still need will be added back at the proper index. 360 | for (int i = 0; i < viewCache.size(); i++) { 361 | detachView(viewCache.valueAt(i)); 362 | } 363 | } 364 | 365 | /* 366 | * Next, we advance the visible position based on the fill direction. 367 | * DIRECTION_NONE doesn't advance the position in any direction. 368 | */ 369 | switch (direction) { 370 | case DIRECTION_START: 371 | mFirstVisiblePosition--; 372 | break; 373 | case DIRECTION_END: 374 | mFirstVisiblePosition++; 375 | break; 376 | case DIRECTION_UP: 377 | mFirstVisiblePosition -= getTotalColumnCount(); 378 | break; 379 | case DIRECTION_DOWN: 380 | mFirstVisiblePosition += getTotalColumnCount(); 381 | break; 382 | } 383 | 384 | /* 385 | * Next, we supply the grid of items that are deemed visible. 386 | * If these items were previously there, they will simply be 387 | * re-attached. New views that must be created are obtained 388 | * from the Recycler and added. 389 | */ 390 | int leftOffset = startLeftOffset; 391 | int topOffset = startTopOffset; 392 | 393 | for (int i = 0; i < getVisibleChildCount(); i++) { 394 | int nextPosition = positionOfIndex(i); 395 | 396 | /* 397 | * When a removal happens out of bounds, the pre-layout positions of items 398 | * after the removal are shifted to their final positions ahead of schedule. 399 | * We have to track off-screen removals and shift those positions back 400 | * so we can properly lay out all current (and appearing) views in their 401 | * initial locations. 402 | */ 403 | int offsetPositionDelta = 0; 404 | if (state.isPreLayout()) { 405 | int offsetPosition = nextPosition; 406 | 407 | for (int offset = 0; offset < removedPositions.size(); offset++) { 408 | //Look for off-screen removals that are less-than this 409 | if (removedPositions.valueAt(offset) == REMOVE_INVISIBLE 410 | && removedPositions.keyAt(offset) < nextPosition) { 411 | //Offset position to match 412 | offsetPosition--; 413 | } 414 | } 415 | offsetPositionDelta = nextPosition - offsetPosition; 416 | nextPosition = offsetPosition; 417 | } 418 | 419 | if (nextPosition < 0 || nextPosition >= state.getItemCount()) { 420 | //Item space beyond the data set, don't attempt to add a view 421 | continue; 422 | } 423 | 424 | //Layout this position 425 | View view = viewCache.get(nextPosition); 426 | if (view == null) { 427 | /* 428 | * The Recycler will give us either a newly constructed view, 429 | * or a recycled view it has on-hand. In either case, the 430 | * view will already be fully bound to the data by the 431 | * adapter for us. 432 | */ 433 | view = recycler.getViewForPosition(nextPosition); 434 | addView(view); 435 | 436 | /* 437 | * Update the new view's metadata, but only when this is a real 438 | * layout pass. 439 | */ 440 | if (!state.isPreLayout()) { 441 | LayoutParams lp = (LayoutParams) view.getLayoutParams(); 442 | lp.row = getGlobalRowOfPosition(nextPosition); 443 | lp.column = getGlobalColumnOfPosition(nextPosition); 444 | } 445 | 446 | /* 447 | * It is prudent to measure/layout each new view we 448 | * receive from the Recycler. We don't have to do 449 | * this for views we are just re-arranging. 450 | */ 451 | measureChildWithMargins(view, 0, 0); 452 | layoutDecorated(view, leftOffset, topOffset, 453 | leftOffset + mDecoratedChildWidth, 454 | topOffset + mDecoratedChildHeight); 455 | 456 | } else { 457 | //Re-attach the cached view at its new index 458 | attachView(view); 459 | viewCache.remove(nextPosition); 460 | } 461 | 462 | if (i % mVisibleColumnCount == (mVisibleColumnCount - 1)) { 463 | leftOffset = startLeftOffset; 464 | topOffset += mDecoratedChildHeight; 465 | 466 | //During pre-layout, on each column end, apply any additional appearing views 467 | if (state.isPreLayout()) { 468 | layoutAppearingViews(recycler, view, nextPosition, removedPositions.size(), offsetPositionDelta); 469 | } 470 | } else { 471 | leftOffset += mDecoratedChildWidth; 472 | } 473 | } 474 | 475 | /* 476 | * Finally, we ask the Recycler to scrap and store any views 477 | * that we did not re-attach. These are views that are not currently 478 | * necessary because they are no longer visible. 479 | */ 480 | for (int i = 0; i < viewCache.size(); i++) { 481 | final View removingView = viewCache.valueAt(i); 482 | recycler.recycleView(removingView); 483 | } 484 | } 485 | 486 | /* 487 | * You must override this method if you would like to support external calls 488 | * to shift the view to a given adapter position. In our implementation, this 489 | * is the same as doing a fresh layout with the given position as the top-left 490 | * (or first visible), so we simply set that value and trigger onLayoutChildren() 491 | */ 492 | @Override 493 | public void scrollToPosition(int position) { 494 | if (position >= getItemCount()) { 495 | Log.e(TAG, "Cannot scroll to " + position + ", item count is " + getItemCount()); 496 | return; 497 | } 498 | 499 | //Set requested position as first visible 500 | mFirstVisiblePosition = position; 501 | //Toss all existing views away 502 | removeAllViews(); 503 | //Trigger a new view layout 504 | requestLayout(); 505 | } 506 | 507 | /* 508 | * You must override this method if you would like to support external calls 509 | * to animate a change to a new adapter position. The framework provides a 510 | * helper scroller implementation (LinearSmoothScroller), which we leverage 511 | * to do the animation calculations. 512 | */ 513 | @Override 514 | public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, final int position) { 515 | if (position >= getItemCount()) { 516 | Log.e(TAG, "Cannot scroll to " + position + ", item count is " + getItemCount()); 517 | return; 518 | } 519 | 520 | /* 521 | * LinearSmoothScroller's default behavior is to scroll the contents until 522 | * the child is fully visible. It will snap to the top-left or bottom-right 523 | * of the parent depending on whether the direction of travel was positive 524 | * or negative. 525 | */ 526 | LinearSmoothScroller scroller = new LinearSmoothScroller(recyclerView.getContext()) { 527 | /* 528 | * LinearSmoothScroller, at a minimum, just need to know the vector 529 | * (x/y distance) to travel in order to get from the current positioning 530 | * to the target. 531 | */ 532 | @Override 533 | public PointF computeScrollVectorForPosition(int targetPosition) { 534 | final int rowOffset = getGlobalRowOfPosition(targetPosition) 535 | - getGlobalRowOfPosition(mFirstVisiblePosition); 536 | final int columnOffset = getGlobalColumnOfPosition(targetPosition) 537 | - getGlobalColumnOfPosition(mFirstVisiblePosition); 538 | 539 | return new PointF(columnOffset * mDecoratedChildWidth, rowOffset * mDecoratedChildHeight); 540 | } 541 | }; 542 | scroller.setTargetPosition(position); 543 | startSmoothScroll(scroller); 544 | } 545 | 546 | /* 547 | * Use this method to tell the RecyclerView if scrolling is even possible 548 | * in the horizontal direction. 549 | */ 550 | @Override 551 | public boolean canScrollHorizontally() { 552 | //We do allow scrolling 553 | return true; 554 | } 555 | 556 | /* 557 | * This method describes how far RecyclerView thinks the contents should scroll horizontally. 558 | * You are responsible for verifying edge boundaries, and determining if this scroll 559 | * event somehow requires that new views be added or old views get recycled. 560 | */ 561 | @Override 562 | public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { 563 | if (getChildCount() == 0) { 564 | return 0; 565 | } 566 | 567 | //Take leftmost measurements from the top-left child 568 | final View topView = getChildAt(0); 569 | //Take rightmost measurements from the top-right child 570 | final View bottomView = getChildAt(mVisibleColumnCount - 1); 571 | 572 | //Optimize the case where the entire data set is too small to scroll 573 | int viewSpan = getDecoratedRight(bottomView) - getDecoratedLeft(topView); 574 | if (viewSpan < getHorizontalSpace()) { 575 | //We cannot scroll in either direction 576 | return 0; 577 | } 578 | 579 | int delta; 580 | boolean leftBoundReached = getFirstVisibleColumn() == 0; 581 | boolean rightBoundReached = getLastVisibleColumn() >= getTotalColumnCount(); 582 | if (dx > 0) { // Contents are scrolling left 583 | //Check right bound 584 | if (rightBoundReached) { 585 | //If we've reached the last column, enforce limits 586 | int rightOffset = getHorizontalSpace() - getDecoratedRight(bottomView) + getPaddingRight(); 587 | delta = Math.max(-dx, rightOffset); 588 | } else { 589 | //No limits while the last column isn't visible 590 | delta = -dx; 591 | } 592 | } else { // Contents are scrolling right 593 | //Check left bound 594 | if (leftBoundReached) { 595 | int leftOffset = -getDecoratedLeft(topView) + getPaddingLeft(); 596 | delta = Math.min(-dx, leftOffset); 597 | } else { 598 | delta = -dx; 599 | } 600 | } 601 | 602 | offsetChildrenHorizontal(delta); 603 | 604 | if (dx > 0) { 605 | if (getDecoratedRight(topView) < 0 && !rightBoundReached) { 606 | fillGrid(DIRECTION_END, recycler, state); 607 | } else if (!rightBoundReached) { 608 | fillGrid(DIRECTION_NONE, recycler, state); 609 | } 610 | } else { 611 | if (getDecoratedLeft(topView) > 0 && !leftBoundReached) { 612 | fillGrid(DIRECTION_START, recycler, state); 613 | } else if (!leftBoundReached) { 614 | fillGrid(DIRECTION_NONE, recycler, state); 615 | } 616 | } 617 | 618 | /* 619 | * Return value determines if a boundary has been reached 620 | * (for edge effects and flings). If returned value does not 621 | * match original delta (passed in), RecyclerView will draw 622 | * an edge effect. 623 | */ 624 | return -delta; 625 | } 626 | 627 | /* 628 | * Use this method to tell the RecyclerView if scrolling is even possible 629 | * in the vertical direction. 630 | */ 631 | @Override 632 | public boolean canScrollVertically() { 633 | //We do allow scrolling 634 | return true; 635 | } 636 | 637 | /* 638 | * This method describes how far RecyclerView thinks the contents should scroll vertically. 639 | * You are responsible for verifying edge boundaries, and determining if this scroll 640 | * event somehow requires that new views be added or old views get recycled. 641 | */ 642 | @Override 643 | public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { 644 | if (getChildCount() == 0) { 645 | return 0; 646 | } 647 | 648 | //Take top measurements from the top-left child 649 | final View topView = getChildAt(0); 650 | //Take bottom measurements from the bottom-right child. 651 | final View bottomView = getChildAt(getChildCount() - 1); 652 | 653 | //Optimize the case where the entire data set is too small to scroll 654 | int viewSpan = getDecoratedBottom(bottomView) - getDecoratedTop(topView); 655 | if (viewSpan < getVerticalSpace()) { 656 | //We cannot scroll in either direction 657 | return 0; 658 | } 659 | 660 | int delta; 661 | int maxRowCount = getTotalRowCount(); 662 | boolean topBoundReached = getFirstVisibleRow() == 0; 663 | boolean bottomBoundReached = getLastVisibleRow() >= maxRowCount; 664 | if (dy > 0) { // Contents are scrolling up 665 | //Check against bottom bound 666 | if (bottomBoundReached) { 667 | //If we've reached the last row, enforce limits 668 | int bottomOffset; 669 | if (rowOfIndex(getChildCount() - 1) >= (maxRowCount - 1)) { 670 | //We are truly at the bottom, determine how far 671 | bottomOffset = getVerticalSpace() - getDecoratedBottom(bottomView) 672 | + getPaddingBottom(); 673 | } else { 674 | /* 675 | * Extra space added to account for allowing bottom space in the grid. 676 | * This occurs when the overlap in the last row is not large enough to 677 | * ensure that at least one element in that row isn't fully recycled. 678 | */ 679 | bottomOffset = getVerticalSpace() - (getDecoratedBottom(bottomView) 680 | + mDecoratedChildHeight) + getPaddingBottom(); 681 | } 682 | 683 | delta = Math.max(-dy, bottomOffset); 684 | } else { 685 | //No limits while the last row isn't visible 686 | delta = -dy; 687 | } 688 | } else { // Contents are scrolling down 689 | //Check against top bound 690 | if (topBoundReached) { 691 | int topOffset = -getDecoratedTop(topView) + getPaddingTop(); 692 | 693 | delta = Math.min(-dy, topOffset); 694 | } else { 695 | delta = -dy; 696 | } 697 | } 698 | 699 | offsetChildrenVertical(delta); 700 | 701 | if (dy > 0) { 702 | if (getDecoratedBottom(topView) < 0 && !bottomBoundReached) { 703 | fillGrid(DIRECTION_DOWN, recycler, state); 704 | } else if (!bottomBoundReached) { 705 | fillGrid(DIRECTION_NONE, recycler, state); 706 | } 707 | } else { 708 | if (getDecoratedTop(topView) > 0 && !topBoundReached) { 709 | fillGrid(DIRECTION_UP, recycler, state); 710 | } else if (!topBoundReached) { 711 | fillGrid(DIRECTION_NONE, recycler, state); 712 | } 713 | } 714 | 715 | /* 716 | * Return value determines if a boundary has been reached 717 | * (for edge effects and flings). If returned value does not 718 | * match original delta (passed in), RecyclerView will draw 719 | * an edge effect. 720 | */ 721 | return -delta; 722 | } 723 | 724 | /* 725 | * This is a helper method used by RecyclerView to determine 726 | * if a specific child view can be returned. 727 | */ 728 | @Override 729 | public View findViewByPosition(int position) { 730 | for (int i = 0; i < getChildCount(); i++) { 731 | if (positionOfIndex(i) == position) { 732 | return getChildAt(i); 733 | } 734 | } 735 | 736 | return null; 737 | } 738 | 739 | /** 740 | * Boilerplate to extend LayoutParams for tracking row/column of attached views 741 | */ 742 | 743 | /* 744 | * Even without extending LayoutParams, we must override this method 745 | * to provide the default layout parameters that each child view 746 | * will receive when added. 747 | */ 748 | @Override 749 | public RecyclerView.LayoutParams generateDefaultLayoutParams() { 750 | return new LayoutParams( 751 | ViewGroup.LayoutParams.WRAP_CONTENT, 752 | ViewGroup.LayoutParams.WRAP_CONTENT); 753 | } 754 | 755 | @Override 756 | public RecyclerView.LayoutParams generateLayoutParams(Context c, AttributeSet attrs) { 757 | return new LayoutParams(c, attrs); 758 | } 759 | 760 | @Override 761 | public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { 762 | if (lp instanceof ViewGroup.MarginLayoutParams) { 763 | return new LayoutParams((ViewGroup.MarginLayoutParams) lp); 764 | } else { 765 | return new LayoutParams(lp); 766 | } 767 | } 768 | 769 | @Override 770 | public boolean checkLayoutParams(RecyclerView.LayoutParams lp) { 771 | return lp instanceof LayoutParams; 772 | } 773 | 774 | public static class LayoutParams extends RecyclerView.LayoutParams { 775 | 776 | //Current row in the grid 777 | public int row; 778 | //Current column in the grid 779 | public int column; 780 | 781 | public LayoutParams(Context c, AttributeSet attrs) { 782 | super(c, attrs); 783 | } 784 | 785 | public LayoutParams(int width, int height) { 786 | super(width, height); 787 | } 788 | 789 | public LayoutParams(ViewGroup.MarginLayoutParams source) { 790 | super(source); 791 | } 792 | 793 | public LayoutParams(ViewGroup.LayoutParams source) { 794 | super(source); 795 | } 796 | 797 | public LayoutParams(RecyclerView.LayoutParams source) { 798 | super(source); 799 | } 800 | } 801 | 802 | /** 803 | * Animation Layout Helpers 804 | */ 805 | 806 | /* Helper to obtain and place extra appearing views */ 807 | private void layoutAppearingViews(RecyclerView.Recycler recycler, View referenceView, int referencePosition, int extraCount, int offset) { 808 | //Nothing to do... 809 | if (extraCount < 1) return; 810 | 811 | //FIXME: This code currently causes double layout of views that are still visible… 812 | for (int extra = 1; extra <= extraCount; extra++) { 813 | //Grab the next position after the reference 814 | final int extraPosition = referencePosition + extra; 815 | if (extraPosition < 0 || extraPosition >= getItemCount()) { 816 | //Can't do anything with this 817 | continue; 818 | } 819 | 820 | /* 821 | * Obtain additional position views that we expect to appear 822 | * as part of the animation. 823 | */ 824 | View appearing = recycler.getViewForPosition(extraPosition); 825 | addView(appearing); 826 | 827 | //Find layout delta from reference position 828 | final int newRow = getGlobalRowOfPosition(extraPosition + offset); 829 | final int rowDelta = newRow - getGlobalRowOfPosition(referencePosition + offset); 830 | final int newCol = getGlobalColumnOfPosition(extraPosition + offset); 831 | final int colDelta = newCol - getGlobalColumnOfPosition(referencePosition + offset); 832 | 833 | layoutTempChildView(appearing, rowDelta, colDelta, referenceView); 834 | } 835 | } 836 | 837 | /* Helper to place a disappearing view */ 838 | private void layoutDisappearingView(View disappearingChild) { 839 | /* 840 | * LayoutManager has a special method for attaching views that 841 | * will only be around long enough to animate. 842 | */ 843 | addDisappearingView(disappearingChild); 844 | 845 | //Adjust each disappearing view to its proper place 846 | final LayoutParams lp = (LayoutParams) disappearingChild.getLayoutParams(); 847 | 848 | final int newRow = getGlobalRowOfPosition(lp.getViewAdapterPosition()); 849 | final int rowDelta = newRow - lp.row; 850 | final int newCol = getGlobalColumnOfPosition(lp.getViewAdapterPosition()); 851 | final int colDelta = newCol - lp.column; 852 | 853 | layoutTempChildView(disappearingChild, rowDelta, colDelta, disappearingChild); 854 | } 855 | 856 | 857 | /* Helper to lay out appearing/disappearing children */ 858 | private void layoutTempChildView(View child, int rowDelta, int colDelta, View referenceView) { 859 | //Set the layout position to the global row/column difference from the reference view 860 | int layoutTop = getDecoratedTop(referenceView) + rowDelta * mDecoratedChildHeight; 861 | int layoutLeft = getDecoratedLeft(referenceView) + colDelta * mDecoratedChildWidth; 862 | 863 | measureChildWithMargins(child, 0, 0); 864 | layoutDecorated(child, layoutLeft, layoutTop, 865 | layoutLeft + mDecoratedChildWidth, 866 | layoutTop + mDecoratedChildHeight); 867 | } 868 | 869 | /** 870 | * Private Helpers and Metrics Accessors 871 | */ 872 | 873 | /* Return the overall column index of this position in the global layout */ 874 | private int getGlobalColumnOfPosition(int position) { 875 | return position % mTotalColumnCount; 876 | } 877 | 878 | /* Return the overall row index of this position in the global layout */ 879 | private int getGlobalRowOfPosition(int position) { 880 | return position / mTotalColumnCount; 881 | } 882 | 883 | /* 884 | * Mapping between child view indices and adapter data 885 | * positions helps fill the proper views during scrolling. 886 | */ 887 | private int positionOfIndex(int childIndex) { 888 | int row = childIndex / mVisibleColumnCount; 889 | int column = childIndex % mVisibleColumnCount; 890 | 891 | return mFirstVisiblePosition + (row * getTotalColumnCount()) + column; 892 | } 893 | 894 | private int rowOfIndex(int childIndex) { 895 | int position = positionOfIndex(childIndex); 896 | 897 | return position / getTotalColumnCount(); 898 | } 899 | 900 | private int getFirstVisibleColumn() { 901 | return (mFirstVisiblePosition % getTotalColumnCount()); 902 | } 903 | 904 | private int getLastVisibleColumn() { 905 | return getFirstVisibleColumn() + mVisibleColumnCount; 906 | } 907 | 908 | private int getFirstVisibleRow() { 909 | return (mFirstVisiblePosition / getTotalColumnCount()); 910 | } 911 | 912 | private int getLastVisibleRow() { 913 | return getFirstVisibleRow() + mVisibleRowCount; 914 | } 915 | 916 | private int getVisibleChildCount() { 917 | return mVisibleColumnCount * mVisibleRowCount; 918 | } 919 | 920 | private int getTotalColumnCount() { 921 | if (getItemCount() < mTotalColumnCount) { 922 | return getItemCount(); 923 | } 924 | 925 | return mTotalColumnCount; 926 | } 927 | 928 | private int getTotalRowCount() { 929 | if (getItemCount() == 0 || mTotalColumnCount == 0) { 930 | return 0; 931 | } 932 | int maxRow = getItemCount() / mTotalColumnCount; 933 | //Bump the row count if it's not exactly even 934 | if (getItemCount() % mTotalColumnCount != 0) { 935 | maxRow++; 936 | } 937 | 938 | return maxRow; 939 | } 940 | 941 | private int getHorizontalSpace() { 942 | return getWidth() - getPaddingRight() - getPaddingLeft(); 943 | } 944 | 945 | private int getVerticalSpace() { 946 | return getHeight() - getPaddingBottom() - getPaddingTop(); 947 | } 948 | } 949 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-hdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-hdpi/ic_file.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-hdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-hdpi/ic_folder.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-mdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-mdpi/ic_file.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-mdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-mdpi/ic_folder.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-v21/ic_menu_camera.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-v21/ic_menu_gallery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-v21/ic_menu_manage.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-v21/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-v21/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-v21/ic_menu_slideshow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-xhdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-xhdpi/ic_file.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-xhdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-xhdpi/ic_folder.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-xxhdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-xxhdpi/ic_file.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-xxhdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-xxhdpi/ic_folder.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-xxxhdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-xxxhdpi/ic_file.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable-xxxhdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/drawable-xxxhdpi/ic_folder.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable/edittext_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/activity_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/activity_shared_preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 29 | 30 | 39 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/app_bar_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 20 | 21 | 22 | 23 | 28 | 29 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/content_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/fragment_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 23 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/item_database_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 25 | 26 | 34 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/item_shared_preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/item_simple_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 24 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/item_table_content.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/main_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/nav_header_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 21 | 22 | 28 | 29 | 34 | 35 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/layout/table_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 20 | 21 | 22 | 23 | 26 | 27 | 31 | 32 | 38 | 39 | 43 | 44 | 45 | 46 | 55 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/menu/drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/menu/menu_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 31 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/mipmap-hdpi/ic_android_robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/mipmap-hdpi/ic_android_robot.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/mipmap-mdpi/ic_android_robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/mipmap-mdpi/ic_android_robot.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/mipmap-xhdpi/ic_android_robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/mipmap-xhdpi/ic_android_robot.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/mipmap-xxhdpi/ic_android_robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/mipmap-xxhdpi/ic_android_robot.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/mipmap-xxxhdpi/ic_android_robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk121/Android-Debug-Tools/1493e76b178ed882d89dacd5bac173faf3907efb/debug_tools/src/main/res/mipmap-xxxhdpi/ic_android_robot.png -------------------------------------------------------------------------------- /debug_tools/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | #E1F5FE 8 | #FFFFFF 9 | #F5F5F5 10 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 8dp 6 | 176dp 7 | 16dp 8 | 4dp 9 | 10 | 250dp 11 | 86dp 12 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/values/drawables.xml: -------------------------------------------------------------------------------- 1 | 2 | @android:drawable/ic_menu_camera 3 | @android:drawable/ic_menu_gallery 4 | @android:drawable/ic_menu_slideshow 5 | @android:drawable/ic_menu_manage 6 | @android:drawable/ic_menu_share 7 | @android:drawable/ic_menu_send 8 | 9 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Dev Tools 3 | DrawerActivity 4 | 5 | Open navigation drawer 6 | Close navigation drawer 7 | 8 | Settings 9 | 10 | 11 | -------------------------------------------------------------------------------- /debug_tools/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 |