Compare commits

..

33 commits

Author SHA1 Message Date
Przemek Grondek
0a37de8e2b Fix NullPointerException 2014-10-14 09:39:26 +02:00
Przemek Grondek
534824c1c9 Can't use that 2014-10-13 15:39:41 +02:00
Przemek Grondek
a6c7b27e2f Revert "Moved OnPostExecuteListener to Download class"
This was a mistake

This reverts commit 038a86e35c.
2014-10-08 20:44:01 +02:00
Przemek Grondek
038a86e35c Moved OnPostExecuteListener to Download class 2014-10-08 20:39:13 +02:00
Przemek Grondek
99f56acb4b Rename DatabaseConnector 2014-10-08 20:14:23 +02:00
Przemek Grondek
58fc51b6bd Fix for not updating current field on save 2014-10-07 00:33:46 +02:00
Przemek Grondek
283af19d92 Bug fix
Missing new values in edit when they out of view
 SQL Query better view with IME
2014-10-07 00:19:52 +02:00
Przemek Grondek
4fbbabbf81 Backup disallowed. 2014-10-06 13:04:08 +02:00
Przemek Grondek
7b3b06db5e Don't need this permissions. 2014-10-02 15:31:13 +02:00
Przemek Grondek
b5615d7591 SQL queries
Full support
2014-10-01 11:40:22 +02:00
Przemek Grondek
6c842541c3 Half implementation of SQL Query
Need to finish it.
2014-09-30 15:41:43 +02:00
Przemek Grondek
7b5e2ddd6d Support for ICS (API 14) 2014-09-17 13:43:35 +02:00
Przemek Grondek
fae910fc8c Time to POST it
Moved away from sending data in GET request and now using POST requests.
2014-09-16 11:25:54 +02:00
Przemek Grondek
d478b474fb Connection error handling 2014-08-21 15:17:36 +02:00
Przemek Grondek
ba8b96c22e Revert "Showing connection error DO NOT MERGE"
It doesn't work right now. Work moved into error branch.

This reverts commit 5d635e4408.
2014-08-20 23:38:44 +02:00
Przemek Grondek
f223b58e21 Add missing image 2014-08-20 20:14:04 +02:00
Przemek Grondek
5d635e4408 Showing connection error DO NOT MERGE
FIXME
2014-08-20 15:52:45 +02:00
Przemek Grondek
dfb3374d59 Polskie tłumaczenie 2014-08-20 15:38:50 +02:00
Przemek Grondek
23e1078c7d Turns out we need it
Re added title_fragment_database string.
2014-08-20 15:35:58 +02:00
Przemek Grondek
2dd63650de Some Bolding 2014-08-20 15:31:44 +02:00
Przemek Grondek
9bebe4407c Some String cleanup 2014-08-20 15:26:29 +02:00
Przemek Grondek
93c8d65cfa Added warning before remove entry 2014-08-20 15:20:12 +02:00
Przemek Grondek
7bcbe46d91 Added remove element 2014-08-20 15:07:12 +02:00
Przemek Grondek
555a428af4 Fix not showing scroll 2014-08-20 12:16:05 +02:00
Przemek Grondek
ba87ba1291 Set more generic Type 2014-08-20 11:47:01 +02:00
Przemek Grondek
2b661013bd Remove unused commented code. 2014-08-20 11:39:39 +02:00
Przemek Grondek
298fab290a Don't need URL log now. 2014-08-20 11:38:53 +02:00
Przemek Grondek
87c276dfc4 Reload table after changes 2014-08-20 11:37:02 +02:00
Przemek Grondek
475a7b4c61 Fix for info box 2014-08-20 11:25:55 +02:00
Przemek Grondek
e48b75863e Better UI
Less actions on main thread.
2014-08-20 11:24:55 +02:00
Przemek Grondek
697c2e845a More jobs on AsyncTask DO NOT MERGE
not finished yet.
2014-08-20 01:30:50 +02:00
Przemek Grondek
f691d83fab Fix different fields height 2014-08-19 23:06:07 +02:00
Przemek Grondek
f40ed11461 Fix URL Encoding 2014-08-17 22:17:54 +02:00
43 changed files with 1394 additions and 606 deletions

View file

@ -6,7 +6,7 @@ android {
defaultConfig {
applicationId "info.nerull7.mysqlbrowser"
minSdkVersion 15
minSdkVersion 14
targetSdkVersion 19
versionCode 1
versionName "1.0"

View file

@ -3,7 +3,7 @@
package="info.nerull7.mysqlbrowser" >
<application
android:allowBackup="true"
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
@ -32,11 +32,16 @@
</activity>
<activity
android:name=".ElementActivity"
android:label="@string/title_activity_element" >
android:label="@string/title_activity_element"
android:windowSoftInputMode="adjustPan">
</activity>
<activity
android:name=".SQLActivity"
android:label="@string/title_activity_sql"
android:windowSoftInputMode="adjustResize">
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

View file

@ -17,18 +17,25 @@ import android.widget.TextView;
import java.util.List;
import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 14.07.14.
*
* Fragment for showing list of Available Databases for user
*/
public class DatabaseFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener {
public class DatabaseFragment extends Fragment implements AdapterView.OnItemClickListener, DatabaseConnector.ListReturnListener, DatabaseConnector.OnPostExecuteListener {
private ListView databasesListView;
private ListAdapter listAdapter;
private RelativeLayout rootView;
private ProgressBar progressBar;
private List<String> databases;
@Override
public void onResume() {
super.onResume();
Static.databaseConnector.setDatabaseInUse(null);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
@ -38,8 +45,9 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
this.rootView = (RelativeLayout) rootView;
progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
Static.asyncDatabaseConnector.setListReturnListener(this);
Static.asyncDatabaseConnector.getDatabases();
Static.databaseConnector.setListReturnListener(this);
Static.databaseConnector.setOnPostExecuteListener(this);
Static.databaseConnector.getDatabases();
return rootView;
}
@ -51,7 +59,7 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
Intent intent = new Intent(getActivity(), ListActivity.class);
intent.putExtra(Static.FRAGMENT_TO_START, Static.FRAGMENT_TABLE);
intent.putExtra(Static.DATABASE_NAME_ARG, chosenDatabase);
Static.asyncDatabaseConnector.setDatabaseInUse(chosenDatabase);
Static.databaseConnector.setDatabaseInUse(chosenDatabase);
startActivity(intent);
} else {
Static.showErrorAlert(getResources().getString(R.string.no_connection), getActivity());
@ -60,6 +68,11 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
@Override
public void onListReturn(List<String> databases) {
this.databases = databases;
}
@Override
public void onPostExecute() {
if(databases!= null) {
listAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, databases);
databasesListView.setAdapter(listAdapter);

View file

@ -1,13 +1,14 @@
package info.nerull7.mysqlbrowser;
import android.content.Context;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
@ -21,33 +22,58 @@ public class ElementArrayAdapter extends ArrayAdapter<String> {
public ElementArrayAdapter(Context context, int resource, List<String> fields) {
super(context, resource, fields);
this.context = context;
this.fields = fields;
layout = resource;
values = null;
init(context, resource, fields);
values = new ArrayList<String>();
for(String field: fields){
values.add("");
}
}
public ElementArrayAdapter(Context context, int resource, List<String> fields, List<String> values) {
this(context, resource, fields);
this.values = values;
super(context, resource, fields);
init(context, resource, fields);
this.values = new ArrayList<String>();
if(values!=null) {
this.values.addAll(values); // Copy
} else {
for(int i=0;i<fields.size();i++){
this.values.add(new String());
}
}
}
private void init(Context context, int resource, List<String> fields){
this.context = context;
this.fields = fields;
layout = resource;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = layoutInflater.inflate(layout, parent, false);
final View rowView = layoutInflater.inflate(layout, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.textFieldName);
textView.setText(fields.get(position));
if(values != null){
EditText textFieldName = (EditText) rowView.findViewById(R.id.editFieldValue);
textFieldName.setText(values.get(position));
}
TextView textFieldName = (TextView) rowView.findViewById(R.id.editFieldValue);
textFieldName.setText(values.get(position));
textFieldName.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
String tmp = String.valueOf(((TextView) v).getText());
values.set(position, tmp);
}
}
});
return rowView;
}
public List<String> getFieldArray(){
return fields;
}
public List<String> getValues() {
return values;
}
}

View file

@ -2,6 +2,7 @@ package info.nerull7.mysqlbrowser;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
@ -10,24 +11,29 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.ProgressBar;
import java.util.ArrayList;
import java.util.List;
import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 2014-08-06.
*
* Fragment for editing/adding elements
*/
public class ElementFragment extends Fragment implements AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.StringReturnListener {
public class ElementFragment extends Fragment implements DatabaseConnector.ListReturnListener, DatabaseConnector.StringReturnListener, DatabaseConnector.OnPostExecuteListener {
public static final String EDIT_ELEMENT = "edit_element";
public static final String EDIT_LIST = "edit_element_list";
private static final int POST_EXECUTE_NONE = 0;
private static final int POST_EXECUTE_GET_FIELDS = 1;
private static final int POST_EXECUTE_UPDATE_ELEMENT = 2;
private static final int POST_EXECUTE_ADD_ELEMENT = 3;
private String tableName;
private ElementArrayAdapter listAdapter;
@ -35,6 +41,8 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
private ListView listView;
private List<String> values;
private String message;
private int postExecute;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -43,28 +51,83 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar);
listView = (ListView) rootView.findViewById(R.id.listView);
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState==SCROLL_STATE_TOUCH_SCROLL) {
listView.requestFocus();
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(listView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
listView.setItemsCanFocus(true);
initArguments();
Static.asyncDatabaseConnector.setListReturnListener(this);
Static.asyncDatabaseConnector.getFields(tableName);
postExecute = POST_EXECUTE_NONE;
Static.databaseConnector.setListReturnListener(this);
Static.databaseConnector.setOnPostExecuteListener(this);
Static.databaseConnector.getFields(tableName);
return rootView;
}
private void actionSave(){
List<String> fields = listAdapter.getFieldArray();
Static.databaseConnector.setStringReturnListener(this);
if(getArguments().getBoolean(EDIT_ELEMENT))
Static.databaseConnector.updateElement(tableName, fields, values, listAdapter.getValues());
else
Static.databaseConnector.addNewElement(tableName, fields, listAdapter.getValues());
}
private void actionRemove(){
final List<String> fields = listAdapter.getFieldArray();
Static.databaseConnector.setStringReturnListener(this);
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.error_remove);
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Static.databaseConnector.removeElement(tableName, fields, values);
// getActivity().finish();
}
});
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// Nothing to do just get back
}
});
builder.setTitle(R.string.warning);
builder.setIcon(R.drawable.ic_action_warning);
builder.setCancelable(false); // There is no exit
builder.create();
builder.show();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.action_save ){
List<String> fields = listAdapter.getFieldArray();
Static.asyncDatabaseConnector.setStringReturnListener(this);
if(getArguments().getBoolean(EDIT_ELEMENT))
Static.asyncDatabaseConnector.updateElement(tableName, fields, values, getNewValues());
else
Static.asyncDatabaseConnector.addNewElement(tableName, fields, getNewValues());
return true;
} else {
return super.onOptionsItemSelected(item);
listView.requestFocus();
switch (item.getItemId()){
case R.id.action_save:
actionSave();
break;
case R.id.action_remove:
actionRemove();
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
private void initArguments() {
@ -78,34 +141,45 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.element, menu);
if(!getArguments().getBoolean(EDIT_ELEMENT)) {
menu.findItem(R.id.action_remove).setVisible(false);
}
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onListReturn(List<String> fields) {
listAdapter = new ElementArrayAdapter(getActivity(), R.layout.list_item_element_simple, fields, values);
listView.setAdapter(listAdapter);
// databasesListView.setAdapter(listAdapter);
// databasesListView.setOnItemClickListener(this);
progressBar.setVisibility(View.INVISIBLE);
postExecute = POST_EXECUTE_GET_FIELDS;
setHasOptionsMenu(true);
}
private List<String> getNewValues(){
List<String> newValues = new ArrayList<String>();
for(int i=0; i<listView.getChildCount();i++){
EditText editText = (EditText) listView.getChildAt(i).findViewById(R.id.editFieldValue);
newValues.add(String.valueOf(editText.getText()));
}
return newValues;
}
@Override
public void onStringReturn(String data) {
message = data;
postExecute = POST_EXECUTE_ADD_ELEMENT;
}
@Override
public void onPostExecute() {
switch (postExecute){
case POST_EXECUTE_GET_FIELDS:
listView.setAdapter(listAdapter);
progressBar.setVisibility(View.INVISIBLE);
setHasOptionsMenu(true);
break;
case POST_EXECUTE_ADD_ELEMENT:
case POST_EXECUTE_UPDATE_ELEMENT:
showInfo(message);
break;
}
// Clean after execute
postExecute = POST_EXECUTE_NONE;
}
private void showInfo(String info){
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(data);
builder.setMessage(info);
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
@ -119,8 +193,10 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
}
});*/
builder.setTitle(R.string.status);
builder.setIcon(R.drawable.ic_action_warning); //TODO Change Icon
builder.setIcon(R.drawable.ic_action_warning);
builder.setCancelable(false); // There is no exit
builder.create();
builder.show();
}
}

