I made a little tool for getting all information from database at runtime. Here is my code:
package com.example.helix.whiffs;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class FragmentDatabase extends Fragment{
private final String LOG_TAG = "FRAGMENTDATABASE";
DatabaseListener listener;
int rowHeight = 40;
String text;
Button select;
TextView counter;
LinearLayout titleBar;
LinearLayout dataList;
PopupMenu popup;
String[] fields;
int[] colWidths;
List<String> data;
HashMap<Integer, String[]> dataItems;
HashMap<Integer, String> menuItems;
DBAdapter db;
public interface DatabaseListener{
void onload(String table);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_database, container, false);
select = (Button)v.findViewById(R.id.select);
counter = (TextView)v.findViewById(R.id.count);
titleBar = (LinearLayout)v.findViewById(R.id.titles);
dataList = (LinearLayout) v.findViewById(R.id.list);
data = new ArrayList<>();
menuItems = new HashMap<>();
dataItems = new HashMap<>();
db = new DBAdapter(getActivity().getApplicationContext());
data = db.allTables();
popup = new PopupMenu(getActivity().getApplicationContext(), select);
for(int i = 0; i < data.size(); i++) {
popup.getMenu().add(Menu.NONE, i, i, data.get(i));
menuItems.put(i, data.get(i));
}
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
dataList.removeAllViews();
titleBar.removeAllViews();
dataItems.clear();
int itemId = menuItem.getItemId();
String table = menuItems.get(itemId);
fields = db.allFields(table);
TextView idField = new TextView(getActivity().getApplicationContext());
idField.setText(fields[0]);
titleBar.addView(idField);
colWidths = new int[fields.length];
colWidths[0] = 80;
for(int i = 1; i < fields.length; i++){
colWidths[i] = 200;
TextView f = new TextView(getActivity().getApplicationContext());
String text = fields[i];
f.setText(text);
titleBar.addView(f);
}
dataItems = db.allValues(table);
counter.setText(String.valueOf(dataItems.size()));
for(int i = 0; i < dataItems.size(); i++){
LinearLayout row = new LinearLayout(getActivity().getApplicationContext());
row.setOrientation(LinearLayout.HORIZONTAL);
String[] rowData = dataItems.get(i);
TextView idf = new TextView(getActivity().getApplicationContext());
if(rowData.length != 0) idf.setText(rowData[0]);
row.addView(idf);
for(int j = 1; j < rowData.length; j++){
TextView idf2 = new TextView(getActivity().getApplicationContext());
text = rowData[j];
row.addView(idf2);
if(text != null && text.length() > 9){
int length = 18 * text.length();
if(colWidths[j] < length) colWidths[j] = length;
}
idf2.setText(text);
}
dataList.addView(row);
}
for(int j = 0; j < colWidths.length; j++){
TextView tv = (TextView) titleBar.getChildAt(j);
ViewGroup.LayoutParams vlp = tv.getLayoutParams();
vlp.width = colWidths[j];
vlp.height = rowHeight;
tv.setLayoutParams(vlp);
}
for(int i = 0; i < dataItems.size(); i++){
LinearLayout rowLayout = (LinearLayout) dataList.getChildAt(i);
for(int j = 0; j < colWidths.length; j++){
TextView tv = (TextView) rowLayout.getChildAt(j);
ViewGroup.LayoutParams vlp = tv.getLayoutParams();
vlp.width = colWidths[j];
vlp.height = rowHeight;
tv.setLayoutParams(vlp);
}
}
return true;
}
});
select.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
popup.show();
}
});
return v;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentDatabase.DatabaseListener) {
listener = (FragmentDatabase.DatabaseListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentListener");
}
}
@Override
public void onDetach() {
listener = null;
super.onDetach();
}
}
Here is important part of my database adapter:
myDbHelper myhelper;
public List<String> allTables(){
List<String> result = new ArrayList<>();
SQLiteDatabase db = myhelper.getWritableDatabase();
Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE type = 'table'",null);
if(c.moveToFirst()){
while (!c.isAfterLast()){
result.add(c.getString(0));
c.moveToNext();
}
}
return result;
}
public String[] allFields(String table){
List<String> result = new ArrayList<>();
SQLiteDatabase db = myhelper.getWritableDatabase();
Cursor c = db.query(table, null, null, null, null, null, null);
return c.getColumnNames();
}
public HashMap<Integer, String[]> allValues(String table) {
HashMap<Integer, String[]> result = new HashMap<>();
String[] row;
SQLiteDatabase db = myhelper.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM "+table, null);
int columns = c.getColumnCount();
if(c.moveToFirst()){
int rowCount = 0;
while(!c.isAfterLast()){
row = new String[columns];
for(int i = 0; i < columns; i++){
row[i] = c.getString(i);
Log.i(LOG_TAG, "Row add "+String.valueOf(c.getString(i)));
}
result.put(rowCount, row);
rowCount ++;
c.moveToNext();
}
}
return result;
}
static class myDbHelper extends SQLiteOpenHelper
{
private Context context;
public myDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_Version);
this.context=context;
onCreate(this.getWritableDatabase());
}
}
}
And finally the layout file for fragment
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#888888"
android:orientation="horizontal"
>
<Button
android:id="@+id/select"
android:layout_width="100dp"
android:layout_height="match_parent"
android:text="table"/>
<TextView
android:id="@+id/count"
android:layout_width="100dp"
android:layout_height="match_parent"
android:text="total"
android:textSize="24sp"
android:gravity="center_horizontal"
android:layout_marginTop="5dp"/>
</LinearLayout>
<HorizontalScrollView
android:layout_below="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:id="@+id/titles"
android:background="#777777"
android:layout_width="match_parent"
android:layout_height="36dp"
android:orientation="horizontal">
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/list"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</LinearLayout>
</ScrollView>
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
This is all done manually (using nested LinearLayouts). Performance is very good on my Huawei p8. If no list- or recyclerview option is not an option, perhaps this code might be useful for someone.
The answer is Yes as :-
I have a tool I call SQLiteInfoAssistant that is designed as a module and will display information and the underlying data for multiple database should they exist.
The information is displayed in 3 ListView. 2 side by side at the top which initially display the Databases in the upper left view and tables in the selected database in the upper right view.
In this initial view various Database information is displayed in the bottom view. eg The path along with various other information obtained via pragma's.
When a table is clicked, the tables for the database are then displayed in the upper left view and the columns in the upper right view. The lower view shows table information name, SQL used to create the table, column count and the count of columns in the primary key.
In either of the above views long clicking a table will then display the actual data (blobs truncated and displayed as hex representation).
Here's some screen shots:-
Invocation can be as simple as including the module, creating an instance of the SQLiteInformationAssistan
t passing the context and then using the show
method. However, many customisations can be made as can be seen by the comments in the following invocation code :-
private void tryitout() {
// Get an SQLiteInformationAssistant instance
// Note! the show method invokes the Activity
SQLiteInformationAssistant SIA = new SQLiteInformationAssistant(this);
// Instance customisation i.e set Display attributes
//SIA.setBaseBackgroundColour(0xFFFFFFFF);
//SIA.setHeadingTextColour(0xFFFFFF00);
//SIA.setDatabaseListHeadingTextColour(0xFFFFFF00);
//SIA.setTableListHeadingTextColour(0xFF0077FF);
//SIA.setColumnListHeadingTextColour(0xFF77FF00);
//SIA.setDatabaseListTextColour(0xFFFFFFFF);
//SIA.setDatabaseInfoTextColour(0xFFFF0000);
//SIA.setDatabaseListBackgroundColour(0xFFFFFF00);
//SIA.setDatabaseInfoBackgroundColour(0xFFFFFF00);
//SIA.setDatabaseInfoHeadingTextColour(0xFFFF0000);
//SIA.setTableListTextColour(0xFFFF00FF);
//SIA.setTableInfoTextcolour(0xFF0000FF);
//SIA.setTableListBackgroundColour(0xFFFFFF00);
//SIA.setTableInfoBackgroundColour(0xFFFFFF00);
//SIA.setTableInfoHeadingTextColour(0xFFFF00FF);
//SIA.setColumnListTextColour(0xFFFFFF00);
//SIA.setColumnInfoTextColour(0xFF000000);
//SIA.setColumnListBackgroundColour(0xFFFFFF00);
//SIA.setColumnInfoBackgroundColour(0xFFFFFF00);
//SIA.setColumnInfoHeadingTextColour(0xFF00FF00);
//SIA.setStringCellBackgroundColour(0xFFEEEEEE);
//SIA.setStringCellTextColour(0xFF0000FF);
//SIA.setIntegerCellBackgroundColour(0xFFFF0000);
//SIA.setIntegerCelltextColour(0XFFFFFFFF);
//SIA.setDoubleCellBackgroundColour(0xFF00FFFF);
//SIA.setDoubleCelltextColour(0XFF5555FF);
//SIA.setBlobCellBackgroundColour(0xFF44FF55);
//SIA.setBlobCelltextColour(0xFFFFFF00);
//SIA.setUnkownCelltextColour(0xFFFFFF00);
//SIA.setUnknownBackgroundCellColour(0xFFFF0000);
// Note
//SIA.setBytesToShowInBlob(128);
SIA.show();
}
I haven't actually published this or made it available but if anyone is interested I can supply the code, this is mainly because I myself rarely use it as it's so easy to just copy a database into one of the freely available SQLite tools (Navicat, DB Browser for Sqlite, SQLite manager etc). The full code would probably be too large to post here though.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.