Пример применения библиотеки ASNE
В данной статье я покажу как можно легко добавить поддержку VK и Odnoklassniki в андроид приложении, используя соответсвующие модули ASNE. Это упрощенный пример, включающий добавления логина, шаринга ссылки и вывода списка друзей.
##Регистрация приложения в социальной сети Для добавления социальной сети в ваше приложение потребуется ключ для совершения запросов. Поэтому первым шагом необходимо зарегистрировать приложение - по ссылкам вы увидите краткое руководство по созданию приложения для
для продолжения вам необходимы ключи, которые используются в SDK социальных сетей
- VK App ID
- Ok App ID
- Ok публичный ключ
- Ok секретный ключ
##Интеграция ВК и Одноклассники в приложение
-
Создайте новый проект
-
Сохраните ключи в
values/strings.xmlstrings.xml(source)
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">ASNE-tutorial</string> <string name="vk_app_id">4542602</string> <string name="ok_app_id">1096125440</string> <string name="ok_public_key">CBANIGFCEBABABABA</string> <string name="ok_secret_key">FF5161844C04525B64FA41A7</string> </resources>
-
Добавим разрешения и активити для интегарции с Одноклассниками - откроем
AndroidManifest.xmlи добавим uses-permission - INTERNET, ACCESS_NETWORK_STATE и добавим ru.ok.android.sdk.OkAuthActivityAndroidManifest.xml(код)
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.github.gorbin.asnetutorial" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="ru.ok.android.sdk.OkAuthActivity" android:launchMode="singleTask" android:configChanges="orientation"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="ok1096125440" android:scheme="okauth" /> </intent-filter> </activity> </application> </manifest>
-
Добавим зависимости для модулей ASNE:
Например в Android Studio Откойте Project Structure => выберите модуль приложения и откройте Dependencies => Add new library dependency
Затем по запросу asne вы увидите все модули доступные в библиотеке и добавьте в зависимость asne-vk, asne-odnoklassniki
либо вручную добавьте зависимоси в build.gradle
build.gradle(код)
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion '20.0.0'
defaultConfig {
applicationId "com.github.gorbin.asnetutorial"
minSdkVersion 10
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:20.0.0'
compile 'com.github.asne:asne-vk:0.3.1'
compile 'com.github.asne:asne-odnoklassniki:0.3.1'
}
- Теперь немного украсим наше приложение
В главном фрагменте расположим 2 кнопки отвечающие за логин в социальные сети
main_fragment.xml(код)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFCCCCCC"> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Login via VK" android:id="@+id/vk" android:layout_gravity="center_horizontal" android:background="@color/vk" android:layout_margin="8dp" android:textColor="#ffffffff" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Login via Odnoklassniki" android:id="@+id/ok" android:layout_gravity="center_horizontal" android:background="@color/ok" android:layout_margin="8dp" android:textColor="#ffffffff"/> </LinearLayout>
Зададим внешний вид профиля пользователя profile_fragment.xml(full source) ```xml
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/grey_light">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_margin="8dp"
android:id="@+id/frame"
android:background="@color/dark">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_margin="3dp"
android:id="@+id/card"
android:background="#FFFFFF">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/imageView"
android:layout_margin="8dp"
android:padding="2dp"
android:background="@color/grey_light"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:src="proxy.php?url=https%3A%2F%2Fgithub.com%2F%40drawable%2Fuser"
android:adjustViewBounds="true"
android:cropToPadding="true"
android:scaleType="centerCrop"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="NoName"
android:maxLines="3"
android:singleLine="false"
android:id="@+id/name"
android:padding="8dp"
android:layout_alignTop="@+id/imageView"
android:layout_toRightOf="@+id/imageView"
android:layout_toEndOf="@+id/imageView"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="null"
android:maxLines="3"
android:singleLine="false"
android:id="@+id/id"
android:padding="8dp"
android:layout_below="@+id/name"
android:layout_alignLeft="@+id/name"
android:layout_alignStart="@+id/name" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="@+id/info"
android:padding="8dp"
android:layout_marginBottom="4dp"
android:layout_below="@+id/imageView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/buttonLayout"
android:layout_below="@+id/card"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:gravity="center"
android:background="@color/grey_light">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Friends"
android:id="@+id/friends"
android:padding="8dp"
android:background="@color/dark"
android:layout_marginRight="1dp"
android:layout_weight="1"
android:textColor="#ffffffff"/>
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Share"
android:id="@+id/share"
android:padding="8dp"
android:background="@color/dark"
android:layout_weight="1"
android:textColor="#ffffffff"/>
</LinearLayout>
</RelativeLayout>
</ScrollView>
```
и сохраним цвета социальных сетей
color.xml(full source) ```xml #FFCCCCCC #4b4b4b
<color name="vk">#36638e</color>
<color name="ok">#cf6700</color>
</resources>
```
-
Теперь в
MainActivity.javaнеобходимо вonActivityResultловить ответ после запроса логинаMainActivity.java(full source)
public static final String SOCIAL_NETWORK_TAG = "SocialIntegrationMain.SOCIAL_NETWORK_TAG";
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Fragment fragment = getSupportFragmentManager().findFragmentByTag(SOCIAL_NETWORK_TAG);
if (fragment != null) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}При обработке запроса логина социальная сеть отправляет onActivityResult проверяем его, отправляем в SocialNetworkManager, который передаст его в соответствующую SocialNetwork
-
Теперь интегрируем социальную сеть в
MainFragment.java- это просто:- Достанем ключи социальных сетей из
values.xml
String VK_KEY = getActivity().getString(R.string.vk_app_id); String OK_APP_ID = getActivity().getString(R.string.ok_app_id); String OK_PUBLIC_KEY = getActivity().getString(R.string.ok_public_key); String OK_SECRET_KEY = getActivity().getString(R.string.ok_secret_key);
- Получим
SocialNetworkManager
mSocialNetworkManager = (SocialNetworkManager) getFragmentManager().findFragmentByTag(MAinActivity.SOCIAL_NETWORK_TAG);
- Создадим
SocialNetworksс соответствующими разрешениями
String[] vkScope = new String[] { VKScope.FRIENDS, VKScope.WALL, VKScope.PHOTOS, VKScope.NOHTTPS, VKScope.STATUS, }; VkSocialNetwork vkNetwork = new VkSocialNetwork(this, VK_KEY, vkScope); String[] okScope = new String[] { OkScope.VALUABLE_ACCESS }; OkSocialNetwork okNetwork = new OkSocialNetwork(this, OK_APP_ID, OK_PUBLIC_KEY, OK_SECRET_KEY, okScope);
-
Проверим существует ли
SocialNetworkManager -
Если не существует зададим его и добавим в него
SocialNetworksmSocialNetworkManager = new SocialNetworkManager(); mSocialNetworkManager.addSocialNetwork(vkNetwork); mSocialNetworkManager.addSocialNetwork(okNetwork); //Initiate every network from mSocialNetworkManager getFragmentManager().beginTransaction().add(mSocialNetworkManager, MAinActivity.SOCIAL_NETWORK_TAG).commit(); mSocialNetworkManager.setOnInitializationCompleteListener(this);
не забудьте добавить
SocialNetworkManager.OnInitializationCompleteListener-
Если
SocialNetworkManagerсуществует - задали в activity или другом фрагменте - выберем все инициализированные социальные сети и установим имOnLoginCompleteListenerif(!mSocialNetworkManager.getInitializedSocialNetworks().isEmpty()) { List<SocialNetwork> socialNetworks = mSocialNetworkManager.getInitializedSocialNetworks(); for (SocialNetwork socialNetwork : socialNetworks) { socialNetwork.setOnLoginCompleteListener(this); }
-
Теперь необходимо обработать callback инициации
SocialNetworks@Override public void onSocialNetworkManagerInitialized() { for (SocialNetwork socialNetwork : mSocialNetworkManager.getInitializedSocialNetworks()) { socialNetwork.setOnLoginCompleteListener(this); initSocialNetwork(socialNetwork); } }
не забудьте добавить
OnLoginCompleteListener
- Достанем ключи социальных сетей из
Весь исходный код onCreateView и onSocialNetworkManagerInitialized из MainFragment инициацией социальных сетей и установкой listenerов
**MainFragment.java**(full [source](https://github.com/gorbin/ASNETutorial/blob/ru/app/src/main/java/com/github/gorbin/asnetutorial/MainFragment.java))
```java
public static SocialNetworkManager mSocialNetworkManager;
/**
* SocialNetwork Ids in ASNE:
* 1 - Twitter
* 2 - LinkedIn
* 3 - Google Plus
* 4 - Facebook
* 5 - Vkontakte
* 6 - Odnoklassniki
* 7 - Instagram
*/
public static final int VK = 5;
public static final int OK = 6;
private Button vk;
private Button ok;
public MainFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main_fragment, container, false);
((MainActivity)getActivity()).getSupportActionBar().setTitle(R.string.app_name);
// init buttons and set Listener
vk = (Button) rootView.findViewById(R.id.vk);
vk.setOnClickListener(loginClick);
ok = (Button) rootView.findViewById(R.id.ok);
ok.setOnClickListener(loginClick);
//Get Keys for initiate SocialNetworks
String VK_KEY = getActivity().getString(R.string.vk_app_id);
String OK_APP_ID = getActivity().getString(R.string.ok_app_id);
String OK_PUBLIC_KEY = getActivity().getString(R.string.ok_public_key);
String OK_SECRET_KEY = getActivity().getString(R.string.ok_secret_key);
//Chose permissions
String[] okScope = new String[] {
OkScope.VALUABLE_ACCESS
};
String[] vkScope = new String[] {
VKScope.FRIENDS,
VKScope.WALL,
VKScope.PHOTOS,
VKScope.NOHTTPS,
VKScope.STATUS,
};
//Use manager to manage SocialNetworks
mSocialNetworkManager = (SocialNetworkManager) getFragmentManager().findFragmentByTag(MainActivity.SOCIAL_NETWORK_TAG);
//Check if manager exist
if (mSocialNetworkManager == null) {
mSocialNetworkManager = new SocialNetworkManager();
//Init and add to manager VkSocialNetwork
VkSocialNetwork vkNetwork = new VkSocialNetwork(this, VK_KEY, vkScope);
mSocialNetworkManager.addSocialNetwork(vkNetwork);
//Init and add to manager OkSocialNetwork
OkSocialNetwork okNetwork = new OkSocialNetwork(this, OK_APP_ID, OK_PUBLIC_KEY, OK_SECRET_KEY, okScope);
mSocialNetworkManager.addSocialNetwork(okNetwork);
//Initiate every network from mSocialNetworkManager
getFragmentManager().beginTransaction().add(mSocialNetworkManager, MainActivity.SOCIAL_NETWORK_TAG).commit();
mSocialNetworkManager.setOnInitializationCompleteListener(this);
} else {
//if manager exist - get and setup login only for initialized SocialNetworks
if(!mSocialNetworkManager.getInitializedSocialNetworks().isEmpty()) {
List<SocialNetwork> socialNetworks = mSocialNetworkManager.getInitializedSocialNetworks();
for (SocialNetwork socialNetwork : socialNetworks) {
socialNetwork.setOnLoginCompleteListener(this);
initSocialNetwork(socialNetwork);
}
}
}
return rootView;
}
private void initSocialNetwork(SocialNetwork socialNetwork){
if(socialNetwork.isConnected()){
switch (socialNetwork.getID()){
case VK:
vk.setText("Show VK profile");
break;
case OK:
ok.setText("Show Odnoklassniki profile");
break;
}
}
}
@Override
public void onSocialNetworkManagerInitialized() {
//when init SocialNetworks - get and setup login only for initialized SocialNetworks
for (SocialNetwork socialNetwork : mSocialNetworkManager.getInitializedSocialNetworks()) {
socialNetwork.setOnLoginCompleteListener(this);
initSocialNetwork(socialNetwork);
}
}
```
##Запросы к Социальным сетям
-
Запросим логин в каждой социальной сети
SocialNetwork socialNetwork = mSocialNetworkManager.getSocialNetwork(networkId); socialNetwork.requestLogin();
Весь исходный код OnClickListener loginClick с проверкой состояния подключения к социальной сети, если социальная сеть подключена - откроем ProfileFragment.java
**MainFragment.java**([код](https://github.com/gorbin/ASNETutorial/blob/ru/app/src/main/java/com/github/gorbin/asnetutorial/MainFragment.java))
```java
private View.OnClickListener loginClick = new View.OnClickListener() {
@Override
public void onClick(View view) {
int networkId = 0;
switch (view.getId()){
case R.id.vk:
networkId = VK;
break;
case R.id.ok:
networkId = OK;
break;
}
SocialNetwork socialNetwork = mSocialNetworkManager.getSocialNetwork(networkId);
if(!socialNetwork.isConnected()) {
if(networkId != 0) {
socialNetwork.requestLogin();
MainActivity.showProgress("Loading social person");
} else {
Toast.makeText(getActivity(), "Wrong networkId", Toast.LENGTH_LONG).show();
}
} else {
startProfile(socialNetwork.getID());
}
}
};
```
- После заполнения логина или обработки логина приложением социальной сети получим
onLoginSuccess(int networkId)илиonError(int networkId, String requestID, String errorMessage, Object data)- выведем соответствующее сообщение
MainFragment.java(код)
```java
@Override
public void onLoginSuccess(int networkId) {
MainActivity.hideProgress();
Toast.makeText(getActivity(), "Login Success", Toast.LENGTH_LONG).show();
}
@Override
public void onError(int networkId, String requestID, String errorMessage, Object data) {
MainActivity.hideProgress();
Toast.makeText(getActivity(), "ERROR: " + errorMessage, Toast.LENGTH_LONG).show();
}
```
- Откроем
ProfileFragment.javaс помощью метода:
MainFragment.java(код)
```java
private void startProfile(int networkId){
ProfileFragment profile = ProfileFragment.newInstannce(networkId);
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack("profile")
.replace(R.id.container, profile)
.commit();
}
```
- В
ProfileFragment.javaполучим идетификатор социальной сети изMainFragment.java
ProfileFragment.java(код) ```java public static ProfileFragment newInstannce(int id) { ProfileFragment fragment = new ProfileFragment(); Bundle args = new Bundle(); args.putInt(NETWORK_ID, id); fragment.setArguments(args); return fragment; }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
networkId = getArguments().containsKey(NETWORK_ID) ? getArguments().getInt(NETWORK_ID) : 0;
}
```
-
Теперь с помощью
networkIdмы выберем социальную сеть и запросим данные профиля текущего пользователя следующим образом:socialNetwork = MainFragment.mSocialNetworkManager.getSocialNetwork(networkId); socialNetwork.setOnRequestCurrentPersonCompleteListener(this); socialNetwork.requestCurrentPerson();
не забудьте добавить OnRequestSocialPersonCompleteListener
6. После обработки запроса мы можем использовать полученный объект SocialPerson для заполнения профиля пользователя в приложении, либо вывести ошибку при неудаче
ProfileFragment.java(full source) ```java @Override public void onRequestSocialPersonSuccess(int i, SocialPerson socialPerson) { MainActivity.hideProgress(); name.setText(socialPerson.name); id.setText(socialPerson.id); String socialPersonString = socialPerson.toString(); String infoString = socialPersonString.substring(socialPersonString.indexOf("{")+1, socialPersonString.lastIndexOf("}")); info.setText(infoString.replace(", ", "\n")); Picasso.with(getActivity()) .load(socialPerson.avatarURL) .into(photo); }
@Override
public void onError(int networkId, String requestID, String errorMessage, Object data) {
MainActivity.hideProgress();
Toast.makeText(getActivity(), "ERROR: " + errorMessage, Toast.LENGTH_LONG).show();
}
```
7. Для выхода из социальной сети необходимо использовать метод logout()
socialNetwork.logout();
getActivity().getSupportFragmentManager().popBackStack();- И, честно говоря, это все - добавили ВК и Одноклассники в приложение. Аналогично вы можете добавить и другие социальные сети Facebook, Twitter, Linkedin, Instagram или Google Plus лишь добавив соответствующую зависимость и добавив их в
SocialNetworkManagerкак в шаге 8:
FacebookSocialNetwork fbNetwork = new FacebookSocialNetwork(this, fbScope);
mSocialNetworkManager.addSocialNetwork(fbNetwork);
TwitterSocialNetwork twNetwork = new TwitterSocialNetwork(this, TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
mSocialNetworkManager.addSocialNetwork(twNetwork);
LinkedInSocialNetwork liNetwork = new LinkedInSocialNetwork(this, LINKEDIN_CONSUMER_KEY, LINKEDIN_CONSUMER_SECRET, linkedInScope);
mSocialNetworkManager.addSocialNetwork(liNetwork);
GooglePlusSocialNetwork gpNetwork = new GooglePlusSocialNetwork(this);
mSocialNetworkManager.addSocialNetwork(gpNetwork);
InstagramSocialNetwork instagramNetwork = new InstagramSocialNetwork(this, INSTAGRAM_CLIENT_KEY, INSTAGRAM_CLIENT_SECRET, instagramScope);
mSocialNetworkManager.addSocialNetwork(instagramNetwork);И конечно же вы можете использовать выше описанные методы для раобты с ними
- Но давайте разберем еще несколько запросов Share link и Get user friendslist
Давайте поделимся ссылкой с помощью социальной сети:
-
Настройим кнопку
share = (Button) rootView.findViewById(R.id.share); share.setOnClickListener(shareClick);
-
Для отправки ссылки на стену пользователя нам необходимо ее передать в Bundle
Bundle postParams = new Bundle(); postParams.putString(SocialNetwork.BUNDLE_LINK, link); socialNetwork.requestPostLink(postParams, message, postingComplete);
-
И конечно же обработать ответы
```java private OnPostingCompleteListener postingComplete = new OnPostingCompleteListener() { @Override public void onPostSuccessfully(int socialNetworkID) { Toast.makeText(getActivity(), "Sent", Toast.LENGTH_LONG).show(); } @Override public void onError(int socialNetworkID, String requestID, String errorMessage, Object data) { Toast.makeText(getActivity(), "Error while sending: " + errorMessage, Toast.LENGTH_LONG).show(); } }; ``` -
Итак в
OnClickListener shareClickпокажем пользователю простой диалог в котором спросим, хочет ли он расшарить ссылку, и если да, отправим ее**ProfileFragment.java**(full [source](https://github.com/gorbin/ASNETutorial/blob/ru/app/src/main/java/com/github/gorbin/asnetutorial/ProfileFragment.java))private View.OnClickListener shareClick = new View.OnClickListener() { @Override public void onClick(View view) { AlertDialog.Builder ad = alertDialogInit("Would you like to post Link:", link); ad.setPositiveButton("Post link", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Bundle postParams = new Bundle(); postParams.putString(SocialNetwork.BUNDLE_LINK, link); socialNetwork.requestPostLink(postParams, message, postingComplete); } }); ad.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int i) { dialog.cancel(); } }); ad.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) { dialog.cancel(); } }); ad.create().show(); } };
Теперь выведем список друзей пользователя:
-
Получим
SocialNetworkиз идентификатора социальной сети запросим список друзей```java SocialNetwork socialNetwork = MainFragment.mSocialNetworkManager.getSocialNetwork(networkId); socialNetwork.setOnRequestGetFriendsCompleteListener(this); socialNetwork.requestGetFriends(); ```не забудьте добавить
OnRequestGetFriendsCompleteListener -
Обработаем ответ
```java @Override public void OnGetFriendsIdComplete(int id, String[] friendsID) { ((MainActivity)getActivity()).getSupportActionBar().setTitle(friendsID.length + " Friends"); } @Override public void OnGetFriendsComplete(int networkID, ArrayList<SocialPerson> socialPersons) { MainActivity.hideProgress(); FriendsListAdapter adapter = new FriendsListAdapter(getActivity(), socialPersons, networkID); listView.setAdapter(adapter); } @Override public void onError(int networkId, String requestID, String errorMessage, Object data) { MainActivity.hideProgress(); Toast.makeText(getActivity(), "ERROR: " + errorMessage, Toast.LENGTH_LONG).show(); } ```
Подробнее вы можете изучить в FriendsFragment.java
##Итог Используя модули библиотеки ASNE вы легко и быстро интегрируете любую популярную социальную сеть в приложение. Конечно же в библиотеке содержится больше методов которые возможно пригодятся в вашем приложении. А в случае необходимости использовать методы SDK вы можете получить токен или объект SDK и написать свой метод
Если данное приложение вам показалось простым, вы можете посмотерть реализацию всех методов - тут
Статья по подключению Facebook, Twitter and LinkedIn на codeproject.com
В данный момент библиотека дорабатывается, и я буду рад вашим советам или помощи в разработке.
В ближайшее время напишу статью по подключению социальных сетей как модулей и подключу азиатскую социальную сеть. А так же все не доходят руки до javdoc и тестов