View file

@ -24,14 +24,14 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 15.07.14.
*
* Fragment for showing elements
*/
public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.IntegerReturnListener, View.OnClickListener {
public class EntriesFragment extends Fragment implements DatabaseConnector.MatrixReturnListener, DatabaseConnector.ListReturnListener, DatabaseConnector.IntegerReturnListener, View.OnClickListener, DatabaseConnector.OnPostExecuteListener {
private static final int HEADER_PADDING_TOP = 15;
private static final int HEADER_PADDING_BOTTOM = 15;
private static final int HEADER_PADDING_LEFT = 15;
@ -57,7 +57,13 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
private CustomScrollView fakeScrollView;
private View dummyView;
private int onPostExecuteListenerExecuted;
private Menu menu;
private TableRow headerRow;
private int[] maxWidth;
private boolean isFirstCreate;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -66,12 +72,11 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
initArguments();
initViewItems(rootView);
initListeners();
Static.asyncDatabaseConnector.setIntegerReturnListener(this);
Static.asyncDatabaseConnector.setListReturnListener(this);
Static.asyncDatabaseConnector.setMatrixReturnListener(this);
Static.asyncDatabaseConnector.getFields(tableName);
Static.asyncDatabaseConnector.getEntriesCount(tableName);
onPostExecuteListenerExecuted = 0;
Static.databaseConnector.getFields(tableName);
Static.databaseConnector.getEntriesCount(tableName);
return rootView;
}
@ -80,18 +85,19 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
databaseName = getArguments().getString(Static.DATABASE_NAME_ARG);
tableName = getArguments().getString(Static.TABLE_NAME_ARG);
page = 1;
isFirstCreate = true;
entriesLimit = PreferenceManager.getDefaultSharedPreferences(getActivity()).getInt(SettingsFragment.ENTRIES_PAGE_LIMIT, SettingsFragment.ENTRIES_PAGE_LIMIT_DEF);
}
private void initViewItems(View rootView){
headerFrame = (FrameLayout) rootView.findViewById(R.id.headerFrame);
entriesTable = (TableLayout) rootView.findViewById(R.id.entriesTable);
entriesScrollView = (ScrollView) rootView.findViewById(R.id.entriesScrollView);
fakeScrollView = (CustomScrollView) rootView.findViewById(R.id.fakeScroll);
progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
dummyView = rootView.findViewById(R.id.dummyView);
horizontalScrollView = (HorizontalScrollView) rootView.findViewById(R.id.horizontalScrollView);
entriesTable = new TableLayout(getActivity());
fakeScrollView.setOnTouchEventListener(new CustomScrollView.OnTouchEventListener() {
@Override
@ -102,9 +108,14 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
}
});
layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
headerFrame.setVisibility(View.INVISIBLE);
entriesTable.setVisibility(View.INVISIBLE);
layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT);
}
private void initListeners(){
Static.databaseConnector.setIntegerReturnListener(this);
Static.databaseConnector.setListReturnListener(this);
Static.databaseConnector.setMatrixReturnListener(this);
Static.databaseConnector.setOnPostExecuteListener(this);
}
@Override
@ -141,10 +152,12 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
private void loadAnotherPage(){
changeMenus(page);
entriesTable.removeAllViews(); // clean table
entriesScrollView.removeAllViews(); // clean table
entriesTable = new TableLayout(getActivity());
onPostExecuteListenerExecuted--;
setLoading(true);
Static.asyncDatabaseConnector.getRows(tableName, entriesLimit, page); // get new entries
Static.databaseConnector.getRows(tableName, entriesLimit, page); // get new entries
}
private void addNewElement(){
@ -203,27 +216,17 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
newRow.setClickable(true);
newRow.setOnClickListener(this);
entriesTable.addView(newRow);
syncWidths();
fakeScroll();
syncWidthsFirstStage();
}
} else {
TextView errorMessage = new TextView(getActivity());
errorMessage.setText(R.string.error_no_entries);
errorMessage.setTypeface(null, Typeface.ITALIC);
errorMessage.setClickable(false);
entriesScrollView.removeView(entriesTable);
headerFrame.setVisibility(View.VISIBLE);
entriesScrollView.addView(errorMessage);
entriesTable = null;
}
setLoading(false);
}
@Override
public void onListReturn(List<String> fieldList) {
// First we need header
TableRow headerRow;
headerRow = new TableRow(getActivity());
headerRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
rowCount = fieldList.size();
@ -236,9 +239,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
textView.setPadding(HEADER_PADDING_LEFT, HEADER_PADDING_TOP, HEADER_PADDING_RIGHT, HEADER_PADDING_BOTTOM);
headerRow.addView(textView);
}
headerFrame.addView(headerRow);
Static.asyncDatabaseConnector.getRows(tableName, entriesLimit, page);
Static.databaseConnector.getRows(tableName, entriesLimit, page);
}
@Override
@ -246,30 +248,35 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
pageCount = result/entriesLimit;
if( result%entriesLimit > 0)
pageCount++;
setHasOptionsMenu(true);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
setHasOptionsMenu(true);
}
});
}
private void syncWidths(){ // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
TableRow headerRow = (TableRow) headerFrame.getChildAt(0);
int maxWidth[]= new int[headerRow.getChildCount()];
for(int i=0;i<headerRow.getChildCount();i++){
private void syncWidthsFirstStage() { // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
maxWidth = new int[headerRow.getChildCount()];
for (int i = 0; i < headerRow.getChildCount(); i++) {
TextView textView = (TextView) headerRow.getChildAt(i);
textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
maxWidth[i] = textView.getMeasuredWidth();
}
for(int i=0;i<entriesTable.getChildCount();i++){
for (int i = 0; i < entriesTable.getChildCount(); i++) {
TableRow tableRow = (TableRow) entriesTable.getChildAt(i);
for(int j=0;j<tableRow.getChildCount();j++){
for (int j = 0; j < tableRow.getChildCount(); j++) {
TextView textView = (TextView) tableRow.getChildAt(j);
textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int width = textView.getMeasuredWidth();
if(width>maxWidth[j])
maxWidth[j]=width;
if (width > maxWidth[j])
maxWidth[j] = width;
}
}
}
private void syncWidthsSecondStage() {
for(int i=0;i<headerRow.getChildCount();i++){
TableRow entriesRow = (TableRow) entriesTable.getChildAt(0);
@ -279,9 +286,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
tmpEntries.setWidth(maxWidth[i]);
tmpHeader.setWidth(maxWidth[i]);
}
headerFrame.setVisibility(View.VISIBLE);
entriesTable.setVisibility(View.VISIBLE);
}
private void fakeScroll(){
@ -290,7 +294,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
dummyView.setMinimumHeight(height);
RelativeLayout.LayoutParams fakeScrollLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
fakeScrollLayout.setMargins(0,headerFrame.getHeight(),0,0);
headerFrame.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
fakeScrollLayout.setMargins(0,headerFrame.getMeasuredHeight(),0,0);
fakeScrollView.setLayoutParams(fakeScrollLayout);
}
@ -311,4 +316,35 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
intent.putStringArrayListExtra(ElementFragment.EDIT_LIST, values);
startActivity(intent);
}
@Override
public void onResume() {
super.onResume();
if(!isFirstCreate) {
initListeners(); // Could be overwritten
loadAnotherPage(); // This reloads entries
} else {
isFirstCreate = false;
}
}
@Override
public void onPostExecute() {
if(++onPostExecuteListenerExecuted==3){
if(headerFrame.getChildCount()==0) // You can have only one child
headerFrame.addView(headerRow);
if(entriesTable!=null) {
syncWidthsSecondStage();
entriesScrollView.addView(entriesTable);
fakeScroll();
} else {
TextView errorMessage = new TextView(getActivity());
errorMessage.setText(R.string.error_no_entries);
errorMessage.setTypeface(null, Typeface.ITALIC);
errorMessage.setClickable(false);
entriesScrollView.addView(errorMessage);
}
setLoading(false);
}
}
}

View file

@ -33,7 +33,7 @@ public class ListActivity extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
getMenuInflater().inflate(R.menu.logged, menu);
return true;
}
@ -47,6 +47,8 @@ public class ListActivity extends Activity {
if (id == R.id.action_settings) {
Static.startSettings(this);
return true;
} else if (id == R.id.action_sql){
Static.startSQL(this, getIntent().getExtras().getString(Static.DATABASE_NAME_ARG));
}
return super.onOptionsItemSelected(item);
}

View file

@ -12,21 +12,23 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 07.07.14.
*
* Fragment for login
*/
public class LoginFragment extends Fragment implements View.OnClickListener, AsyncDatabaseConnector.BooleanReturnListener {
public class LoginFragment extends Fragment implements View.OnClickListener, DatabaseConnector.BooleanReturnListener, DatabaseConnector.OnPostExecuteListener {
private EditText urlTextbox;
private EditText loginTextbox;
private EditText passwordTextbox;
private ProgressBar progressBar;
private Button loginButton;
AsyncDatabaseConnector asyncDatabaseConnector;
DatabaseConnector databaseConnector;
private boolean result;
public LoginFragment(){}
@ -84,9 +86,10 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
url = urlTextbox.getText().toString();
if(Static.isNetworkConnected(getActivity())) {
asyncDatabaseConnector = new AsyncDatabaseConnector(login, password, url);
asyncDatabaseConnector.setBooleanReturnListener(this);
asyncDatabaseConnector.checkLogin();
databaseConnector = new DatabaseConnector(login, password, url, getActivity().getResources());
databaseConnector.setBooleanReturnListener(this);
databaseConnector.setOnPostExecuteListener(this);
databaseConnector.checkLogin();
} else {
Static.showErrorAlert(getResources().getString(R.string.no_connection), getActivity());
loginButton.setEnabled(true); // Now we can click button again
@ -96,18 +99,23 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
@Override
public void onBooleanReturn(boolean result) {
this.result = result;
}
@Override
public void onPostExecute() {
if(result) {
Static.asyncDatabaseConnector = asyncDatabaseConnector;
Static.databaseConnector = databaseConnector;
Intent intent = new Intent(getActivity(), ListActivity.class);
intent.putExtra(Static.FRAGMENT_TO_START, Static.FRAGMENT_DATABASE);
startActivity(intent);
}
else {
Static.showErrorAlert(AsyncDatabaseConnector.errorMsg, getActivity());
Static.showErrorAlert(DatabaseConnector.errorMsg, getActivity());
}
loginButton.setEnabled(true); // Now we can click button again
progressBar.setVisibility(View.INVISIBLE);
}
}

View file

@ -1,108 +0,0 @@
package info.nerull7.mysqlbrowser;
/**
* Created by nerull7 on 18.07.14.
*/
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.NumberPicker;
/**
* A dialog that prompts the user for the message deletion limits.
*/
public class NumberPickerDialog extends AlertDialog implements DialogInterface.OnClickListener {
private static final String NUMBER = "number";
/**
* The callback interface used to indicate the user is done filling in
* the time (they clicked on the 'Set' button).
*/
public interface OnNumberSetListener {
/**
* @param number The number that was set.
*/
void onNumberSet(int number);
}
private final NumberPicker mNumberPicker;
private final OnNumberSetListener mCallback;
/**
* @param context Parent.
* @param callBack How parent is notified.
* @param number The initial number.
*/
public NumberPickerDialog(Context context,
OnNumberSetListener callBack,
int number,
int rangeMin,
int rangeMax,
int title) {
this(context, AlertDialog.THEME_HOLO_LIGHT, callBack, number, rangeMin, rangeMax, title);
}
/**
* @param context Parent.
* @param theme the theme to apply to this dialog
* @param callBack How parent is notified.
* @param number The initial number.
*/
public NumberPickerDialog(Context context,
int theme,
OnNumberSetListener callBack,
int number,
int rangeMin,
int rangeMax,
int title) {
super(context, theme);
mCallback = callBack;
setTitle(title);
setButton(DialogInterface.BUTTON_POSITIVE, context.getText(R.string.set), this);
setButton(DialogInterface.BUTTON_NEGATIVE, context.getText(R.string.cancel),
(OnClickListener) null);
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.number_picker_dialog, null);
setView(view);
mNumberPicker = (NumberPicker) view.findViewById(R.id.number_picker);
// initialize state
mNumberPicker.setMinValue(rangeMin);
mNumberPicker.setMaxValue(rangeMax);
mNumberPicker.setValue(number);
mNumberPicker.setOnLongPressUpdateInterval(100); // make the repeat rate three times as fast
// as normal since the range is so large.
mNumberPicker.setWrapSelectorWheel(false); // don't wrap from min->max
}
public void onClick(DialogInterface dialog, int which) {
if (mCallback != null) {
mNumberPicker.clearFocus();
mCallback.onNumberSet(mNumberPicker.getValue());
dialog.dismiss();
}
}
@Override
public Bundle onSaveInstanceState() {
Bundle state = super.onSaveInstanceState();
state.putInt(NUMBER, mNumberPicker.getValue());
return state;
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int number = savedInstanceState.getInt(NUMBER);
mNumberPicker.setValue(number);
}
}

View file

@ -0,0 +1,22 @@
package info.nerull7.mysqlbrowser;
import android.app.Activity;
import android.os.Bundle;
/**
* Created by nerull7 on 30.09.14.
*/
public class SQLActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sql);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new SQLFragment())
.commit();
}
}
}

