Так получилось, что в рамках своей работы я связался с проектом по разработке приложения для общения Android и 1С. Быстрый поиск в интернете дал достаточно четкие инструкции и куски кода, которые очень быстро оформились в готовую программу, но запускаться она не хотела. Здесь я расскажу основные тонкости и способы их решения.
Первоисточники кода расписаны здесь и тут. Необходимо только подключить стороннюю библиотеку ksoap2-android, чтобы стали доступны классы SoapObject и HttpTransportSE. Старый проверенный способ скачать jar с официального репозитория и положить его в app/libs почему-то не увенчался успехом, и я стал смотреть, как подключить библиотеку используя современный Gradle. Почти на всех ресурсах было написано, что простое добавление
должно «подтягивать» нужные ресурсы. Но этого не произошло, т.к. сам ресурс не находится в стандартных репозиториях. Значит, надо указать, откуда его скачивать. Делается это добавлением в Gradle файл проекта следующих строк:
После этих простых действий просто синхронизируем проект, и Gradle закачает все, что нужно.
Вот код, который начинает работать после вышеописанных процедур:
Не секрет, что работа с любой сетевой активностью должна делаться из отдельной асинхронной задачи. doInBackground – это стандартный метод AsyncTask. Если еще не знакомы, то вот здесь про него написано просто и очень понятно.
Сама MainActivity выглядит следующим образом:
На этом приключения не заканчиваются. В моем случае запрос к серверу был закрыт Basic Auth, поэтому потребовалось куда-то вводить логин и пароль. И вот на этот вопрос однозначного ответа в интернете я не нашел. Во многих статьях был упомянут некий класс HttpTransportBasicAuthSE, в конструктор которого и передается логин с паролем. Но его было не найти в ksoap2-android, пришлось искать в интернете. Нашелся здесь. Привожу полный текст:
Полагаю, комментарии к коду излишни. Уточню только, что для применения HttpTransportBasicAuthSE достаточно просто изменить строку в DataLoader
на
и все начинает работать с авторизацией очень четко!
P.S.: не забывайте добавлять в Manifest разрешение на Internet
Первоисточники кода расписаны здесь и тут. Необходимо только подключить стороннюю библиотеку ksoap2-android, чтобы стали доступны классы SoapObject и HttpTransportSE. Старый проверенный способ скачать jar с официального репозитория и положить его в app/libs почему-то не увенчался успехом, и я стал смотреть, как подключить библиотеку используя современный Gradle. Почти на всех ресурсах было написано, что простое добавление
dependencies { compile 'com.google.code.ksoap2-android:ksoap2-android:3.6.1' }
должно «подтягивать» нужные ресурсы. Но этого не произошло, т.к. сам ресурс не находится в стандартных репозиториях. Значит, надо указать, откуда его скачивать. Делается это добавлением в Gradle файл проекта следующих строк:
buildTypes { repositories { maven { url 'https://oss.sonatype.org/content/repositories/ksoap2-android-releases' } } }
После этих простых действий просто синхронизируем проект, и Gradle закачает все, что нужно.
Вот код, который начинает работать после вышеописанных процедур:
public class DataLoader extends AsyncTask<Void, Void, String> { private static final String NAMESPACE = "namespace"; private static final String URL = "http://host/wsdlAcceptor?wsdl"; private static final String SOAP_ACTION = "http://host/wsdlAcceptor"; private static final String METHOD_NAME = "testOperation"; @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(Void... params) { try { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10); request.addProperty("IsFirstRequest", true); envelope.setOutputSoapObject(request); HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); androidHttpTransport.debug = true; try { androidHttpTransport.call(SOAP_ACTION, envelope); SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn; System.out.println("Response::"+resultsRequestSOAP.toString()); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } return ""; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); } }
Не секрет, что работа с любой сетевой активностью должна делаться из отдельной асинхронной задачи. doInBackground – это стандартный метод AsyncTask. Если еще не знакомы, то вот здесь про него написано просто и очень понятно.
Сама MainActivity выглядит следующим образом:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DataLoader dl = new DataLoader(); dl.execute(); } }
На этом приключения не заканчиваются. В моем случае запрос к серверу был закрыт Basic Auth, поэтому потребовалось куда-то вводить логин и пароль. И вот на этот вопрос однозначного ответа в интернете я не нашел. Во многих статьях был упомянут некий класс HttpTransportBasicAuthSE, в конструктор которого и передается логин с паролем. Но его было не найти в ksoap2-android, пришлось искать в интернете. Нашелся здесь. Привожу полный текст:
public class HttpTransportBasicAuthSE extends HttpTransportSE { private String username; private String password; /** * Constructor with username and password * * @param url * The url address of the webservice endpoint * @param username * Username for the Basic Authentication challenge RFC 2617 * @param password * Password for the Basic Authentication challenge RFC 2617 */ public HttpTransportBasicAuthSE(String url, String username, String password) { super(url); this.username = username; this.password = password; } public ServiceConnection getServiceConnection() throws IOException { ServiceConnectionSE midpConnection = new ServiceConnectionSE(url); addBasicAuthentication(midpConnection); return midpConnection; } protected void addBasicAuthentication(ServiceConnection midpConnection) throws IOException { if (username != null && password != null) { StringBuffer buf = new StringBuffer(username); buf.append(':').append(password); byte[] raw = buf.toString().getBytes(); buf.setLength(0); buf.append("Basic "); org.kobjects.base64.Base64.encode(raw, 0, raw.length, buf); midpConnection.setRequestProperty("Authorization", buf.toString()); } } }
Полагаю, комментарии к коду излишни. Уточню только, что для применения HttpTransportBasicAuthSE достаточно просто изменить строку в DataLoader
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
на
HttpTransportBasicAuthSE androidHttpTransport = new HttpTransportBasicAuthSE(URL, "basicLogin", "authPassword");
и все начинает работать с авторизацией очень четко!
P.S.: не забывайте добавлять в Manifest разрешение на Internet
<uses-permission android:name="android.permission.INTERNET" />