Имя: Пароль:
1C
1С v8
Связка: Android - web-сервисы - 1Cv8
,
0 Cube
 
02.02.12
07:38
Собсна задача: Есть база на 1Cv82 (самописка, но это не важно). Нужно к базе прикрутить web-сервисы и написать приложение для android со следующим функционалом:

1). Загрузка справочников из 1Cv8.
2). Создание и хранение документов на смартфоне.
3). Выгрузка документов в 1Cv82 через web-сервисы. Удаление выгруженных документов со смартфона.

Предыстория: Пол года назад я поднимал тему Помогите с установкой Java , но дальше HelloWorld я не ушел, т.к. на тот момент у меня ещё не было смарта с андрюшей и я решил отложить этот вопрос. Теперь у меня есть смарт с андрюшей 2.3.7 и вопрос опять актуален.
1 Cube
 
02.02.12
07:38
На данный момент в базе 1Cv8 есть web-сервис "ПроверкаСвязи" с операцией "ПроверитьСвязь", возвращающая строку "Сервер доступен".
База 1Cv8 опубликована на web-сервере. Имя файла публикаци: "TestConnection.1cws".

Есть работающий под Windows java-код:

function ПриветствоватьВебСервис(){
   определитьБраузер()
   var xmlhttp = getXmlHttp()

   // создаём соединение типа POST, второй параметр - адрес, параметр true значит асинхронное, то есть браузер не бедет ждать ответа сервера, а продолжит работу
   xmlhttp.open('POST', '/MyBase/ws/TestConnection.1cws', true)

   // Скажем что делать когда придёт ответ - вызвать функцию ПриОтветеВебСервиса()
   xmlhttp.onreadystatechange = function() {ПриОтветеВебСервиса(xmlhttp)}

   // Отправим своё приветствие веб сервису в виде XML.
   xmlhttp.send('<?xml version="1.0" encoding="UTF-8"?>' +
       '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header/>' +
       '<soap:Body> <m:ПроверитьСвязь xmlns:m="http://www.sample-package.org"/> </soap:Body>' +
       '</soap:Envelope>')
   
   // Напишем на кнопке чего мы ждём, а то пользователи они такие. Понатыкают на кнопку а потом удивляются.
   document.getElementById("MyButton").value = "Ждём ответа..."
   document.getElementById("MyButton").disabled = true
}

Необходимо сделать то же самое, но на Android.
У меня уже есть форма настроек, где указывается адрес сервера и есть кнопочка "Проверить связь с сервером". Не знаю, с чего начать писать код в функции ""...
Адрес сервера, как мне кажется, можно получить строкой: "http://" + EditTextServerAddress.getText().toString() + "/MyBase/ws/TestConnection.1cws".
2 Cube
 
02.02.12
07:39
+(1) *Не знаю, с чего начать писать код в функции "onClick"...
3 Cube
 
02.02.12
07:43
Точнее так, как на андрюше написать post-запрос и передать в нем xml-файл?
4 Cube
 
02.02.12
10:11
Я пытаюсь так:

public void onClick(View v)
   {
       String citateRequestString = "http://" + EditTextServerAddress.getText().toString() + "/MyBase/ws/TestConnection.1cws";
       String resultString = new String("");
       try {

           URLConnection connection = null;
           URL url = new URL(citateRequestString);
       
         HttpURLConnection httpConnection = (HttpURLConnection)connection;
         httpConnection.setRequestMethod("POST");
         
         //httpConnection.setRequestProperty("User-Agent", "MyAndroid/1.6");
         //httpConnection.setRequestProperty("Content-Language", "ru-RU");
         //httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

         httpConnection.setDoOutput(true);
         httpConnection.setDoInput(true);
         
         httpConnection.connect();
         
         // здесь можем писать в поток данные запроса
         OutputStream os = httpConnection.getOutputStream();
         String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                        "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> <soap:Header/>" +
                        "<soap:Body> <m:ПроверитьСвязь xmlns:m=\"http://www.sample-package.org\"/> </soap:Body>" +
                        "</soap:Envelope>";
         os.write( str.getBytes());
         
         os.flush();
         os.close();

         
          int responseCode = httpConnection.getResponseCode();
          if (responseCode == HttpURLConnection.HTTP_OK) {
                 InputStream in = httpConnection.getInputStream();
                 
                 InputStreamReader isr = new InputStreamReader(in, "UTF-8");

                 StringBuffer data = new StringBuffer();
                 int c;
                 while ((c = isr.read()) != -1){
                     data.append((char) c);
                 }


                 resultString = new String (data.toString());

           }
           else
           {
               resultString = "Server does not respond";
           }
        }
        catch (MalformedURLException e) {
                   resultString = "MalformedURLException:" + e.getMessage();
          }
        catch (IOException e) {
                  resultString = "IOException:" + e.getMessage();
         }
       
       
       TextViewServerAnswerText.setText(resultString);
   }