View file

@ -0,0 +1,240 @@
package info.nerull7.mysqlbrowser;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import java.util.List;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 15.07.14.
*
* Fragment for showing elements
*/
public class SQLEntriesFragment extends Fragment implements DatabaseConnector.MatrixReturnListener, DatabaseConnector.ListReturnListener, DatabaseConnector.OnPostExecuteListener, DatabaseConnector.StringReturnListener {
private static final int HEADER_PADDING_TOP = 15;
private static final int HEADER_PADDING_BOTTOM = 15;
private static final int HEADER_PADDING_LEFT = 15;
private static final int HEADER_PADDING_RIGHT = 15;
private static final int ENTRIES_PADDING_TOP = 30;
private static final int ENTRIES_PADDING_BOTTOM = 30;
private static final int ENTRIES_PADDING_LEFT = 15;
private static final int ENTRIES_PADDING_RIGHT = 15;
private TableLayout entriesTable;
private ScrollView entriesScrollView;
private FrameLayout headerFrame;
private HorizontalScrollView horizontalScrollView;
private TableRow.LayoutParams layoutParams;
private ProgressBar progressBar;
private CustomScrollView fakeScrollView;
private View dummyView;
private boolean showError;
private Menu menu;
private TableRow headerRow;
private int[] maxWidth;
private boolean isFirstCreate;
private String errorMessage;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_entries, container, false);
initViewItems(rootView);
showError = false;
return rootView;
}
private void initViewItems(View rootView){
headerFrame = (FrameLayout) rootView.findViewById(R.id.headerFrame);
entriesScrollView = (ScrollView) rootView.findViewById(R.id.entriesScrollView);
fakeScrollView = (CustomScrollView) rootView.findViewById(R.id.fakeScroll);
progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
dummyView = rootView.findViewById(R.id.dummyView);
horizontalScrollView = (HorizontalScrollView) rootView.findViewById(R.id.horizontalScrollView);
entriesTable = new TableLayout(getActivity());
fakeScrollView.setOnTouchEventListener(new CustomScrollView.OnTouchEventListener() {
@Override
public boolean onTouchEvent(MotionEvent ev) {
ev.offsetLocation(0, headerFrame.getHeight());
horizontalScrollView.dispatchTouchEvent(ev);
return true;
}
});
layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT);
}
private void setLoading(boolean isLoading){
if(menu != null) {
menu.findItem(R.id.action_next).setEnabled(!isLoading);
menu.findItem(R.id.action_previous).setEnabled(!isLoading);
}
progressBar.setVisibility(isLoading ? View.VISIBLE : View.INVISIBLE);
}
@Override
public void onMatrixReturn(List<List<String>> rows) {
// Now we get Rows
if(rows!=null) {
int background;
for (int i = 0; i < rows.size(); i++) {
List<String> elements = rows.get(i);
TableRow newRow = new TableRow(getActivity());
if( i%2 == 0 ){ // Two backgrounds for lines for better visibility
background=R.drawable.entries_element_1;
} else {
background=R.drawable.entries_element_2;
}
for (int j = 0; j < elements.size(); j++) { // elements.size can be the same as in header so maybe some one number or not
TextView textView = new TextView(getActivity());
textView.setText(elements.get(j));
textView.setLayoutParams(layoutParams);
textView.setPadding(ENTRIES_PADDING_LEFT, ENTRIES_PADDING_TOP, ENTRIES_PADDING_RIGHT, ENTRIES_PADDING_BOTTOM);
textView.setBackgroundResource(background);
textView.setId(j);
newRow.addView(textView);
}
newRow.setClickable(false);
entriesTable.addView(newRow);
syncWidthsFirstStage();
}
} else {
entriesTable = null;
}
}
@Override
public void onListReturn(List<String> fieldList) {
// First we need header
headerRow = new TableRow(getActivity());
headerRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
for (String aFieldList : fieldList) {
TextView textView = new TextView(getActivity());
textView.setText(aFieldList);
textView.setTypeface(null, Typeface.BOLD);
textView.setLayoutParams(layoutParams);
textView.setBackgroundResource(R.drawable.background_header);
textView.setPadding(HEADER_PADDING_LEFT, HEADER_PADDING_TOP, HEADER_PADDING_RIGHT, HEADER_PADDING_BOTTOM);
headerRow.addView(textView);
}
}
private void syncWidthsFirstStage() { // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
maxWidth = new int[headerRow.getChildCount()];
for (int i = 0; i < headerRow.getChildCount(); i++) {
TextView textView = (TextView) headerRow.getChildAt(i);
textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
maxWidth[i] = textView.getMeasuredWidth();
}
for (int i = 0; i < entriesTable.getChildCount(); i++) {
TableRow tableRow = (TableRow) entriesTable.getChildAt(i);
for (int j = 0; j < tableRow.getChildCount(); j++) {
TextView textView = (TextView) tableRow.getChildAt(j);
textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int width = textView.getMeasuredWidth();
if (width > maxWidth[j])
maxWidth[j] = width;
}
}
}
private void syncWidthsSecondStage() {
for(int i=0;i<headerRow.getChildCount();i++){
TableRow entriesRow = (TableRow) entriesTable.getChildAt(0);
TextView tmpEntries = (TextView) entriesRow.getChildAt(i);
TextView tmpHeader = (TextView) headerRow.getChildAt(i);
tmpEntries.setWidth(maxWidth[i]);
tmpHeader.setWidth(maxWidth[i]);
}
}
private void fakeScroll(){
entriesScrollView.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
int height = entriesScrollView.getMeasuredHeight();
dummyView.setMinimumHeight(height);
RelativeLayout.LayoutParams fakeScrollLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
headerFrame.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
fakeScrollLayout.setMargins(0,headerFrame.getMeasuredHeight(),0,0);
fakeScrollView.setLayoutParams(fakeScrollLayout);
}
// @Override
// public void onResume() {
// super.onResume();
// if(!isFirstCreate) {
// getActivity().finish();
// } else {
// isFirstCreate = false;
// }
// }
@Override
public void onPostExecute() {
if(!showError) {
if (headerFrame.getChildCount() == 0) // You can have only one child
headerFrame.addView(headerRow);
if (entriesTable != null) {
syncWidthsSecondStage();
entriesScrollView.addView(entriesTable);
fakeScroll();
} else {
TextView errorMessage = new TextView(getActivity());
errorMessage.setText(R.string.error_no_entries);
errorMessage.setTypeface(null, Typeface.ITALIC);
errorMessage.setClickable(false);
entriesScrollView.addView(errorMessage);
}
setLoading(false);
} else {
setLoading(false);
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(errorMessage);
builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
getActivity().finish();
}
});
builder.setTitle(R.string.info);
builder.setIcon(R.drawable.ic_action_info);
builder.create();
builder.show();
}
}
@Override
public void onStringReturn(String data) {
errorMessage = data;
showError = true;
}
}

