میخوای وارد بازار کار بشی و محصولات خودت رو بفرشی همین الان ثبت نام کن
0

تبادل داده و ارتباط با سرویس ها در اندروید

راه های مختلفی برای تبادل داده و ارتباط و تعامل بین activity و سرویس ها در اندروید وجود دارد. مطالب زیر روش های ممکن برای نیل به این هدف را نام برده و روش پیشنهادی خود را در اختیار شما قرار می دهد.

 

استفاده از داده های کپسوله شده در intent

در یک سناریوی ساده، نیازی به هیچ تعامل مستقیم (بین سرویس و )activityوجود ندارد. سرویس داده های کپسوله شده در intent را از کامپوننت آغاز کننده (فراخواننده ی سرویس) دریافت نموده و عملیات لازم را به انجام می رساند. لازم به ذکر است که برای این منظور notification ضروری نیست. در واقع در شرایطی که سرویس محتوای یک content provider را با داده های جدید بروز آوری می کند، خود کامپوننت نرم افزاری مزبور activity را از این رخداد با خبر کرده و هیچ اقدام یا مرحله ی دیگری در سرویس لازم نیست. این روش هم برای سرویس های محلی و هم برای سرویس هایی که در فرایند مختص به خود اجرا می شوند، قابل پیاده سازی و استفاده خواهد بود.

 


استفاده از receiver

می توان برای تعامل و ارتباط بین activity و سرویس ها از broadcast ها و receiver هایی که به این broadcast ها گوش می دهند، بهره گرفت. به عنوان مثال، activity شما می تواند یک broadcast receiver برای گوش دادن به eventای معین ثبت کند و سرویس مورد نظر اتفاق افتادن eventهای مربوطه را به بیرون (کاپوننت های دیگر) اعلان نماید. این روش بسیار معمول بوده و اغلب زمانی استفاده می شود که سرویس می بایست پس از به انجام رساندن پردازش به activity این اتفاق را اعلان کند.

این جریان ارتباطی در تصویر زیر به تصویر کشیده شده است.

receiver
تبادل داده و ارتباط با سرویس ها در اندروید

 

روش نام برده برای سرویس های محلی و سرویس هایی که در فرایند میزبان و مختص خود اجرا می شوند، قابل استفاده می باشد.

 


اتصال activity به سرویس محلی

چنانچه activity و service هر دو در فرایندی یکسان اجرا شوند، در این شرایط activity قادر خواهد بود به سرویس مستقیما به صورت دو طرفه وصل شود. روش حاضر از میان گزینه هایی که تاکنون عنوان شده، بهینه ترین بوده و برای زمانی که activity نیاز دارد با سرویس با سرعت بالا تبادل داده داشته باشد بسیار مناسب می باشد.

ناگفته نماند که این روش تنها برای سرویس های محلی (سرویس هایی که) قابل پیاده سازی و استفاده می باشد.

 


Handler و ResultReceiver یا Messenger 

چنانچه سرویس با activity تعامل دو طرفه داشته باشد (اطلاعاتی را به activity برگرداند)، در آن صورت می تواند از طریق داده های کپسوله شده در intent که از activity دریافت می کند، آبجکتی از جنس Messenger دریافت نماید. در صورتی که Messenger به Handler در activity متصل باشد، آنگاه service قادر خواهد بود آبجکت هایی از جنس Message را به activity ارسال نماید.

Messenger در واقع اینترفیس parcelable را پیاده سازی می کند، بدین معنی که می توان آن را به فرایند دیگر ارسال کرده و با استفاده از این آبجکت Message هایی را به Handler در activity ارسال نمود.

Messenger همچنین متدی به نام () getBinder را ارائه می دهد. این متد قابلیت ارسال آبجکتی از جنس Messenger به activity را فراهم می نماید. activity نیز متعاقبا قادر خواهد بود Message های (نمونه هایی از کلاس Message که حاوی توصیف و آبجکت های داده ای دلخواه می باشد) متعددی را به سرویس مورد نظر ارسال کند. این روش برای سرویس های محلی که در فرایند خود اجرا می شوند، قابل استفاده می باشد.

 


اتصال به سرویس در فرایند دیگر با استفاده از AIDL

به منظور تبادل داده و اتصال (bind) به سرویسی که در فرایند دیگری در حال اجرا است، برنامه نویس بایستی از IPC ( ارتباط میان پردازشی ) کمک بگیرد. برای نیل به این هدف، ابتدا لازم است یک فایل AIDL ایجاد کند که تقریبا مشابه interface های جاوا می باشد با این تفاوت که پسوند آن aidl بوده و تنها اجازه ی ارث بری و بسط دیگر فایل های AIDL را دارد.

توصیه می شود از این روش زمانی استفاده نمایید که لازم باشد به سرویسی که در فرایند دیگری در حال اجرا است متصل شوید. برای مثال زمانی که اپلیکیشن های دیگر درخواست استفاده از سرویس مورد نظر را داشته باشند باید از این رویکرد استفاده کرد.

 


تمرین: استفاده از Service ها و تبادل داده با سرویس

