Pull to refresh

Превращение Android телефона в сетевую SQL базу данных (MyMobileSQLServer — Utesov)

Reading time5 min
Views26K
Недавно я начал делать очередной проект для мобильных устройств. Его побочным продуктом стало приложение, с помощью которого можно развернуть сетевую базу данных на любимом Android телефоне, планшете и т.п… Предлагаемое решение является сетевым провайдером SQLite базы данных.

Приложение многопользовательское, каждый пользователь имеет свою БД, которая недоступна другим пользователям. Код открытый, лицензия Apache 2.0.

Для демонстрации заявленных возможностей написано простое приложение которое позволяет делать SQL запросы на сервер и получать результаты их выполнения, его код рассмотрим здесь. Время освоения — 10 минут. Для тестирования достаточно одного устройства (если используется два и более, то необходимо WiFi подключение). Поехали!

image
Кадр из к\ф «Весёлые ребята» (доработанный)

Прежде всего устанавливаем приложение (сервер) MyMobileSQLServer — Utesov из PlayMarket, Yandex.Store или из репозитория. Далее необходимо создать пользователя для доступа к данным и саму базу данных. Для этого на главном экране выберите «edit user» -> «Add user». Заполняйте поля формы. После возвращайтесь на главный экран приложения и запускайте его с помощью кнопки «on». Обратите внимание на порт и IP адрес для подключения.

image

Перейдем к непосредственному созданию приложения для доступа к сетевой БД.

1 — Создаем новый проект. Копируем файл библиотеки «myMobileSQLClient.jar» в директорию для хранения библиотек и делаем необходимые действия, чтобы она стала доступна для проекта

2 — Настраиваем манифест проекта, добавляем директиву для возможности использования подключения к сети:

<uses-permission android:name=«android.permission.INTERNET» />

3 — Кидаем на форму:
пять полей ввода: IP адрес, номер порта, текст для sql запроса, логин, пароль;
три кнопки: подключиться, отключиться, отправить запрос;
поле для вывода информации.
У вас должно получиться примерно так:

image

Копируем следующий код с необходимыми корректировками:

import ru.gc986.SQLClient.MainMobileSQLClient; 
import ru.gc986.SQLClient.parse.DATA_request; 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.TextView; 

public class MainActivity extends Activity { 

	MainMobileSQLClient mainMobileSQLClient; 
	 
	@Override 
	protected void onCreate(Bundle savedInstanceState) { 
		super.onCreate(savedInstanceState); 
		setContentView(R.layout.activity_main); 
		 
		// Подключение к серверу		 
		Button bt_connect = (Button) findViewById(R.id.button_connect); 
		bt_connect.setOnClickListener(new View.OnClickListener() { 
			@Override 
			public void onClick(View v) { 
				EditText et_ip = (EditText) findViewById(R.id.editText_ip); 
				EditText et_port = (EditText) findViewById(R.id.editText_port); 
				mainMobileSQLClient = new MainMobileSQLClient(et_ip.getText().toString(),Integer.parseInt(et_port.getText().toString())){ 
					 
					/**Пришло новое сообщение с сервера*/ 
					@Override 
					public void onMessage(String id, DATA_parser data){ 
						super.onMessage(id, data); 
						TextView tv_log = (TextView) findViewById(R.id.textView_log); 
						 
						String message = ""; 
						for(int i = 0 ; i < data.recordsCount ; i ++){ 
							for(int i1 = 0 ; i1 < data.structure.length ; i1++) 
							{ 
								message = message + "\n" + data.structure[i1] + " : " + data.listData.get(i)[i1]; 
							} 
							message = message + "\n" + "-----"; 
						} 
						message = "Status - " + data.status + "\n" + message + "\n" + "======" + "\n"; 
						tv_log.setText(message + tv_log.getText().toString()); 
					} 
					 
					/**Начинается процесс подключения к серверу*/ 
					@Override 
					public void onConnection(){ 
						super.onConnection(); 
						 
					} 
					 
					/**Подключились к серверу*/ 
					@Override 
					public void onConnect(){ 
						super.onConnect(); 
						 
						// Аутентификация 
						EditText et_login = (EditText) findViewById(R.id.editText_login); 
						EditText et_pass = (EditText) findViewById(R.id.editText_pass); 
						onAuthentication(et_login.getText().toString(), et_pass.getText().toString()); 
					} 
					 
					/**Сообщаем что отключились от сервера*/ 
					@Override 
					public void onDisconnect(){ 
						showAllView(); 
					} 
					 
					/**Ошибка регистрации на сервере*/ 
					@Override 
					public void onErrAuthentication(){ 
						showAllView(); 
					} 
					 
					/**Регитрация прошла успешно*/ 
					@Override 
					public void onCompleteAuthentication(){ 
					} 
					 

				}; 
				mainMobileSQLClient.startClient(); 
			} 
		}); 
		 
		// Отключение от сервера 
		Button bt_disconnect = (Button) findViewById(R.id.button_disconnect); 
		bt_disconnect.setOnClickListener(new View.OnClickListener() { 
			@Override 
			public void onClick(View v) { 
				if(mainMobileSQLClient!=null) 
					mainMobileSQLClient.stopClient(); 
			} 
		}); 
		 
		// Отправить сообщение 
		Button bt_request = (Button) findViewById(R.id.button_request); 
		bt_request.setOnClickListener(new View.OnClickListener() { 
			 
			@Override 
			public void onClick(View v) { 
				EditText et_request = (EditText) findViewById(R.id.editText_sql_request); 
				 
				if(mainMobileSQLClient!=null) 
					mainMobileSQLClient.sendSQLRequest(et_request.getText().toString()); 
			} 
		}); 
	} 

}