View file

@ -0,0 +1,89 @@
package info.nerull7.mysqlbrowser;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 30.09.14.
*/
public class SQLFragment extends Fragment implements DatabaseConnector.OnPostExecuteListener {
private EditText sqlEditText;
private InputMethodManager inputMethodManager;
private SQLEntriesFragment sqlEntriesFragment;
private FragmentTransaction fragmentTransaction;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sql, container, false);
sqlEditText = (EditText) rootView.findViewById(R.id.sqlQueryText);
setHasOptionsMenu(true);
return rootView;
}
@Override
public void onStart() {
super.onStart();
inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.showSoftInput(sqlEditText, InputMethodManager.SHOW_FORCED);
sqlEditText.requestFocus();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.action_execute:
actionExecute();
break;
case R.id.action_cancel:
actionCancel();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.sql, menu);
super.onCreateOptionsMenu(menu, inflater);
}
private void actionCancel(){
inputMethodManager.hideSoftInputFromWindow(sqlEditText.getWindowToken(), 0);
getActivity().finish();
}
private void actionExecute(){
String sqlQuery = String.valueOf(sqlEditText.getText());
Log.d("SQLQUERY", sqlQuery);
fragmentTransaction = getFragmentManager().beginTransaction();
sqlEntriesFragment = new SQLEntriesFragment();
fragmentTransaction.replace(R.id.container, sqlEntriesFragment);
fragmentTransaction.commit();
Static.databaseConnector.setStringReturnListener(sqlEntriesFragment);
Static.databaseConnector.setListReturnListener(sqlEntriesFragment);
Static.databaseConnector.setMatrixReturnListener(sqlEntriesFragment);
Static.databaseConnector.setOnPostExecuteListener(this);
Static.databaseConnector.executeSQL(getActivity().getIntent().getExtras().getString(Static.DATABASE_NAME_ARG), sqlQuery);
}
@Override
public void onPostExecute() {
sqlEntriesFragment.onPostExecute();
}
}

