شنود رویدادها در اندروید توسط BroadcastReceiver
گاهی اوقات لازم است اپلیکیشن ما بر اساس یک وضعیت یا رویداد که در سیستم عامل اندروید یا سایر برنامهها اتفاق افتاده واکنش نشان داده و متناسب آن پاسخ دهد که با استفاده از کامپوننت BroadcastReceiver امکان پذیر است. در واقع برودکست رسیورها به ما اجازه میدهند تا رویدادهای سیستم عامل یا برنامهها را دریافت کنیم. در این جلسه به معرفی این کامپوننت میپردازیم.
BroadcastReceiver چیست؟
به نام خدا. بهتر است با چند مثال شروع کنم. فرض کنید قصد ساخت اپلیکیشنی را داریم که وابستگی زیادی به شبکه اینترنت دارد و میخواهیم قطع و وصل ارتباط اینترنتی را به محض وقوع، به اطلاع کاربر برسانیم. در مثالی دیگر، برنامهای داریم که ورود کاربر توسط دریافت کد تایید از طریق پیامک (SMS) انجام میشود و میخواهیم بدون نیاز به وارد کردن دستی کد تایید توسط کاربر، به محض دریافت پیامک، کد دریافتی به برنامه منتقل شود.
در این موارد لازم است برنامه ما به رویدادها و وضعیت سیستم عامل دسترسی داشته باشد تا بتواند اتصال یا عدم اتصال به اینترنت و همچنین دریافت پیامک را بررسی کند. در اینجا با استفاده از BroadcastReceiver به پیغامهای مرتبط با رویداد مدنظرمان گوش داده سپس اقدام مناسب را انجام میدهیم.
به عبارتی دیگر، سیستم عامل اندروید برای وقوع تعدادی رویداد و وضعیت خاص، پیغامی همگانی صادر میکند که هر برنامه میتواند بر اساس نیاز خود، این پیغامها را دریافت کند. البته این پیغامها محدود و منحصر به سیستم عامل نبوده و برنامهها هم میتوانند پیغامهای سفارشی خود را منتشر کرده تا سایر برنامهها آنرا دریافت کنند.
واژه Broadcast به معنی “پخش” و “منتشر کردن” و Receiver به معنی “دریافت کننده” است. لذا از نام این کامپوننت هم کاربرد و هدف آن را میتوان حدس زد.
در ادامه جلسه به نحوه استفاده از برودکست رسیورها در اندروید میپردازیم.
پیاده سازی BroadcastReceiver در اندروید
قبل از هر چیز طبق مبحث آموزش ساخت پروژه در اندروید استودیو یک پروژه اندرویدی با نام BroadcastReceiver میسازم. اکتیویتی را از نوع Empty Activity و زبان را Java انتخاب کردم.
جهت پیاده سازی BroadcastReceiver و استفاده از آن، دو مرحله را باید انجام دهیم که در قالب مثال بررسی وضعیت اتصال اینترنت و همچنین دریافت پیامک بررسی میکنیم.
۱:ساخت BroadcastReceiver
برای ایجاد یک BroadcastReceiver یک کلاس تعریف میکنیم که از کلاس BroadcastReceiver مشتق (ارث بری) شده باشد. برای دریافت پیغامها باید متد onReceive() درون این کلاس Override شود. پیغام در قالب intent دریافت میشود.
در پکیج پروژه یک کلاس جاوا با نام دلخواه MyReceiver اضافه میکنم:
عمل مشتق کردن کلاس از BroadcastReceiver را هم در مرحله ساخت کلاس (مانند تصویر فوق) و هم به صورت دستی و بعد از ساخت کلاس میتوان انجام داد. در نهایت کلاس باید به صورت زیر تکمیل شود:
MyReceiver.java
package ir.android_studio.broadcastreceiver; import android.content.BroadcastReceiver; public class MyReceiver extends BroadcastReceiver { }
Override کردن متد onReceive() هم به هر دو صورت دستی و یا خودکار قابل انجام است. روی بدنه کلاس alt + enter زده و متد onReceive() را implement میکنم:
متد به اینصورت اضافه شد:
MyReceiver.java
package ir.android_studio.broadcastreceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { } }
کلاس را به صورت زیر تکمیل کردم:
MyReceiver.java
package ir.android_studio.broadcastreceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.widget.Toast; public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (checkNetwork(context)) { Toast.makeText(context, "اتصال برقرار است", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "اتصال برقرار نیست", Toast.LENGTH_SHORT).show(); } } private boolean checkNetwork(Context mContext) { try { ConnectivityManager conManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo nInfo = conManager.getActiveNetworkInfo(); return (nInfo != null && nInfo.isConnected()); } catch (NullPointerException e) { e.printStackTrace(); return false; } } }
پیغامی که سیستم عامل منتشر میکند و ما آنرا دریافت میکنیم صرفا تغییر وضعیت اتصال را اعلام میکند و نه اتصال یا عدم اتصال را. بنابراین وظیفه بررسی نوع وضعیت بر عهده خودمان است.
یک متد با نام دلخواه checkNetwork از نوع boolean در کلاس تعریف کردم که بررسی وضعیت اتصال را بر عهده دارد.
ConnectivityManager conManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo nInfo = conManager.getActiveNetworkInfo();
توسط متد ConnectivityManager و سپس getActiveNetworkInfo() وضعیت اتصال بررسی شده و نتیجه در nInfo ذخیره میشود. متد از نوع boolean بوده و قرار است یک نتیجه true یا false برگرداند.
return (nInfo.isConnected());
خط فوق بررسی میکند اتصال برقرار است یا خیر. یعنی isConnected مقدار true برمیگرداند یا false. در واقع این خط با شرط زیر برابر است:
if (nInfo.isConnected()) { return true; } else { return false; }
کدها درون یک try catch قرار گرفتهاند تا در صورتی که به هر دلیلی خروجی نال بود، برنامه کرش نکند.
حالا درون متد onReceive() بر اساس خروجی checkNetwork عملیات مدنظر را انجام میدهیم که در اینجا صرفا یک پیغام از جنس Toast تعریف کردهام. چنانچه نتیجه true برگردانده شود، پیغام “اتصال برقرار است” و در غیر اینصورت پیغام “اتصال برقرار نیست” اجرا خواهد شد.
۲:ثبت یا رجیستر کردن BroadcastReceiver
بعد از ساخت BroadcastReceiver لازم است آنرا در سیستم عامل ثبت کنیم. تا زمانی که کلاس مدنظر به عنوان یک Receiver ثبت و تعریف نشود، امکان گوش دادن به رویدادهای منتشر شده را نخواهد داشت. ثبت BroadcastReceiver به دو طریق امکان پذیر است که در ادامه هر دو روش را توضیح میدهم:
ثبت BroadcastReceiver در مانیفست (روش استاتیک)
مانیفست پروژه را باز کرده و مطابق زیر، یک تگ با نام receiver درون تگ application اضافه میکنم:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".MyReceiver"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> </application>
درست مانند تعریف اکتیویتی در مانیفست، برای تعریف برودکست رسیور اقدام میکنیم. ویژگی name همان نام کلاس و تگ action رویدادی که میخواهیم بررسی شود را تعریف میکنیم.
android.net.conn.CONNECTIVITY_CHANGE تغییر وضعیت اتصال را بررسی میکند. برخی اکشنها مانند اکشن فعلی، نیاز به دریافت مجوز دسترسی از سیستم عامل دارند. بنابراین پرمیشن موردنیاز را هم به تگ manifest اضافه میکنم:
در مورد حق دسترسیها قبلا در مبحث آموزش کار با کتابخانه Retrofit صحبت کردیم.
کد نهایی مانیفست پروژه:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ir.android_studio.broadcastreceiver"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".MyReceiver"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> </application> </manifest>
تعداد زیادی اکشن در سیستم عامل اندروید تعریف شده که نوع کاربرد هرکدام از نام آن مشخص است:
به عنوان مثال اکشن android.intent.action.BOOT_COMPLETED بوت شدن سیستم عامل را گوش میدهد که به محض بوت شدن دستگاه، پیغام مرتبط از طرف سیستم عامل به برنامهها ارسال میگردد.
ثبت BroadcastReceiver در اکتیویتی (داینامیک):
علاوه بر ثبت رسیور در تگ receiver مانیفست، امکان ثبت آن در اکتیویتی نیز وجود دارد. ضمن اینکه در مواردی مانند همین رویداد بررسی اتصال شبکه، به دلیل منقضی شدن اکشن در اندروید ۷، ناچاریم برای عملکرد صحیح برنامه در نسخههای جدیدتر، عمل ثبت را در اکتیویتی نیز انجام دهیم. اکتیویتی را به صورت زیر تکمیل میکنم:
MainActivity.java
package ir.android_studio.broadcastreceiver; import androidx.appcompat.app.AppCompatActivity; import android.content.IntentFilter; import android.os.Build; import android.os.Bundle; public class MainActivity extends AppCompatActivity { MyReceiver myReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { myReceiver = new MyReceiver(); registerReceiver(myReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")); } } }
درون متد onCreate() یک شرط تعریف کردم که بررسی کند چنانچه برنامه روی اندروید N و به بالا اجرا شد، دستورات زیر اجرا شود:
MyReceiver myReceiver = new MyReceiver(); registerReceiver(myReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
ابتدا یک نمونه از کلاس MyReceiver ایجاد کردم. سپس توسط متد registerReceiver() اکشن مدنظر را ثبت (رجیستر) کردهام. این متد دو ورودی میگیرد که ورودی اول کلاس رسیور و ورودی دوم نام اکشن یا همان intent مدنظر است.
برخلاف متد registerReceiver که عملیات ثبت BroadcastReceiver را انجام میدهد، متد unregisterReceiver برودکست رسیور ثبت شده را غیر فعال و حذف میکند. بنابراین بهتر است این دو متد را به صورت زیر در متدهای onResume() (یا onStart()) و onPause() (یا onDestroy()) اکتیویتی تعریف کنیم. عدم حذف receiver داینامیک میتواند موجب بروز خطا گردد.
MainActivity.java
package ir.android_studio.broadcastreceiver; import androidx.appcompat.app.AppCompatActivity; import android.content.IntentFilter; import android.os.Build; import android.os.Bundle; public class MainActivity extends AppCompatActivity { MyReceiver myReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onResume() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { myReceiver = new MyReceiver(); registerReceiver(myReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")); } super.onResume(); } @Override protected void onPause() { unregisterReceiver(myReceiver); super.onPause(); } }
پروژه را اجرا کرده و دسترسی به WiFi را روی حالتهای روشن و خاموش تست میکنم:
ملاحظه میکنید با فعال شدن WiFi پیغام “اتصال برقرار است” و با غیرفعال شدن آن پیغام “اتصال برقرار نیست” نمایش داده شده.
تاکید میکنم متد checkNetwork را صرفا برای بررسی وضعیت اتصال یا عدم اتصال نوشتیم وگرنه صرف دریافت پیغام مرتبط با رویداد نیاز به انجام کار خاصی ندارد. برای مثال کلاس را به صورت زیر امتحان کنید:
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "وضعیت اتصال به شبکه تغییر کرد", Toast.LENGTH_SHORT).show(); } }
به محض آنکه پیغامی مرتبط با اکشن تعریف شده در مانیفست دریافت شود، متد onReceive() اجرا خواهد شد. بنابراین نحوه استفاده از خروجی پیغام به نوع نیاز ما بستگی دارد.
میخواهم برای رویداد دریافت پیامک هم یک شنونده تعریف کنم. ابتدا پرمیشن و اکشن مربوط به دریافت پیامک را در مانیفست تعریف میکنم:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ir.android_studio.broadcastreceiver"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_SMS"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".MyReceiver"> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> </application> </manifest>
در قدم بعد و در متد onReceive() یک Toast دیگر اضافه میکنم:
@Override public void onReceive(Context context, Intent intent) { if (checkNetwork(context)) { Toast.makeText(context, "اتصال برقرار است", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, " اتصال برقرار نیست ", Toast.LENGTH_SHORT).show(); } Toast.makeText(context, "یک پیامک دریافت شد", Toast.LENGTH_SHORT).show(); }
اگر بخاطر داشته باشید در مبحث آموزش Runtime Permission در اندروید در اندروید گفتیم از اندروید ۶ به بعد، تعدادی از پرمیشنها باید از کاربر تاییده دریافت کنند. یکی از این پرمیشنها، دسترسی به پیامکهاست.
ابتدا یک Button در layout اکتیویتی تعریف میکنم:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/btn_request" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="پرمیشن پیامک" /> </RelativeLayout>
سپس کدهای مربوط به Runtime Permission را به صورت زیر به اکتیویتی اضافه میکنم:
MainActivity.java
package ir.android_studio.broadcastreceiver; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.content.DialogInterface; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity { MyReceiver myReceiver; private final int SMS_REQUEST_CODE = 100; private Button requestButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestButton = findViewById(R.id.btn_request); requestButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) { requestCameraPermission(); } else { Toast.makeText(MainActivity.this, "مجوز قبلا دریافت شده", Toast.LENGTH_SHORT).show(); } } }); } private void requestCameraPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.RECEIVE_SMS)) { new AlertDialog.Builder(this) .setTitle("درخواست مجوز") .setMessage("برای بررسی پیامک مجوز را تایید کنید") .setPositiveButton("موافقم", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { reqPermission(); } }) .setNegativeButton("لغو", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }) .create() .show(); } else { reqPermission(); } } private void reqPermission() { ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.RECEIVE_SMS}, SMS_REQUEST_CODE); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == SMS_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "مجوز تایید شد", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "مجوز رد شد", Toast.LENGTH_SHORT).show(); } } } @Override protected void onResume() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { myReceiver = new MyReceiver(); registerReceiver(myReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")); } super.onResume(); } @Override protected void onPause() { unregisterReceiver(myReceiver); super.onPause(); } }
مجدد پروژه را اجرا کرده و روی دکمه کلیک میکنم تا مجوز RECEIVE_SMS را به برنامه بدهم. سپس یک پیامک به دیوایس ارسال میکنم:
ملاحظه میکنید پیغام “پیامک دریافت شد” نمایش داده شده است. با توجه به اینکه این اکشن در مانیفست تعریف شده، در صورت اجرای برنامه در پس زمینه هم پیغام رویداد پیامک توسط برنامه ما دریافت خواهد شد.
مهمترین رویدادهای سیستمی در اندروید
در جدول زیر به تعدادی از مهمترین و پرکاربردترین رویدادهای سیستمی اندروید اشاره شده است:
نام رویداد | کاربرد |
---|---|
android.intent.action.BOOT_COMPLETED | این پیغام بعد از بوت شدن سیستم عامل منتشر میشود |
android.intent.action.CALL_BUTTON | هنگامی که کاربر روی گزینه Call یا گزینه دیگری با هدف باز کردن صفحه شماره گیر کلیک میکند |
android.intent.action.REBOOT | بعد از راه اندازی مجدد اندروید، پیغام این رویداد منتشر میشود |
android.intent.action.BATTERY_LOW | شارژ کم باتری دستگاه را اعلام میکند |
android.intent.action.BATTERY_OKAY | رسیدن شارژ باتری به حد مطلوب را اعلام میکند |
android.intent.action.DATE_CHANGED | تغییر تاریخ سیستم عامل را اعلام میکند |
android.intent.action.AIRPLANE_MODE | هنگامی که دستگاه روی حالت پرواز قرار میگیرد یک پیغام منتشر میشود |
انتشار پیغام یا intent سفارشی (Custom Intent Broadcasting)
تا اینجای کار ما پیغام یا intent هایی که توسط سیستم عامل منتشر میشد را دریافت میکردیم. اما علاوه بر دریافت پیغام، امکان ارسال پیغامهای سفارشی هم وجود دارد. یعنی ما یک پیغام سفارشی را از برنامه خود منتشر کرده و سایر برنامهها این پیغام را دریافت میکنند.
فرض کنید با وقوع یک رویداد خاص در برنامه ما (برای مثال کلیک روی یک دکمه) کد زیر فراخوانی میشود:
Intent mIntent = new Intent(); mIntent.setAction("ir.android_studio.ir.MY_CUSTOM_BROADCAST"); sendBroadcast(mIntent);
در اینجا توسط setAction() یک اکشن سفارشی با نامی دلخواه ایجاد کردهایم. اکشن تعریف شده توسط sendBroadcast() در سطح سیستم عامل منتشر میشود. در صورت نیاز میتوان اطلاعات بیشتری توسط intent ارسال کرد که به وسیله putExtra() قابل انجام است:
Intent mIntent = new Intent(); mIntent.setAction("ir.android_studio.ir.MY_CUSTOM_BROADCAST"); mIntent.putExtra("data","My additional information"); sendBroadcast(mIntent);
حالا کافیست در یک برنامه دیگر، تگ action کلاس BroadcastReceiver (در حالت استاتیک) به صورت زیر تعریف شود:
و یا ورودی دوم در متد registerReceiver() (در حالت داینامیک):
registerReceiver(myReceiver, new IntentFilter("ir.android_studio.ir.MY_CUSTOM_BROADCAST "));
انتشار پیغام به همراه درخواست پرمیشن
ممکن است پیغام سفارشی مدنظر ما به یک مجوز دسترسی خاص نیاز داشته باشد. بنابراین میتوانیم در کنار پیغام، پرمیشن مورد نیاز را هم ارسال کنیم تا فقط برنامههایی که پرمیشن مربوطه را از سیستم عامل (و یا کاربر) دریافت کردهاند قادر به دریافت پیغام سفارشی ما باشند. به نمونه زیر دقت کنید:
sendBroadcast(new Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS);
در اینجا علاوه بر نام، مجوز SEND_SMS هم ارسال میشود و فقط برنامهای میتواند این Broadcast را دریافت (Receive) کند که مجوز دسترسی به SEND_SMS را دریافت کرده باشد.
انتشار پیغام سفارشی در داخل برنامه (درون برنامهای)
در مواردی ممکن است قصد داشته باشیم پیغام سفارشی که درون برنامه ما تولید شده صرفا در همین برنامه قابل دریافت بوده و سایر برنامهها به آن دسترسی نداشته باشند. این کار مزایایی دارد از جمله امنیت بیشتر و عدم شنود پیغامهای اختصاصی ما توسط برنامههای دیگر و دیگری عدم درگیر کردن Broadcast در سطح سیستم عامل.
اندروید کلاس LocalBroadcastManager را برای ارسال پیغامهای سفارشی درون برنامهای معرفی کرده که البته این کلاس هم به دلایلی از جانب اندروید Deprecate شده و به همین دلیل بیشتر از این پیرامون آن صحبت نمیکنم. چنانچه مایل هستید با این کلاس آشنا شوید مقالاتی مانند این لینک را مطالعه کنید. خود اندروید استفاده از روشهای دیگر مانند LiveData را پیشنهاد کرده است.
در پایان توصیه میکنم در خصوص مبحث BroadcastReceiver ها مطالعه بیشتری کرده و مثالهای بیشتری را بررسی کنید. بررسی تمامی اکشنها از حوصله این آموزش خارج هست.
موفق و پیروز باشید.
مطالعهی بیشتر:
https://developer.android.com/guide/components/broadcasts
https://developer.android.com/reference/android/content/Intent
https://developer.android.com/reference/android/content/BroadcastReceiver
https://developer.android.com/reference/android/content/Context
https://developer.android.com/reference/androidx/localbroadcastmanager/content/LocalBroadcastManager
توجه : سورس پروژه درون پوشه Exercises قرار دارد
تعداد صفحات : ۲۲
حجم : ۲ مگابایت
قیمت : رایگان
دانلود رایگان با حجم ۲ مگابایت لینک کمکی
سلام و عرض ادب
دوره آموزش اندروید در سایت شما مجموعا چند ساعته؟
و از مقدماتی تا چه سطی هست؟
ممنون میشم پاسخ بدید
دوره به صورت متنی (PDF) هست.
تقریبا تمامی مباحث پایه اندروید رو شامل میشه
با تشکر از مطالب خوبتون ، یک سوال آیا امکان راه اندازی خودکار اپلیکیشن بعد از یک event خاص مثل اتمام تماس هست خیلی اینترنت را جستوجو کردم اما تنها چیزی که به دست اوردم این بود که با context میتونستیم یک Toast بدیم که شامل اطلاعات تماس و… ولی از استارت شدن اپلیکیشن در onReceive هیچی پیدا نکردم ممنون میشم راهنمایی بفرمایید .
از برودکست رسیور چطور استفاده کنم که بعد از بسته شدن برنانه همچنین در حال اجرا بمونه و به کار خودش ادامه بده. توی نت که سرچ کردم همه گفته بودن از سرویس باید استفاده بشه ولی طبق همون کدها سرویس رو ایجاد می کنم و برودکست رو داخل سرویس ثبت می کنم ولی همچنان با بسته شدن اپ برودکست از کار میوفته
ممنون میشم راهنماییم کنید چی کار کنم
این مساله بخصوص تو نسخه های جدید اندروید یه چالش محسوب میشه. ان شا الله سر فرصت که تونستم در موردش کامل تحقیق و تست انجام بدم آموزش رو بروز می کنم. البته بعید میدونم به این زودی ها انجام بشه و کار شما راه بیفته
لینک دانلود خرابه
هم لینک اصلی و هم کمکی هردو قابل دریافت هستن و مشکلی نیست
ببخشید یه سوال
آیا همه این موارد باید تو ذهن برنامه نویس بمونه ؟
مثال میزنم من در لحظه یادگیری recyclerview ، fragment
database، service، broadcast..
و الباقی موارد هر کدوم رو کامل متوجه میشم و حتی برنامه های متفاوتی باهاشون کد میزنم
ولی بعد از چند هفته اگه قرار باشه ازشون استفاده کنم نیاز به یه سرچ مختصر دارم
میخوام ببینم این حالت عادیه ؟ یا تمرین باید در حدی باشه که تمامشون رو حفظ بشیم ؟
اصلا همچین توقعی نداشته باشید از خودتون. جزئیات فرّار هستن و سرچ کردن و مرور مباحث اجتناب ناپذیره
سلام خداقوت
این خطاها در اجرای برنامه هست
Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could not resolve
com.android.tools.build:gradle:3.5.3.
تاکید شده قبل از ارسال مشکل، صفحه پرسش های رایج رو مطالعه کنید تا هم وقت خودتون تلف نشه هم سوالات تکراری نباشه
سلام توی تعریف متد sms نوشتین private void requestCameraPermission() { ما اینجا پرمیشن دوربین نمیخوایم که sms میخواهیم! ضمناً هیچ توضیحی در مورد
shouldShowRequestPermissionRationale
AlertDialog ها
onRequestPermissionsResult
داده نشده فکر کنم این قسمت رو از قلم انداختین ممنون میشم توضیح بدین
عذرخواهی میکنم چون کد این قسمت رو از آموزش دوربین کپی کردم یادم رفت نامش رو تغییر بدم تا باعث سردرگمی نشه. ارتباطی به دوربین نداره و باید به requestSMSPermission تغییر میدادم
سلام وقتتون بخیر.
من برای چک کردن اینترنت روش شما رو اجرا کردم و از alert استفاده کردم تا وقتی که اینترنت قطعه همراه با toast نمایش بده و موقعی که اینترنت وصل میشه alert.dismiss() زدم و همه چی درست کار میکنه alert موقعی که اینترنت قطعه درست کار میکنه و نمایش داده میشه ولی وقتی دوباره اینترنت رو وصل میکنم alert بسته نمیشه ولی toast که اینترنت وصل شده رو نمایش میده
داخل اینترنت هم هرچی گشتم روش هایی بود که همون مشکل رو داشت چجوری باید alert رو ببندم؟
ممنون میشم راهنمایی کنید
مطمئنید خود Alert رو درست نوشتید؟ یعنی اگه داخل اکتیویتی توسط یه دکمه dismiss بشه بسته میشه؟