Теперь разберемся что происходит.
За работу с удаленной БД отвечает данный объект:
MainMobileSQLClient mainMobileSQLClient;
В нём переопределены следующие методы:
onMessage — пришло сообщение с сервера;
onConnection — клиент осуществляет подключение к серверу;
onConnect — клиент подсоединился к серверу;
onDisconnect — клиент отсоединился от сервера;
onErrAuthentication — ошибка аутентификации;
onCompleteAuthentication — аутентификация прошла успешно;

При создании главного объекта задается IP адрес сервера и порт для подключения. Запуск клиента осуществляется с помощью метода startClient(). Начало подключения сопровождается методом onConnection. Если произошла ошибка подключения, то вызывается метод onDisconnect, который также вызывается при отключении клиента от сервера (например при разрыве соединения или отключении сервера). Если всё произошло в штатном режиме, то завершение процесса подключения ознаменует метод onConnect.

Далее необходимо произвести регистрацию пользователя на сервере, лучше всего делать это после окончания подключения, прямо в методе onConnect:

onAuthentication(''user_name'', ''pass_pass'');

В случае успеха аутентификации, будет вызван метод onCompleteAuthentication, иначе onErrAuthentication. Если аутентификация не произошла, то скорее всего ваши логин и пароль не совпадают с теми, которые были зарегистрированы на сервере.

Теперь дело остается за малым — делать запросы и обрабатывать реакцию на приходящие данные.
Чтобы инициировать SQL запрос, необходимо вызвать метод (пример):
String id_request = mainMobileSQLClient.sendSQLRequest(''select * from test;'');
Он, в свою очередь, возвратит идентификатор запроса в виде текстовой строки. Это важно, так как это сетевое приложение, оно работает асинхронно. Когда с сервера приходит новый ответ, то вызывается метод onMessage(String id, DATA_parser data), который передает идентификатор запроса (id), на который пришел ответ и сами данные (data). Данные предоставляются в виде объекта DATA_request, в котором имеются следующие объекты:
status — String — статус результата запроса данных, если «ok», то запрос отработан удачно, иначе «err» (в дальнейшем статусы возможно будут пополняться);
recordsCount — int— количество записей пришедших от сервера, являющиеся результатом запроса;
structure — String[] — текстовый массив, являющийся перечислением названий всех полей ответного запроса;
listData — ArrayList<String[]>— список массивов данных. Количество элементов в списке соответствует количеству записей с сервера. В каждом элементе находится текстовый массив, с количеством элементов равным количеству элементов в массиве structure.

Корректность обработки каждого запроса пока что ложится на плечи программиста, т.е. придется отслеживать каждый пришедший ответ с сервера и сравнивать его с идентификаторами в таблицах запросов, которые необходимо вести. Зато данное решение дает разработчику полную свободу и контроль в обработке всех результатов приходящих с сервера.

Всё готово! Теперь приступайте к тестированию, отправляйте любые SQL запросы на сервер (создание таблиц, вставка/модификация данных, удаление записей и т.д.) и получайте соответствующие результаты выполнения.

Репозиторий с сервером, клиентом, библиотекой и примером приложения — https://github.com/gc986/MyMobileSQLServer_Utesov
(В настоящее время в репозитории находится самая первая версия проекта подготовленная в формате ADT Eclipse. Следующим этапом станет перевод проекта под формат AndroidStudio)

Вопрос к хабраудитории: где можно применить данное решение?
Tags:
Hubs:
Total votes 16: ↑11 and ↓5+6
Comments13

Articles