View file

@ -7,7 +7,6 @@ import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.util.Base64;
/**
@ -15,19 +14,18 @@ import android.util.Base64;
*
* Fragment for Preferences/Settings
*/
public class SettingsFragment extends PreferenceFragment implements NumberPickerDialog.OnNumberSetListener, Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
public class SettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
public static final String ENTRIES_PAGE_LIMIT = "entries_limit";
public static final String ENTRIES_PAGE_LIMIT_STRING = "entries_limit_string";
public static final String SAVE_SERVER_CREDENTIALS = "save_credentials_enabled";
public static final String URL_CREDENTIALS = "url";
public static final String LOGIN_CREDENTIALS = "login";
public static final String PASSWORD_CREDENTIALS = "password";
public static final int ENTRIES_PAGE_LIMIT_DEF = 20;
public static final int ENTRIES_MIN_PAGE = 20;
public static final int ENTRIES_MAX_PAGE = 100;
private SharedPreferences preferences;
private Preference mEntriesLimit;
private EditTextPreference mEntriesLimit;
private CheckBoxPreference saveCredentials;
private EditTextPreference connectorUrlCredentials;
private EditTextPreference loginCredentials;
@ -49,17 +47,18 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
addPreferencesFromResource(R.xml.settings);
// Getting fields
mEntriesLimit = findPreference(ENTRIES_PAGE_LIMIT);
mEntriesLimit = (EditTextPreference) findPreference(ENTRIES_PAGE_LIMIT_STRING);
saveCredentials = (CheckBoxPreference) findPreference(SAVE_SERVER_CREDENTIALS);
connectorUrlCredentials = (EditTextPreference) findPreference(URL_CREDENTIALS);
loginCredentials = (EditTextPreference) findPreference(LOGIN_CREDENTIALS);
passwordCredentials = (EditTextPreference) findPreference(PASSWORD_CREDENTIALS); // TODO: Some encryption
// Settings fields
setEntriesPageLimitSummary();
setEntriesPageLimit();
setPasswordCredentials();
// Settings Listener
mEntriesLimit.setOnPreferenceChangeListener(this);
saveCredentials.setOnPreferenceClickListener(this);
passwordCredentials.setOnPreferenceChangeListener(this);
}
@ -94,6 +93,11 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
mEntriesLimit.setSummary(getString(R.string.entries_summary, getEntriesPageLimit()));
}
private void setEntriesPageLimit(){
mEntriesLimit.setText(String.valueOf(getEntriesPageLimit()));
setEntriesPageLimitSummary();
}
private void setPasswordCredentials(){
String password;
password = preferences.getString(PASSWORD_CREDENTIALS, null);
@ -114,23 +118,6 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
} catch (Exception e) { e.printStackTrace(); } // TODO: Something useful
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if(preference == mEntriesLimit){
new NumberPickerDialog(getActivity(), this, getEntriesPageLimit(), ENTRIES_MIN_PAGE, ENTRIES_MAX_PAGE, R.string.entries_limit).show();
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
@Override
public void onNumberSet(int number) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(ENTRIES_PAGE_LIMIT, number);
editor.apply();
setEntriesPageLimitSummary();
}
@Override
public boolean onPreferenceClick(Preference preference) {
if(preference==saveCredentials){
@ -146,7 +133,16 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(preference == passwordCredentials){
savePassword((String) newValue);
} else if (preference == mEntriesLimit) {
saveEntriesLimit((String) newValue);
}
return false;
}
private void saveEntriesLimit(String newValue) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(ENTRIES_PAGE_LIMIT, Integer.parseInt(newValue));
editor.apply();
setEntriesPageLimit();
}
}

View file