Источник: http://blog.plaincodesource.ws/2010/10/android-post.html

Не работает. Ошибка на строке "URL url = new URL(citateRequestString);". Текст ошибки: "The value of the local variable url is not used". Что бы это значило...
5 Scooter
 
02.02.12
10:21
(0)веб-клиента использовать?
6 Cube
 
02.02.12
10:31
(5) Нет, т.к. у него есть минусы:
- Без интернета не фурычит.
- Нужно время на загрузку, время на переход по страницам, время, время, время...

Нужно:
- Работа оффлайн.
- Высокое быстродействие.
7 Астероид
 
02.02.12
10:39
(6) дык, переходи на Агентоид, там все реализовано!
8 Cube
 
02.02.12
10:47
(7) Я ж не мобильную торговлю пишу)) И что, в агендойде реализован учет доходов и расходов и именно в той аналитике, в которой мне надо? Очень сомневаюсь... :)
9 Cube
 
02.02.12
10:49
(7) Кстати, есть чем помочь? Или ты только пиаром занимаешься, а разрабатывают агентойд другие?)
10 Cube
 
02.02.12
12:33
Ап
11 pumbaEO
 
02.02.12
12:41
http://code.google.com/p/droidpres/ Смотри сюда как пример.
Для androida не видел нормальной библиотеки для работы с SOAP. Тут или вариант самому писать xml, что для soap извращение или думать что то другое.
12 Cube
 
02.02.12
13:05
(11) О нет, дернуть нужный кусок из чужого кода я сейчас вряд ли смогу =))
Мне бы простой примерчик. Ну ведь javascript для браузера такой простой, неужели на андройде нельзя сделать нечто подобное?
13 Cube
 
03.02.12
07:32
Итак, я, вроде как, написал код, посылающий xml-запрос web-сервису. Теперь нужно обработать ответ.

В java-скрипте для Windows код разбора ответа выглядит так:

function ПриОтветеВебСервиса(xmlhttp){
   if (xmlhttp.readyState == 4) {// когда ответ готов.
       if(xmlhttp.status != 200) {// Если всё плохо - скажем об этом
           alert("Запрос завершился неудачно. Ответ сервера: " + xmlhttp.responseText)
       }
       else{/*собственно за следующие три строки мы и боролись. Получили ответ сервера и выводим его, ответ, на страницу.
           Работа с javaScript описана в соответствующих учебниках. Напрмер в http://javaScript.ru
           Нам интересно только то что ответ сервера находится в свойстве responseXML объекта xmlhttp
           responseXML - объект типа DOM*/
           var ДомОтвет = xmlhttp.responseXML.getElementsByTagName(ИЕ("return"))[0] // "m:return" - для IE, "return" - для FF
           var ДанныеОтвета = ДомОтвет.childNodes[0].data
           document.getElementById("ОтветСервера").appendChild(document.createTextNode(ДанныеОтвета))
       }

       // Когда сервер ответил можно включить кнопочку.
       document.getElementById("MyButton").value = "Проверка связи с сервером"
       document.getElementById("MyButton").disabled = false
   }
}

Сейчас процедура "onClick" выглядит так:

public void onClick(View v)
   {
       String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> <soap:Header/>" +
                    "<soap:Body> <m:ПроверитьСвязь xmlns:m=\"http://www.sample-package.org\"/> </soap:Body>" +
                    "</soap:Envelope>";
       HttpClient httpclient = new DefaultHttpClient();
       HttpPost httppost = new HttpPost("http://" + EditTextServerAddress.getText().toString() + "/MyBase/ws/TestConnection.1cws");
       try {
           httppost.setEntity(new StringEntity(str));
           HttpResponse response = httpclient.execute(httppost);
           TextViewServerAnswerText.setText(response.toString());  
       } catch (ClientProtocolException e) {
           // TODO Auto-generated catch block
       } catch (IOException e) {
           // TODO Auto-generated catch block
       }
   }

И в текстовое поле "TextViewServerAnswerText" на форме настроек попадает текст "org.apache.http.message.BasicHttpResponse@40573ad8". Из чего я сделал вывод, что код рабочий и ответ пришел, осталось его обработать...
Кто-нибудь может помочь? Я не совсем понимаю, как мне response преобразовать в NodeList...
14 Cube
 