در مثال زیر یک activity با کنترل دکمه پیاده سازی می کنید که از سرویس برای دانلود فایل از اینترنت استفاده می کند. زمانی که کاربر بر روی دکمه در activity کلیک می کند، دانلود اطلاعات از اینترنت آغاز می گردد. پس از به پایان رسیدن دانلود، سرویس از طریق broadcast receiver به activity این اتفاق را اعلان می کند.
در مثال کاربردی حاضر از کلاس IntentService استفاده خواهید نمود چرا که این کلاس پردازش های پس زمینه ای را به صورت خودکار مدیریت می نماید.

یک پروژه و activity جدید به ترتیب به نام های com.vogella.android.service.receiver و MainActivity ایجاد نمایید

سپس کلاس زیر را برای پیاده سازی سرویس تعریف نمایید.

 

package com.vogella.android.service.receiver;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import android.app.Activity;
import android.app.IntentService;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
public class DownloadService extends IntentService {
private int result = Activity.RESULT_CANCELED;
public static final String URL = "urlpath";
public static final String FILENAME = "filename";
public static final String FILEPATH = "filepath";
public static final String RESULT = "result";
public static final String NOTIFICATION = "com.vogella.android.service.receiver";
public DownloadService() {
super("DownloadService");
}
// will be called asynchronously by Android
@Override
protected void onHandleIntent(Intent intent) {
String urlPath = intent.getStringExtra(URL);
String fileName = intent.getStringExtra(FILENAME);
File output = new File(Environment.getExternalStorageDirectory(),
fileName);
if (output.exists()) {
output.delete();
}
InputStream stream = null;
FileOutputStream fos = null;
try {
URL url = new URL(urlPath);
stream = url.openConnection().getInputStream();
InputStreamReader reader = new InputStreamReader(stream);
fos = new FileOutputStream(output.getPath());
int next = -1;
while ((next = reader.read()) != -1) {
fos.write(next);
}
// successfully finished
result = Activity.RESULT_OK;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
publishResults(output.getAbsolutePath(), result);
}
private void publishResults(String outputPath, int result) {
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(FILEPATH, outputPath);
intent.putExtra(RESULT, result);
sendBroadcast(intent);
}
}

این کلاس را در لایه ی ،XMLفایل تنظیمات اپلیکیشن AndroidManifest.xml اضافه نمایید. حال زمان آن رسیده تا مجوزهای لازم را برای درج داده ( write ) در حافظه ی خارجی و دسترسی به اینترنت را نیز اعطا نمایید. پس از وارد کردن تغییرات فوق، محتوای AndroidManifest.xml می بایست ظاهری مشابه زیر داشته باشد.

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.vogella.android.service.receiver"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.vogella.android.service.receiver.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>
<service android:name="com.vogella.android.service.receiver.DownloadService" >
</service>
</application>
</manifest>

فایل layout مربوط به activity خود را به صورت زیر ویرایش نمایید.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Download" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Status: " />
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Not started" />
</LinearLayout>
</LinearLayout>

کلاس MainActivity خود را به صورت زیر ویرایش نمایید.

 

package com.vogella.android.service.receiver;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private TextView textView;
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
String string = bundle.getString(DownloadService.FILEPATH);
int resultCode = bundle.getInt(DownloadService.RESULT);
if (resultCode == RESULT_OK) {
Toast.makeText(MainActivity.this,
"Download complete. Download URI: " + string,
Toast.LENGTH_LONG).show();
textView.setText("Download done");
} else {
Toast.makeText(MainActivity.this, "Download failed",
Toast.LENGTH_LONG).show();
textView.setText("Download failed");
}
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.status);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(
DownloadService.NOTIFICATION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
public void onClick(View view) {
Intent intent = new Intent(this, DownloadService.class);
// add infos for the service which file to download and where to store
intent.putExtra(DownloadService.FILENAME, "index.html");
intent.putExtra(DownloadService.URL,
"http://www.vogella.com/index.html");
startService(intent);
textView.setText("Service started");
}
}

 

حال زمانی که برنامه ی فوق را اجرا کرده و بر روی دکمه کلیک می کنید، سرویس بلافاصله اقدام به بارگیری اطلاعات لازم از اینترنت می نماید. با اتمام دانلود، رابط کاربری بروز رسانی شده و یک پیغام Toast با اسم فایل به نمایش در می آید.

تنظیمات را طوری تغییر دهید که سرویس در فرایند ویژه ی خود اجرا شود. بار دیگر اپلیکیشن را تست کرده و اطمینان حاصل نمایید که همچنان به درستی عمل می کند چرا که با وارد نمودن تغییرات جدید، broadcast receiver ها از فرایندهای مختلف broadcast ها را دریافت می کنند.

 

 


امیدواریم آموزش تبادل داده و ارتباط با سرویس ها در اندروید نیز برای شما مفید واقع شده باشد و ادامه آموزش برنامه نویسی اندروید رو دنبال کنید . برای مطالعه پست‌ها بیشتر ، ما را در مدرسه کدنویسی تلگرام  و یا در تی جوان اینستاگرام دنبال کنید.

نظراتتون رو زیر همین پست با ما به اشتراک بگذارید.
ارسال دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

×

سلام کاربر عزیز

هر سوالی دارید در این بخش هستیم تا شما رو راهنمائی کنیم

روی لوگومون کلیک کنید

× چطور میتونم کمکتون کنم؟