@ -7,7 +7,7 @@ import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 14.07.14.
@ -20,7 +20,7 @@ public class Static {
public static final String FRAGMENT_DATABASE = "DatabaseFragment";
public static final String FRAGMENT_TABLE = "TableFragment";
public static AsyncDatabaseConnector asyncDatabaseConnector = null;
public static DatabaseConnector databaseConnector = null;
public static void startSettings(Context context){
Intent intent = new Intent(context, SettingsActivity.class);
@ -51,4 +51,10 @@ public class Static {
builder.create();
builder.show();
}
public static void startSQL(Context context, String database) {
Intent intent = new Intent(context, SQLActivity.class);
intent.putExtra(Static.DATABASE_NAME_ARG, database);
context.startActivity(intent);
}
}

View file

@ -17,17 +17,18 @@ import android.widget.TextView;
import java.util.List;
import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
import info.nerull7.mysqlbrowser.db.DatabaseConnector;
/**
* Created by nerull7 on 14.07.14.
*/
public class TableFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener{
public class TableFragment extends Fragment implements AdapterView.OnItemClickListener, DatabaseConnector.ListReturnListener, DatabaseConnector.OnPostExecuteListener {
private String databaseName;
private ListView tablesList;
private ListAdapter listAdapter;
private RelativeLayout rootView;
private ProgressBar progressBar;
private List<String> tables;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -37,8 +38,9 @@ public class TableFragment extends Fragment implements AdapterView.OnItemClickLi
tablesList = (ListView) rootView.findViewById(R.id.tableList);
this.rootView = (RelativeLayout) rootView;
progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
Static.asyncDatabaseConnector.setListReturnListener(this);
Static.asyncDatabaseConnector.getTables();
Static.databaseConnector.setListReturnListener(this);
Static.databaseConnector.setOnPostExecuteListener(this);
Static.databaseConnector.getTables();
return rootView;
}
@ -59,6 +61,11 @@ public class TableFragment extends Fragment implements AdapterView.OnItemClickLi
@Override
public void onListReturn(List<String> tables) {
this.tables = tables;
}
@Override
public void onPostExecute() {
if(tables != null) {
listAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1, tables);
tablesList.setAdapter(listAdapter);

View file

@ -1,330 +0,0 @@
package info.nerull7.mysqlbrowser.db;
import android.os.AsyncTask;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Created by nerull7 on 07.07.14.
* Database connector using Async calls
*/
public class AsyncDatabaseConnector {
public static final String ACTION_LOGIN = "login";
public static final String ACTION_DATABASE_LIST = "dblist";
public static final String ACTION_TABLE_LIST = "tablelist";
public static final String ACTION_FIELD_LIST = "fieldlist";
public static final String ACTION_ENTRIES_COUNT = "numrows";
public static final String ACTION_DATA_MATRIX = "getrows";
public static final String ACTION_ADD_ELEMENT = "addelement";
public static final String ACTION_UPDATE_ELEMENT = "updateelement";
private String login;
private String password;
private String url;
private String database;
private BooleanReturnListener booleanReturnListener;
private IntegerReturnListener integerReturnListener;
private StringReturnListener stringReturnListener;
private ListReturnListener listReturnListener;
private MatrixReturnListener matrixReturnListener;
public static String errorMsg;
public AsyncDatabaseConnector(String login, String password, String url){
this.login = login;
this.password = password;
this.url = url;
booleanReturnListener=null;
stringReturnListener=null;
listReturnListener=null;
matrixReturnListener=null;
}
private String actionUrlBuilder(String action){ // TODO Better UrlBuilder this is shit only for use
String urlBuilder = url;
urlBuilder += "?u="+login;
urlBuilder += "&p="+password;
urlBuilder += "&a="+action;
// Log.d("URLBuilder", urlBuilder);
return urlBuilder;
}
public void setDatabaseInUse(String database){
this.database = database;
}
private void getList(String urlQuery){
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
List<String>list = null;
try {
list = parseListFromJSON(data);
} catch (JSONException e) { e.printStackTrace(); }
if(listReturnListener!=null)
listReturnListener.onListReturn(list);
}
});
downloader.execute(urlQuery);
}
private void getMatrix(String urlQuery){
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
List<List<String>> list = null;
try {
list = parseMatrixFromJSON(data);
} catch (JSONException e) { e.printStackTrace(); }
if(matrixReturnListener!=null)
matrixReturnListener.onMatrixReturn(list);
}
});
downloader.execute(urlQuery);
}
private List<String> parseListFromJSON(String jsonListString) throws JSONException {
JSONArray jsonArray = new JSONArray(jsonListString);
List<String> databaseStringList = new ArrayList<String>();
for(int i=0;i<jsonArray.length();i++){
databaseStringList.add(jsonArray.getString(i));
}
return databaseStringList;
}
private List<List<String>> parseMatrixFromJSON(String jsonMatrixString) throws JSONException {
JSONArray jsonMatrix = new JSONArray(jsonMatrixString);
List<List<String>> matrix = new ArrayList<List<String>>();
for(int i=0;i<jsonMatrix.length();i++){
JSONArray jsonArray = jsonMatrix.getJSONArray(i);
List<String> list = new ArrayList<String>();
for(int j=0;j<jsonArray.length();j++){
list.add(jsonArray.getString(j));
}
matrix.add(list);
}
return matrix;
}
public boolean checkLogin(){
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
boolean listenerData;
if(data == null) {
listenerData = false;
errorMsg = error;
} else if( data.compareTo("OK") == 0){
listenerData = true;
} else {
errorMsg = data;
listenerData = false;
}
booleanReturnListener.onBooleanReturn(listenerData);
}
});
downloader.execute(actionUrlBuilder(ACTION_LOGIN));
return false;
}
public void getDatabases(){
getList(actionUrlBuilder(ACTION_DATABASE_LIST));
}
public void getTables(){
getList(actionUrlBuilder(ACTION_TABLE_LIST)+"&d="+database);
}
public void getFields(String table){
getList(actionUrlBuilder(ACTION_FIELD_LIST)+"&d="+database+"&t="+table);
}
public void getRows(String table, int count, int page){
int limitStart = (page-1) * count;
getMatrix(actionUrlBuilder(ACTION_DATA_MATRIX)+"&d="+database+"&t="+table+"&s="+limitStart+"&l="+count);
}
public void getEntriesCount(String table){
String urlQuery = actionUrlBuilder(ACTION_ENTRIES_COUNT)+"&d="+database+"&t="+table;
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
if(integerReturnListener!=null)
integerReturnListener.onIntegerReturn(Integer.parseInt(data));
}
});
downloader.execute(urlQuery);
}
public void addNewElement(String table, List<String> header, List<String> values) {
this.updateElement(table, header, null, values);
}
public void updateElement(String table, List<String> header, List<String> oldValues, List<String> newValues){
JSONArray headerJSON = new JSONArray();
JSONArray newValuesJSON = new JSONArray();
String request;
for (String aHeader : header) {
headerJSON.put(aHeader);
}
for (String newValue : newValues) {
newValuesJSON.put(newValue);
}
if(oldValues!=null){
JSONArray oldValuesJSON = new JSONArray();
for(int i=0;i<newValues.size();i++){
oldValuesJSON.put(oldValues.get(i));
}
request = actionUrlBuilder(ACTION_UPDATE_ELEMENT)+"&d="+database+"&t="+table+"&h="+headerJSON+"&v="+newValuesJSON+"&o="+oldValuesJSON;
} else
request = actionUrlBuilder(ACTION_ADD_ELEMENT)+"&d="+database+"&t="+table+"&h="+headerJSON+"&v="+newValuesJSON;
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
if(stringReturnListener!=null){
stringReturnListener.onStringReturn(data);
}
}
});
downloader.execute(request);
}
public void setBooleanReturnListener(BooleanReturnListener booleanReturnListener){
this.booleanReturnListener = booleanReturnListener;
}
public void setStringReturnListener(StringReturnListener stringReturnListener) {
this.stringReturnListener = stringReturnListener;
}
public void setIntegerReturnListener(IntegerReturnListener integerReturnListener){
this.integerReturnListener = integerReturnListener;
}
public void setListReturnListener(ListReturnListener listReturnListener) {
this.listReturnListener = listReturnListener;
}
public void setMatrixReturnListener(MatrixReturnListener matrixReturnListener) {
this.matrixReturnListener = matrixReturnListener;
}
public static interface BooleanReturnListener{
public void onBooleanReturn(boolean result);
}
public static interface IntegerReturnListener{
public void onIntegerReturn(int result);
}
public static interface StringReturnListener{
public void onStringReturn(String data);
}
public static interface ListReturnListener {
public void onListReturn(List<String> data);
}
public static interface MatrixReturnListener{
public void onMatrixReturn(List<List<String>> data);
}
private static class Downloader extends AsyncTask<String, Void, String> {
private OnFinishedListener onFinishedListener;
private String errorString;
public static final String CONNECTION_REQUEST_METHOD = "GET";
public static final int CONNECTION_TIMEOUT = 15000;
public static final int READ_TIMEOUT = 10000;
Downloader(OnFinishedListener onFinishedListener){
this.onFinishedListener = onFinishedListener;
errorString = null;
}
private String httpRequest(String urlRequest) throws IOException {
URL url = new URL(urlRequest);
InputStream inputStream = null;
String response;
Log.d("URL REQUEST", urlRequest);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); // TODO Handling no connection
urlConnection.setReadTimeout(READ_TIMEOUT);
urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
urlConnection.setRequestMethod(CONNECTION_REQUEST_METHOD);
urlConnection.connect();
if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
try {
inputStream = urlConnection.getInputStream();
response = readStream(inputStream);
} finally {
if(inputStream!=null)
inputStream.close();
urlConnection.disconnect();
}
return response;
}
else {
errorString = "ERROR "+urlConnection.getResponseCode()+": "+urlConnection.getResponseMessage();
return null;
}
}
private String readStream(InputStream in) throws IOException {
String streamOutput = "";
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
streamOutput += line;
}
} finally {
if (reader != null) {
reader.close();
}
}
return streamOutput;
}
@Override
protected String doInBackground(String... strings) {
try {
return httpRequest(strings[0]);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String data) {
onFinishedListener.onFinished(data, errorString); // Can't be null cos we demand listener in constructor
}
private static interface OnFinishedListener {
void onFinished(String data, String error);
}
}
}

View file