07.02.12
07:34
Задача решена. Может кому пригодится реализация:

На стороне 1С нужно быть осторожным при создании web-сервисов и XDTO-пакетов. Если точнее, нужно набирать латиницей: наименование операций web-сервиса, типы объектов и свойства объектов пакета XDTO. Иначе будете получать ошибку на строке "Document Document = DocumentBuilder.parse(HttpResponse.getEntity().getContent());"

А вот и код, ради которого создавалась эта тема:

   final int PROGRESS_DLG_ID = 0;

   @Override
   protected Dialog onCreateDialog(int dialogId){
       ProgressDialog progress = null;
       switch (dialogId) {
       case PROGRESS_DLG_ID:
           progress = new ProgressDialog(this);
           progress.setMessage("Обмен с сервером...");
           break;
       }
       return progress;
   }
   
   public void onClick(View v) {
       if (v == ButtonTestConnection) {
           new TestConnection().execute("http://" + EditTextServerAddress.getText().toString() + "/MyBase/ws/TestConnection.1cws");
       }
       if (v == ButtonExchange) {
           new Exchange().execute("http://" + EditTextServerAddress.getText().toString() + "/MyBase/ws/Exchange.1cws");
       }
   }
   
   class TestConnection extends AsyncTask<String, Void, String> {
       
       @Override
       protected String doInBackground(String... params) {
           publishProgress(new Void[]{});
           String Response = "";
           String XMLRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                   "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> <soap:Header/>" +
                   "<soap:Body> <m:TestConnection xmlns:m=\"http://www.sample-package.org\"/> </soap:Body>" +
                   "</soap:Envelope>";
           HttpClient HttpClient = new DefaultHttpClient();
           HttpPost HttpPost = new HttpPost(params[0]);
           try {
               HttpPost.setEntity(new StringEntity(XMLRequest));
               HttpResponse HttpResponse = HttpClient.execute(HttpPost);
               try {
                   DocumentBuilderFactory CurrentDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
                   DocumentBuilder DocumentBuilder = CurrentDocumentBuilderFactory.newDocumentBuilder();
                   Document Document = DocumentBuilder.parse(HttpResponse.getEntity().getContent());
                   NodeList NodeList = Document.getElementsByTagName("m:return");
                   int NodeListLength = NodeList.getLength();
                   for (int i = 0; i < NodeListLength; i++) {
                       Node NodeListItem = NodeList.item(i);
                       Response = NodeListItem.getFirstChild().getNodeValue();
                   }
                   NodeList NodeListErrors = Document.getElementsByTagName("soap:Fault");
                   int NodeListErrorsLength = NodeListErrors.getLength();
                   for (int i = 0; i < NodeListErrorsLength; i++) {
                       Node NodeListErrorsItem = NodeListErrors.item(i);
                       NodeList NodeListErrorDetails = NodeListErrorsItem.getChildNodes();
                       int NodeListErrorDetailsLength = NodeListErrorDetails.getLength();
                       for (int m = 0; m < NodeListErrorDetailsLength; m++) {
                           Node NodeListErrorDetailsItem = NodeListErrorDetails.item(m);
                           if (NodeListErrorDetailsItem.hasChildNodes()) {
                               Response = Response + "\nОшибка " + (i+1) + " (" + NodeListErrorDetailsItem.getNodeName() + "): " + NodeListErrorDetailsItem.getFirstChild().getNodeValue();
                           }
                       }
                   }
               } catch (Exception ioe) {
                   Response = "Ошибка разбора ответа от сервера";
               }
           } catch (ClientProtocolException e) {
               Response = "Ошибка 2";
           } catch (IOException e) {
               Response = "Ошибка 3";
           }
           return Response;
       }
       
       @Override
       protected void onProgressUpdate(Void... values) {
           super.onProgressUpdate(values);
           showDialog(PROGRESS_DLG_ID);
       }
       
       @Override
       protected void onPostExecute(String result) {
           super.onPostExecute(result);
           dismissDialog(PROGRESS_DLG_ID);
           Toast.makeText(getBaseContext(), result, Toast.LENGTH_LONG).show();
       }
   }
15 Cube
 
07.02.12
07:36
А блин, забыл удалить кусок кода...
Кто будет копировать, удалите этот кусок:

       if (v == ButtonExchange) {
           new Exchange().execute("http://" + EditTextServerAddress.getText().toString() + "/MyBase/ws/Exchange.1cws");

       }

Он тут лишний.
16 Cube
 
07.02.12
07:38
Более подробно можно почитать тут: http://androidforums.ru/Svyazka-android---web-servisy---1cv8-t11842.html