یک برنامه (اپلیکیشن) اندرویدی معمولا چندین اکتیویتی دارد. هر اکتیویتی محتوای خودش را دارد و به کاربر اجازه میدهد تا کار خاصی را انجام دهد (مثل نمایش نقشه یا گرفتن عکس). برای انتقال کاربر از یک اکتیویتی به اکتیویتی دیگر، برنامهی شما باید از اینتنت (Intent) استفاده کند تا نیت و مقصود خود را تعریف کند و به سیستم بگوید که چه کاری میخواهد انجام دهد. اینتنت در انگلیسی یعنی «چیزی که قصد انجام آن را دارید». وقتی که یک اینتنت را از طریق متدی (Method) مثل startActivity() به سیستم میفرستید، سیستم از آن اینتنت برای تشخیص و استارت (شروع) کردن کامپوننت (Component) مناسب استفاده میکند. استفاده از اینتنتها به برنامهی شما اجازه میدهد که حتی یک اکتیویتی متعلق به برنامهی دیگر را استارت کنید.
یک اینتنت میتواند صریح (Explicit) باشد تا یک کامپوننت خاص (مثلا یک اکتیویتی خاص) را استارت کند یا میتواند ضمنی (Implicit) باشد تا هر کامپوننتی -که میتواند اکشن (Action) مورد نظر را انجام دهد- را استارت کند (مثل گرفتن عکس).
این مطلب به شما نشان میدهد که چطور از یک اینتنت استفاده کنید تا چند تعامل متداول و اساسی را با برنامههای دیگر انجام دهید، مثل استارت کردن یک برنامهی دیگر، دریافت یک نتیجه (Receive a result) از برنامهی دیگر و اینکه چطور برنامهی خود را به گونهای بسازید تا به اینتنتهای سایر برنامهها پاسخ دهد.
فرستادن کاربر به برنامهی دیگر
یکی از مهمترین مشخصههای اندروید توانایی یک برنامه برای فرستادن کاربر به برنامهی دیگر میباشد که به اکشن (Action) مورد نظر کاربر بستگی دارد. برای مثال، اگر برنامهی شما یک آدرس تجاری دارد که میخواهید آن را روی نقشه نمایش دهید، مجبور نیستید که یک اکتیویتی برای نمایش نقشه در برنامهی خود بسازید. به جای آن میتوانید با استفاده از اینتنت (Intent) یک درخواست برای نمایش آدرس ایجاد کنید. سپس سیستم اندروید برنامهای را استارت میکند که بتواند آدرس شما را روی نقشه نشان دهد.
همانطور که میدانید برای رفت و آمد بین اکتیویتیهای برنامهی خود باید از اینتنتها استفاده کنید. در واقع این کار را با اینتنت صریح (Explicit) انجام میدهید که دقیقا نام کلاس کامپوننتی را که میخواهید استارت کنید تعریف و مشخص میکند. هر چند مواقعی که میخواهید یک برنامهی جداگانه اکشنی را انجام دهد (مثل نمایش یک نقشه) باید از اینتنت ضمنی (Implicit) استفاده کنید.
در ادامه به شما نشان میدهم که چطور یک اینتنت ضمنی برای اکشن خاص بسازید و چگونه از آن استفاده کنید تا یک اکتیویتی در برنامهی دیگر -که میتواند اکشن شما را انجام دهد- را استارت کنید.
یک اینتنت ضمنی بسازید
اینتنتهای ضمنی نام کلاس کامپوننتی که قرار است استارت شود را اعلان (اعلام) نمیکنند، در عوض یک اکشن را برای اجرا اعلان میکنند. اکشن چیزهایی که میخواهید انجام دهید را مشخص میکند مثل نمایش (View)، ویرایش (Edit)، ارسال (Send) یا دریافت (Get) چیزی. اینتنتها اغلب شامل دیتا (Data) میشوند که با توجه به نوع اکشن به آن پیوند میخورد (متصل میشود) مثلا آدرسی که میخواهید نمایش دهید یا پیامی که میخواهید ارسال کنید. بسته به اینتنتی که میخواهید بسازید، دیتا ممکن است یک Uri یا یکی از چندین نوع داده باشد یا ممکن است یک اینتنت اصلا به دیتا نیاز نداشته باشد.
اگر دیتای شما یک Uri باشد، میتوانید با استفاده از سازندهی (Constructor) سادهی Intent()، اکشن و دیتای خود را تعریف کنید. برای مثال در زیر نشان دادم که چطور یک اینتنت برای برقراری تماس تلفنی بسازید و با استفاده از Uri -که همان دیتای اینتنت است- شمارهی تلفن را مشخص کنید:
Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
وقتی برنامهی شما اینتنت را از طریق startActivity() فراخوانی میکند، برنامهی Phone یک تماس تلفنی با شمارهی داده شده، برقرار میکند.
در ادامه چند نمونه اینتنت دیگر به همراه اکشن و دیتای Uri آنها آمده است:
-
نمایش یک نقشه:
// Map point based on address
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// Or map point based on latitude/longitude
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
-
نمایش یک صفحهی وب:
Uri webpage = Uri.parse("http://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
انواع دیگری از اینتنتهای ضمنی نیاز به دیتای اکسترا (Extra، اضافی) دارند که دیگر انواع داده مثل رشته (String) را در بر میگیرند. شما میتوانید یک یا چند تکه از اکسترا دیتا را با استفاده از ریختهای (گونههای) مختلف متدِ putExtra() به اینتنت وصله (اضافه) کنید.
در حالت پیشفرض، سیستم نوع MIME مناسب و مورد نیاز یک اینتنت را -بر اساس دیتای Uri آن- تعیین میکند؛ اگر در اینتنت یک Uri نیاوردهاید، معمولا باید از setType() استفاده کنید تا نوع دیتایی که به اینتنت پیوند خورده را مشخص کنید. تنظیم نوع MIME بعداً (جلوتر) مشخص میکند که چه نوع اکتیویتیهایی باید اینتنت را دریافت کنند.
در ادامه چند نمونه اینتنت دیگر آمده است که اکسترا دیتای آنها، اکشن دقیق مورد نظر را معلوم میکند.
-
ارسال یک ایمیل با یک اتچمنت (Attachment، پیوست):
Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM,
Uri.parse("content://path/to/email/attachment"));
// You can also attach multiple items by passing an ArrayList of Uris
-
ایجاد یک ایونت (Event، رویداد) در تقویم:
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 1, 19, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 0, 19, 10, 30);
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME,
beginTime.getTimeInMillis());
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME,
endTime.getTimeInMillis());
calendarIntent.putExtra(Events.TITLE, "Ninja class");
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
توجه: این ایونت برای تقویم فقط در APIهای 14 به بالا پشتیبانی میشود.
توجه: خیلی مهم است که اینتنت خود را تا جایی که ممکن است دقیق و مشخص تعریف کنید. برای مثال، اگر میخواهید با استفاده از اینتنت ACTION_VIEW یک تصویر (Image) را نمایش دهید، باید نوع MIME آن را image/* تعیین کنید. با این کار، از تریگر شدن (راه اندازی) دیگر برنامههایی که انواع دیگر داده (غیر از تصویر) را View میکنند، جلوگیری میشود و به این اینتنت پاسخ نمیدهند.
وارسی (اطمینان از) اینکه برنامهای وجود دارد تا اینتنت را دریافت کند
با اینکه پلتفرم اندروید تضمین میکند که اینتنتهای بدیهی و متداول (Certain Intents) به یکی از برنامههای تعبیه شده (built-in، مثل برنامهی Phone، Email یا تقویم) واگذار میشود، اما همیشه قبل از فراخوانی اینتنت باید یک وارسی (Verification) انجام دهید.
اخطار: اگر یک اینتنت را فراخوانی کنید و هیچ برنامهای در سیستم برای هندل کردن (پاسخ دادن) آن وجود نداشته باشد، برنامهی شما کرش (Crash) خواهد کرد.
برای اطمینان از اینکه یک اکتیویتی برای پاسخ دادن به اینتنت وجود دارد، queryIntentActivities() را صدا بزنید تا لیستی از اکتیوتیهایی را دریافت کنید که میتوانند اینتنت شما را هندل کنند. اگر لیست برگشتی (Return شده) خالی نباشد، بدون خطر میتوانید از آن اینتنت استفاده کنید.
برای مثال:
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;
اگر isIntentSafe برابر true باشد، پس حداقل یک برنامه به این اینتنت پاسخ خواهد داد.اگر false باشد هیچ برنامهای برای هندل کردن اینتنت وجود ندارد.
توجه: شما باید این وارسی را در بدو (به محض) استارت شدن اکتیویتی انجام دهید، تا در صورت احتیاط قابلیتهایی که از این اینتنت استفاده میکنند را غیرفعال کنید (قبل از اینکه کاربر بخواهد آن قابلیت را امتحان کند). همچنین اگر یک برنامهی خاص میشناسید که میتواند اینتنت را هندل کند، میتوانید یک لینک برای کاربر تدارک ببینید تا آن برنامه را دانلود کند.
استارت کردن یک اکتیویتی با اینتنت
وقتی که اینتنت را ایجاد کردید و سایر اطلاعات آن را ست (Set) کردید، startActivity() را فراخوانی کنید تا آن را به سیستم بفرستید. اگر سیستم بیش از یک اکتیویتی را -که بتوانند اینتنت را هندل کنند- شناسایی کند، یک دیالوگ برای کاربر نشان میدهد تا انتخاب کند کدام برنامه استفاده شود (مطابق شکل). اگر فقط یک اکتیویتی وجود داشته باشد که بتواند اینتنت را هندل کند، سیستم بلافاصله آن را استارت میکند.
startActivity(intent);
در ادامه یک مثال کامل آمده است که نشان میدهد چگونه یک اینتنت برای نمایش نقشه بسازیم، مطمئن شویم که یک برنامه برای هندل کردن اینتنت وجود دارد، سپس آن را استارت کنیم:
// Build the intent
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
// Verify it resolves
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;
// Start an activity if it's safe
if (isIntentSafe) {
startActivity(mapIntent);
}
نمایش اپ چوزر (App Chooser، دیالوگ انتخاب)
حواستان باشد که وقتی با ارسال اینتنت خود به startActivity() یک اکتیویتی را استارت میکنید -درحالی که بیش از یک برنامه برای هندل کردن اینتنت وجود دارد- کاربر در پایین دیالوگ میتواند انتخاب کند که کدام برنامه بطور پیشفرض (برای دفعات بعد) استفاده شود. این برای وقتی که کاربر میخواهد برای یک اکشن همیشه از یک برنامه استفاده کند، خوب است؛ مثل وقتی که یک صفحهی وب را باز میکند (کاربران معمولا فقط از یک مرورگر وب استفاده میکنند) یا یک عکس میگیرد (عموم کاربران یکی از برنامههای عکاسی را به بقیه ترجیح میدهند).
البته، اگر اکشن مورد نظر بتواند توسط چندین برنامه هندل شود و کاربر احتمالا هر بار برنامهی متفاوتی را ترجیح دهد (انتخاب کند) -مثل اکشن بهاشتراکگذاری (Share) که ممکن است کاربر چندین برنامه داشته باشد که با آن بتواند یک آیتم را به اشتراک بگذارد- شما باید اپ چوزر (دیالوگ انتخاب) را به صراحت (به عمد) نشان دهید. اپ چوزر کاربر را وادار میکند تا هر بار انتخاب کند کدام برنامه برای یک اکشن استفاده شود. در واقع کاربر نمیتواند یک برنامهی پیشفرض برای آن اکشن انتخاب کند).
برای نمایش چوزر، یک اینتنت با استفاده از createChooser() بسازید و آن را به startActivity() بفرستید. برای مثال:
Intent intent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);
// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
کد بالا، یک دیالوگ شامل یک لیست از برنامههایی نشان میدهد که میتوانند به اینتنتی که به متد createChooser() فرستاده شده، پاسخ دهند. همچنین آرگومان دوم متد (رشتهی title) عنوان دیالوگ قرار میگیرد.