@ -0,0 +1,565 @@
package info.nerull7.mysqlbrowser.db;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import info.nerull7.mysqlbrowser.R;
/**
* Created by nerull7 on 07.07.14.
* Database connector using Async calls
*/
public class DatabaseConnector {
public static final String ACTION_LOGIN = "login";
public static final String ACTION_DATABASE_LIST = "dblist";
public static final String ACTION_TABLE_LIST = "tablelist";
public static final String ACTION_FIELD_LIST = "fieldlist";
public static final String ACTION_ENTRIES_COUNT = "numrows";
public static final String ACTION_DATA_MATRIX = "getrows";
public static final String ACTION_ADD_ELEMENT = "addelement";
public static final String ACTION_UPDATE_ELEMENT = "updateelement";
public static final String ACTION_REMOVE_ELEMENT = "removeelement";
public static final String ACTION_SQL_QUERY = "query";
private String login;
private String password;
private String url;
private String database;
private final Resources resources;
private BooleanReturnListener booleanReturnListener;
private IntegerReturnListener integerReturnListener;
private StringReturnListener stringReturnListener;
private ListReturnListener listReturnListener;
private MatrixReturnListener matrixReturnListener;
public static String errorMsg;
private OnPostExecuteListener onPostExecuteListener;
public DatabaseConnector(String login, String password, String url, Resources resources){
this.login = login;
this.password = password;
this.url = url;
this.resources = resources;
booleanReturnListener=null;
stringReturnListener=null;
listReturnListener=null;
matrixReturnListener=null;
}
private Request requestBuilder(String action){
Request request = new Request(url);
String urlData = "u="+login
+ "&p="+password
+ "&a="+action;
request.data = urlData;
return request;
}
private Request actionUrlBuilder(String action, String argument, String value){
ArrayList<String> arguments = new ArrayList<String>();
ArrayList<String> values = new ArrayList<String>();
arguments.add(argument);
values.add(value);
return this.actionUrlBuilder(action, arguments, values);
}
private Request actionUrlBuilder(String action, List<String> arguments, List<String> values){ // TODO Better UrlBuilder this is shit only for use
Request urlBuilder = requestBuilder(action);
for (int i = 0; i < arguments.size(); i++) {
try {
urlBuilder.data += "&" + arguments.get(i) + "=" + URLEncoder.encode(values.get(i), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
// Log.d("URLBuilder", urlBuilder);
return urlBuilder;
}
public void setDatabaseInUse(String database){
this.database = database;
}
private void getList(Request urlQuery){
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
List<String>list = null;
try {
list = parseListFromJSON(data);
} catch (JSONException e) { e.printStackTrace(); }
if(listReturnListener!=null) {
listReturnListener.onListReturn(list);
}
errorMsg = error;
}
}, onPostExecuteListener, resources);
downloader.execute(urlQuery);
}
private void getMatrix(Request urlQuery){
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
List<List<String>> list = null;
try {
list = parseMatrixFromJSON(data);
} catch (JSONException e) { e.printStackTrace(); }
if(matrixReturnListener!=null)
matrixReturnListener.onMatrixReturn(list);
errorMsg = error;
}
}, onPostExecuteListener, resources);
downloader.execute(urlQuery);
}
private List<String> parseListFromJSON(String jsonListString) throws JSONException {
JSONArray jsonArray = new JSONArray(jsonListString);
List<String> databaseStringList = new ArrayList<String>();
for(int i=0;i<jsonArray.length();i++){
databaseStringList.add(jsonArray.getString(i));
}
return databaseStringList;
}
private List<List<String>> parseMatrixFromJSON(String jsonMatrixString) throws JSONException {
JSONArray jsonMatrix = new JSONArray(jsonMatrixString);
List<List<String>> matrix = new ArrayList<List<String>>();
for(int i=0;i<jsonMatrix.length();i++){
JSONArray jsonArray = jsonMatrix.getJSONArray(i);
List<String> list = new ArrayList<String>();
for(int j=0;j<jsonArray.length();j++){
list.add(jsonArray.getString(j));
}
matrix.add(list);
}
return matrix;
}
public boolean checkLogin(){
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
boolean listenerData;
if(data == null) {
listenerData = false;
errorMsg = error;
} else if( data.compareTo("OK") == 0){
listenerData = true;
} else {
errorMsg = data;
listenerData = false;
}
booleanReturnListener.onBooleanReturn(listenerData);
}
}, onPostExecuteListener, resources);
downloader.execute(requestBuilder(ACTION_LOGIN));
return false;
}
public void getDatabases(){
getList(requestBuilder(ACTION_DATABASE_LIST));
}
public void getTables(){
getList(actionUrlBuilder(ACTION_TABLE_LIST, "d", database));
}
public void getFields(String table){
ArrayList<String> args = new ArrayList<String>();
ArrayList<String> values = new ArrayList<String>();
args.add("d");
values.add(database);
args.add("t");
values.add(table);
getList(actionUrlBuilder(ACTION_FIELD_LIST, args, values));
}
public void getRows(String table, int count, int page){
int limitStart = (page-1) * count;
ArrayList<String> args = new ArrayList<String>();
ArrayList<String> values = new ArrayList<String>();
args.add("d");
values.add(database);
args.add("t");
values.add(table);
args.add("s");
values.add(String.valueOf(limitStart));
args.add("l");
values.add(String.valueOf(count));
getMatrix(actionUrlBuilder(ACTION_DATA_MATRIX, args, values));
}
public void getEntriesCount(String table){
ArrayList<String> args = new ArrayList<String>();
ArrayList<String> values = new ArrayList<String>();
args.add("d");
values.add(database);
args.add("t");
values.add(table);
Request urlQuery = actionUrlBuilder(ACTION_ENTRIES_COUNT, args, values);
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
if(integerReturnListener!=null)
integerReturnListener.onIntegerReturn(Integer.parseInt(data));
errorMsg = error;
}
}, onPostExecuteListener, resources);
downloader.execute(urlQuery);
}
public void addNewElement(String table, List<String> header, List<String> values) {
this.updateElement(table, header, null, values);
}
public void updateElement(String table, List<String> header, List<String> oldValues, List<String> newValues){
JSONArray headerJSON = new JSONArray();
JSONArray newValuesJSON = new JSONArray();
Request request;
ArrayList<String> args = new ArrayList<String>();
ArrayList<String> values = new ArrayList<String>();
args.add("d");
values.add(database);
args.add("t");
values.add(table);
for (String aHeader : header) {
headerJSON.put(aHeader);
}
for (String newValue : newValues) {
newValuesJSON.put(newValue);
}
args.add("h");
values.add(headerJSON.toString());
args.add("v");
values.add(newValuesJSON.toString());
if(oldValues!=null){
JSONArray oldValuesJSON = new JSONArray();
for(int i=0;i<newValues.size();i++){
oldValuesJSON.put(oldValues.get(i));
}
args.add("o");
values.add(oldValuesJSON.toString());
request = actionUrlBuilder(ACTION_UPDATE_ELEMENT, args, values);
} else
request = actionUrlBuilder(ACTION_ADD_ELEMENT, args, values);
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
if(stringReturnListener!=null){
stringReturnListener.onStringReturn(data);
}
errorMsg = error;
}
}, onPostExecuteListener, resources);
downloader.execute(request);
}
public void removeElement(String table, List<String> header, List<String> values) {
JSONArray headerJSON = new JSONArray();
JSONArray valuesJSON = new JSONArray();
Request request;
ArrayList<String> args = new ArrayList<String>();
ArrayList<String> argValues = new ArrayList<String>();
args.add("d");
argValues.add(database);
args.add("t");
argValues.add(table);
for (String aHeader : header) {
headerJSON.put(aHeader);
}
for (String value : values) {
valuesJSON.put(value);
}
args.add("h");
argValues.add(headerJSON.toString());
args.add("v");
argValues.add(valuesJSON.toString());
request = actionUrlBuilder(ACTION_REMOVE_ELEMENT, args, argValues);
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
if(stringReturnListener!=null){
stringReturnListener.onStringReturn(data);
}
errorMsg = error;
}
}, onPostExecuteListener, resources);
downloader.execute(request);
}
public void executeSQL(String database, String query){
ArrayList<String> args = new ArrayList();
ArrayList<String> values = new ArrayList();
final Request request;
if(database!=null){
args.add("d");
values.add(database);
}
args.add("q");
values.add(query);
request = actionUrlBuilder(ACTION_SQL_QUERY, args, values);
Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
@Override
public void onFinished(String data, String error) {
String []response = data.split("\n");
if(response[0].equals("OK")) {
List<String> headerList = null;
try {
headerList = parseListFromJSON(response[1]);
} catch (JSONException e) {
e.printStackTrace();
}
if (listReturnListener != null) {
listReturnListener.onListReturn(headerList);
}
List<List<String>> dataMatrix = null;
try {
dataMatrix = parseMatrixFromJSON(response[2]);
} catch (JSONException e) {
e.printStackTrace();
}
if (matrixReturnListener != null)
matrixReturnListener.onMatrixReturn(dataMatrix);
} else {
if(stringReturnListener!=null)
stringReturnListener.onStringReturn(data);
}
}
}, onPostExecuteListener, resources);
downloader.execute(request);
}
public void setBooleanReturnListener(BooleanReturnListener booleanReturnListener){
this.booleanReturnListener = booleanReturnListener;
}
public void setStringReturnListener(StringReturnListener stringReturnListener) {
this.stringReturnListener = stringReturnListener;
}
public void setIntegerReturnListener(IntegerReturnListener integerReturnListener){
this.integerReturnListener = integerReturnListener;
}
public void setListReturnListener(ListReturnListener listReturnListener) {
this.listReturnListener = listReturnListener;
}
public void setMatrixReturnListener(MatrixReturnListener matrixReturnListener) {
this.matrixReturnListener = matrixReturnListener;
}
public void setOnPostExecuteListener(OnPostExecuteListener onPostExecuteListener){
this.onPostExecuteListener = onPostExecuteListener;
}
public static interface BooleanReturnListener{
public void onBooleanReturn(boolean result);
}
public static interface IntegerReturnListener{
public void onIntegerReturn(int result);
}
public static interface StringReturnListener{
public void onStringReturn(String data);
}
public static interface ListReturnListener {
public void onListReturn(List<String> data);
}
public static interface MatrixReturnListener{
public void onMatrixReturn(List<List<String>> data);
}
public static interface OnPostExecuteListener {
void onPostExecute();
}
private static class Downloader extends AsyncTask<Request, Void, String> {
private OnFinishedListener onFinishedListener;
private OnPostExecuteListener onPostExecuteListener;
private String errorString;
private Resources resources;
public static final String CONNECTION_REQUEST_METHOD = "POST";
public static final int CONNECTION_TIMEOUT = 15000; // ms
public static final int READ_TIMEOUT = 10000; // ms
private Downloader(OnFinishedListener onFinishedListener, OnPostExecuteListener onPostExecuteListener, Resources resources){
this.onFinishedListener = onFinishedListener;
this.onPostExecuteListener = onPostExecuteListener;
this.resources = resources;
errorString = null;
}
private String httpRequest(Request urlRequest) throws IOException {
URL url = new URL(urlRequest.url);
InputStream inputStream = null;
String response;
// Log.d("URL REQUEST", urlRequest);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); // TODO Handling no connection
urlConnection.setReadTimeout(READ_TIMEOUT);
urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
urlConnection.setRequestMethod(CONNECTION_REQUEST_METHOD);
OutputStream outputStream = urlConnection.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write(urlRequest.data);
outputStreamWriter.flush();
outputStreamWriter.close();
outputStream.close();
try {
urlConnection.connect();
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
try {
inputStream = urlConnection.getInputStream();
response = readStream(inputStream);
} finally {
if (inputStream != null)
inputStream.close();
urlConnection.disconnect();
}
return response;
} else {
errorString = "ERROR " + urlConnection.getResponseCode() + ": " + urlConnection.getResponseMessage();
}
} catch (Exception e) {
parseException(e);
}
return null;
}
private void parseException(Exception e){
if(e instanceof SocketException){
if(e.getMessage().contains("ECONNREFUSED")) {
errorString = resources.getString(R.string.error_connection_refused);
} else if(e.getMessage().contains("EHOSTUNREACH")) {
errorString = resources.getString(R.string.error_connection_unreachable);
} else {
errorString = "Exception: " + e.getClass();
}
} else if (e instanceof SocketTimeoutException){
errorString = resources.getString(R.string.error_connection_timeout);
} else {
errorString = "Exception: " + e.getClass();
}
}
private String readStream(InputStream in) throws IOException {
String streamOutput = "";
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
streamOutput += line + '\n';
}
} finally {
if (reader != null) {
reader.close();
}
}
return streamOutput.substring(0, streamOutput.length()-1); // Remove last \n
}
@Override
protected String doInBackground(Request... requests) {
try {
String data = httpRequest(requests[0]);
onFinishedListener.onFinished(data, errorString); // Can't be null cos we demand listener in constructor
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String data) {
if (onPostExecuteListener!=null)
onPostExecuteListener.onPostExecute();
}
public void setOnPostExecuteListener(OnPostExecuteListener onPostExecuteListener) {
this.onPostExecuteListener = onPostExecuteListener;
}
private static interface OnFinishedListener {
void onFinished(String data, String error);
}
}
class Request{
String url;
String data;
Request(String url){
this.url = url;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.nerull7.mysqlbrowser.ListActivity"
tools:ignore="MergeRootFrame" />

View file

@ -18,6 +18,7 @@
android:id="@+id/listView"
android:layout_below="@+id/progressBar"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
android:layout_alignParentStart="true"
android:descendantFocusability="afterDescendants"/>
</RelativeLayout>

View file

@ -26,11 +26,11 @@
android:id="@+id/entriesScrollView"
android:layout_below="@+id/headerFrame"
android:scrollbars="none">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/entriesTable">
</TableLayout>
<!--<TableLayout-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:id="@+id/entriesTable">-->
<!--</TableLayout>-->
</ScrollView>
</RelativeLayout>
</HorizontalScrollView>

View file

@ -0,0 +1,24 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.nerull7.mysqlbrowser.DatabaseFragment">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:ems="10"
android:id="@+id/sqlQueryText"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:gravity="left|top"
android:hint="@string/hint_sql_query" >
<requestFocus/>
</EditText>
</RelativeLayout>

View file

@ -7,4 +7,9 @@
android:showAsAction="always"
android:icon="@drawable/ic_action_save"/>
<item android:id="@+id/action_remove"
android:title="@string/action_remove"
android:showAsAction="always"
android:icon="@drawable/ic_action_delete"/>
</menu>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never" />
<item android:id="@+id/action_sql"
android:title="@string/sql_query"
android:orderInCategory="200"
android:showAsAction="never" />
</menu>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/action_execute"
android:title="@string/action_execute"
android:showAsAction="always"
android:icon="@drawable/ic_action_file_upload"/>
<item android:id="@+id/action_cancel"
android:title="@string/action_cancel"
android:showAsAction="always"
android:icon="@drawable/ic_action_delete"/>
</menu>

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Przeglądarka Mysql</string>
<string name="action_settings">Ustawienia</string>
<string name="action_add">Dodaj nowy</string>
<string name="action_remove">Usuń</string>
<string name="action_previous">Poprzedni</string>
<string name="action_next">Następny</string>
<string name="title_fragment_database">Dostępne bazy</string>
<string name="login">Zaloguj</string>
<string name="password">Hasło</string>
<string name="username">Użytkownik</string>
<string name="yes">Tak</string>
<string name="no">Nie</string>
<string name="ok">OK</string>
<string name="cancel">Anuluj</string>
<string name="action_save">Zapisz</string>
<string name="set">Ustaw</string>
<string name="back">Cofnij</string>
<string name="status">Info</string>
<string name="warning">Ostrzeżenie</string>
<string name="error">Błąd</string>
<string name="login_error">Zły login/hasło</string>
<string name="general_category">Ogólne</string>
<string name="entries_limit">Limit wpisów na stronę</string>
<string name="entries_summary">%s na stronę</string> <!-- <xliff:g id="count"></xliff:g> -->
<string name="error_no_tables">Brak tabel w tej bazie</string>
<string name="error_no_entries">Brak wpisów w tej bazie</string>
<string name="error_no_databases">Brak dostępnych baz</string>
<string name="error_no_save">Twoje dane <b>NIE</b> zostaną zapisane! Czy chciałbyś kontynuować?</string>
<string name="error_remove">Ten wpis zostanie usunięty z bazy. Tej akcji <b>NIE MOŻNA</b> cofnąć! Czy chciałbyś kontynuować?</string>
<string name="error_connection_timeout">Przekroczono czas połączenia</string>
<string name="error_connection_reset">Połączenie zostało zrestartowane</string>
<string name="error_connection_unreachable">No route to host</string>
<string name="pref_entries_per_page">Ustaw limit wpisów na stronę</string>
<string name="login_settings">Poświadczenia logowania</string>
<string name="save_credentials">Zapamiętaj poświadczenia</string>
<string name="connector_url">URL Wtyczki php</string>
<string name="no_connection">Brak połączenia internetowego</string>
</resources>

View file

@ -1,43 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Mysql Browser</string>
<string name="action_settings">Settings</string>
<string name="action_add">Add new</string>
<string name="action_remove">Remove</string>
<string name="action_previous">Previous</string>
<string name="action_next">Next</string>
<string name="title_activity_main">MainActivity</string>
<string name="title_activity_entries">EntriesActivity</string>
<string name="title_activity_setting">Settings</string>
<string name="title_activity_element">ElementActivity</string>
<string name="title_activity_list">ListActivity</string>
<string name="title_fragment_database">Available Databases</string>
<string name="login">Log in</string>
<string name="password">Password</string>
<string name="username">Username</string>
<string name="hint_url">URL ex: https://example.com/c.php</string>
<string name="title_activity_main">MainActivity</string>
<string name="hello_world">Hello world!</string>
<string name="login_error">Wrong login/password</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="ok">OK</string>
<string name="cancel">Cancel</string>
<string name="action_save">Save</string>
<string name="set">Set</string>
<string name="back">Back</string>
<string name="status">Status</string>
<string name="warning">Warning</string>
<string name="error">Error</string>
<string name="title_activity_entries">EntriesActivity</string>
<string name="login_error">Wrong login/password</string>
<string name="general_category">General</string>
<string name="entries_limit">Entries per page limit</string>
<string name="entries_summary">%s entries per page</string> <!-- <xliff:g id="count"></xliff:g> -->
<string name="title_activity_setting">Settings</string>
<string name="cancel">Cancel</string>
<string name="set">Set</string>
<string name="pref_entries_per_page">Set number of entries per page</string>
<string name="error_no_tables">No tables in this database</string>
<string name="error_no_entries">No entries in this table</string>
<string name="error_no_databases">No available databases</string>
<string name="action_previous">Previous</string>
<string name="action_next">Next</string>
<string name="error_no_save">Your data will <b>NOT</b> be saved! Would you like to continue?</string>
<string name="error_remove">This entry will be removed from database. This action <b>CAN NOT</b> be reversed! Would you like to continue?</string>
<string name="error_connection_timeout">Connection timeout</string>
<string name="error_connection_reset">Connection reset by peer</string>
<string name="error_connection_refused">Connection refused</string>
<string name="error_connection_unreachable">No route to host</string>
<string name="pref_entries_per_page">Set number of entries per page</string>
<string name="login_settings">Login credentials</string>
<string name="save_credentials">Save credentials</string>
<string name="connector_url">Connector URL</string>
<string name="no_connection">No Internet Connection</string>
<string name="action_add">Add new</string>
<string name="title_activity_element">ElementActivity</string>
<string name="action_save">Save</string>
<string name="title_fragment_database">Available Databases</string>
<string name="title_activity_list">ListActivity</string>
<string name="error_no_save">Your data will NOT be saved! Would you like to continue?</string>
<string name="yes">Yes</string>
<string name="warning">Warning</string>
<string name="status">Status</string>
<string name="back">Back</string>
<string name="sql_query">SQL Query</string>
<string name="title_activity_sql">SQL Query</string>
<string name="hint_sql_query">SQL Query</string>
<string name="action_cancel">Cancel</string>
<string name="action_execute">Execute</string>
<string name="info">Information</string>
</resources>

View file

@ -3,8 +3,9 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/general_category">
<Preference
android:key="entries_limit"
<EditTextPreference
android:key="entries_limit_string"
android:numeric="integer"
android:title="@string/entries_limit"
android:summary="@string/entries_summary"
/>