اذهب إلى المحتوى

يتميز نظام تشغيل أندرويد بوجود شريط أعلى الشاشة يمُد المستخدم بالعديد من المعلومات الهامة من ضمنها الإشعارات التي ترسلها التطبيقات.

android-notifications.png

فالإشعارات هي جزء من واجهة المستخدم لكنها تظهر خارج التطبيق لإعلام المستخدم بحدث معين، مما يُمكّن المستخدم من عرضه والتفاعل معه بينما يستخدم تطبيقًا آخر. ويحتوي الإشعار على رسالة مختصرة عن هذا الحدث.

ويظهر الإشعار عند حدوثه كأيقونة تعبر عن التطبيق في شريط الحالة أعلى الشاشة، ويمكنك معرفة تفاصيله عند سحب درج الإشعارات والضغط على الإشعار.

11.png

هناك عدة خطوات لصنع الإشعارات من داخل تطبيقك:

صنع كائن البناء الخاص بالإشعار من الصنف Notification.Builder

Notification.Builder mBuilder = new Notification.Builder(this);

من خلال هذا الكائن يمكننا التحكم في الخصائص الخاصة بالإشعار مثل عنوان الإشعار، الأيقونة المستخدمة، التحكم في الأولوية، التحكم في المهام التي يستطيع القيام بها عند الضغط عليه وغيرهم من الخصائص المختلفة.

تخصيص الحد الأدنى من الخصائص للإشعار

بعد الحصول على كائن البناء نبدأ في التحكم في خصائص الإشعار، وهناك بعض الخصائص الأساسية اللازم توافرها في الإشعار وهي:

  • الأيقونة الخاصة بالإشعار.
  • عنوان الإشعار.
  • المحتوى الخاص بالإشعار.

12.png

mBuilder.setSmallIcon(R.drawable.msg_icon);
mBuilder.setContentTitle("New Message");
mBuilder.setContentText("Hi, This is the message text.");

ويوجد العديد من الخصائص الأخرى التي يمكنك استخدامها حسب حاجة التطبيق لها.

بناء الإشعار بالخصائص السابقة

يتم ذلك باستدعاء التابع ()build والحصول على كائن من Notification.

Notification notif = mBuilder.build();

إظهار الإشعار في درج الإشعارات

يوفر أندرويد الصنف NotificationManager لإدارة الإشعارات من حيث إصدار الإشعار، تعديل الإشعار بعد إصداره أو إلغاء الإشعار برمجيًا. لذا يجب أولًا الحصول على كائن من هذا الصنف وذلك عن طريق استدعاء الدالة ()getSystemService وتمرير الثابت NOTIFICATION_SERVICE والذي يعني طلب الخدمات الخاصة بالإشعارات من خدمات النظام. وسيتم استخدام الدالة ()getSystemService كثيرًا عند الحاجة لطلب خدمات من النظام.

NotificationManager notifyMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

بعد ذلك نستدعي التابع ()notify باستخدام الكائن من NotificationManager ليظهر الإشعار في الحال، وتمرير رقم مميز له يُعبر عن الإشعار ليُستخدم هذا الرقم فيما بعد للتعديل على الإشعار أو إلغائه، كما يتم تمرير الإشعار الذي تم بنائه من قبل.

int notificationId = 103;
notifyMngr.notify(notificationId, notif);

تطبيق 1

سنقوم في هذا التطبيق بتجربة الخطوات السابق شرحها لتكوين التطبيق مثل الصورة التالية:

13.png

أولًا نبدأ بصنع واجهة المستخدم البسيطة في ملف activity_main.xml:

<?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"
	android:gravity="center">

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Show Notification"
		android:id="@+id/shw_notification"/>
</LinearLayout>

بعد ذلك ننتقل إلى الشيفرة الخاصة بالتطبيق في MainActivity.java باتباع الخطوات ذاتها لصنع الإشعار عند الضغط على الزر.

package apps.noby.simplenotification;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

	private Button shwbtn;
	private String title;
	private String detailText;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		shwbtn = (Button) findViewById(R.id.shw_notification);
		title = "New Message";
		detailText ="Hi, This is the message text.";

		shwbtn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Step 1
				Notification.Builder mBuilder = new Notification.Builder(MainActivity.this);
	
				//Step 2
				mBuilder.setSmallIcon(R.drawable.ic_message);
				mBuilder.setContentTitle(title);
				mBuilder.setContentText(detailText);

				//Step 3
				Notification notif = mBuilder.build();

				//Step 4
				NotificationManager notifyMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

				int notificationId = 103;
				notifyMngr.notify(notificationId,notif);
			}
		});
	}
}

ثم نقوم بتجربة التطبيق على المحاكي للتأكد من عمله كما ينبغي.

14.png

تطبيق 2

في التطبيق السابق عند الضغط على الإشعار لا يحدث شيئ، لذا في هذا التطبيق سنقوم بفتح نشاط جديد يعرض تفاصيل الإشعار أو ما نريد من معلومات عند الضغط على الإشعار.

15.png

ولفتح نشاط جديد داخل التطبيق سنستخدم Intent ولكن سنقوم بتغليف الكائن من Intent داخل كائن آخر من PendingIntent وفائدة هذا التغليف هو أنه لا يمكن استخدام الكائن من Intent خارج التطبيق، والإشعار كما ذكرنا يُعرض خارج حدود التطبيق لذا يقوم PendingIntent بإعطاء الصلاحية للتطبيقات الأخرى أو النظام والذي نُرسل إليه PendingIntent القدرة على تنفيذ الأوامر كأنها تتم داخل تطبيقك.

أولًا نقوم بصنع نشاط جديد يُدعى ResultActivity.

ثانيًا سنقوم بتعديل الشيفرة الخاصة بـ MainActivity.java وإضافة كائن من Intent.

Intent intent = new Intent(MainActivity.this,ResultActivity.class);

ونستطيع إرسال بيانات إلى النشاط الآخر بنفس الطريقة المستخدمة في الدروس السابقة.

intent.putExtra(DESC_KEY,detailText);

ثم نقوم بتغليف الكائن داخل PendingIntent:

PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this , 0 , intent , PendingIntent.FLAG_UPDATE_CURRENT);

والخطوة الأخيرة هي وضع هذا Intent ضمن خصائص الإشعار باستخدام كائن البناء:

mBuilder.setContentIntent(pIntent);

لتُصبح الشيفرة النهائية لملف MainActivity.java بعد التعديل هي:

package apps.noby.simplenotification;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

	private Button shwbtn;
	private String title;
	private String detailText;
	public final static String DESC_KEY ="descriptionKey";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

        shwbtn = (Button) findViewById(R.id.shw_notification);
		title = "New Message";
		detailText ="Hi, This is the message text.";

    	shwbtn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Step 1
				Notification.Builder mBuilder = new Notification.Builder(MainActivity.this);

				//Step 2
				mBuilder.setSmallIcon(R.drawable.ic_message);
				mBuilder.setContentTitle(title);
				mBuilder.setContentText(detailText);

				Intent intent = new Intent(MainActivity.this,ResultActivity.class);
				intent.putExtra(DESC_KEY,detailText);
				PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);

				mBuilder.setContentIntent(pIntent);

				//Step 3
				Notification notif = mBuilder.build();

				//Step 4
				NotificationManager notifyMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

				int notificationId = 103;
				notifyMngr.notify(notificationId,notif);
			}
		});
	}
}

ولم نقم بتغيير شيء في ملف الواجهة activity_main.xml.

الآن لعرض التفاصيل التي سترسل إلى النشاط الجديد ResultActivity.java نبدأ في صنع واجهة المستخدم الخاصة بالنشاط ثم بتغيير الشيفرة الخاصة به ولا يوجد اختلاف بينها وبين الطريقة المستخدمة في الدروس السابقة.

<?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:gravity="center"
	android:orientation="vertical">

	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:textSize="25sp"
		android:id="@+id/desc"/>
</LinearLayout>
package apps.noby.simplenotification;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class ResultActivity extends AppCompatActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_result);

		TextView tv = (TextView) findViewById(R.id.desc);
		Intent intent = getIntent();
		String description = intent.getExtras().getString(MainActivity.DESC_KEY);
		tv.setText(description);
	}
}

16.png

ثم نقوم بتجربة التطبيق على المحاكي.

تطبيق 3

لاحظ أنه عند الضغط على الإشعار في التطبيق السابق يقوم بفتح نشاط جديد ولكن يظل الإشعار متواجدًا في درج الإشعارات رغم عرضه والتفاعل معه لذا سنقوم في هذا التطبيق بتغيير بسيط حتى يختفي الإشعار بمجرد التفاعل معه.

في شيفرة التطبيق السابق بداخل الملف MainActivity.java سنقوم بتعديل السطور الخاصة بالخطوة الثانية لتُصبح.

mBuilder.setContentTitle(title);
mBuilder.setContentText(detailText);

mBuilder.setAutoCancel(true);

Intent intent = new Intent(MainActivity.this,ResultActivity.class);
intent.putExtra(DESC_KEY,detailText);

قمنا فقط بإضافة السطر الخاص باستدعاء التابع ()setAutoCancel وتمرير القيمة true باستخدام كائن البناء، والآن عند تجربة التطبيق بعد هذا التعديل ستجد أنه يقوم بإزالة الإشعار بمجرد الضغط عليه.

17.png

تطبيق 4

يتم استخدام الشكل السابق بكثرة خاصة في تطبيقات المحادثة أو رسائل البريد حيث يتم عرض صورة المستخدم وبجانبها بحجم صغير الأيقونة الخاصة بالتطبيق.

ولصنع ذلك يتم استدعاء التابع ()setLargeIcon باستخدام كائن البناء وتمرير له الصورة المراد عرضها بحجم كبير.

لكن هناك شرط وهو أن تكون الصورة بصيغة Bitmap ولأننا حتى الآن نقوم في الدروس باستخدام الصور المتواجدة في مجلد drawable لذا ينبغي قبل تمريرها للتابع ()setLargeIcon أن نقوم بتحويلها إلى Bitmap ويتم ذلك عن طريق الخطوة التالية.

Bitmap img = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.ic_person);

ثم بعد ذلك تمريرها كما سبق لبناء الإشعار.

mBuilder.setLargeIcon(img);

لتُصبح الشيفرة الكاملة الخاصة بالملف MainActivity.java هي:

package apps.noby.simplenotification;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

	private Button shwbtn;
	private String title;
	private String detailText;
	public final static String DESC_KEY ="descriptionKey";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		shwbtn = (Button) findViewById(R.id.shw_notification);
		title = "New Message";
		detailText ="Hi, This is the message text.";

      	shwbtn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Step 1
				Notification.Builder mBuilder = new Notification.Builder(MainActivity.this);

				//Step 2
				mBuilder.setSmallIcon(R.drawable.ic_message);

				Bitmap img = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.ic_person);
				mBuilder.setLargeIcon(img);

				mBuilder.setContentTitle(title);
				mBuilder.setContentText(detailText);
				mBuilder.setAutoCancel(true);

				Intent intent = new Intent(MainActivity.this,ResultActivity.class);
				intent.putExtra(DESC_KEY,detailText);
				PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);

				mBuilder.setContentIntent(pIntent);

				//Step 3
				Notification notif = mBuilder.build();

				//Step 4
				NotificationManager notifyMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

				int notificationId = 103;
				notifyMngr.notify(notificationId,notif);

			}
		});
	}
}

ليعمل التطبيق كما هو متوقع على المحاكي.

18.png

تطبيق 5

في بعض الأحيان نحتاج إلى التفاعل السريع للمستخدم مع التطبيق دون الحاجة لفتح التطبيق أو لتوفير أكثر من اختيار لفتح أجزاء محددة في التطبيق.

19.png

للقيام بذلك نستخدم التابع ()addAction والذي يمكننا من إضافة زر إلى الإشعار.

PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);

mBuilder.setContentIntent(pIntent);
mBuilder.addAction(R.drawable.ic_reply,"Reply",pIntent);
mBuilder.addAction(R.drawable.ic_content_copy,"Copy",pIntent);

//Step 3
Notification notif = mBuilder.build();

ولاستخدام هذا التابع نقوم بتمرير صورة لتظهر داخل الزر، النص الخاص بالزر وأخيرًا كائن من PendingIntent ليتم تنفيذه عند الضغط على هذا الزر.

ويمكنك عمل ()addAction حتى ثلاث مرات فقط، ويمكن لكل زر أن يكون له PendingIntent مختلف خاص به ليقوم بتنفيذ أمر مختلف وفي المثال السابق لشرح الفكرة تم استخدام PendingIntent واحد.

والآن نقوم بتشغيل التطبيق على المحاكي للتأكد من عمله بشكل صحيح.

تطبيق 6

20.png

في بعض الأحيان تحتاج إلى التعديل على إشعار سابق دون إصدار إشعار جديد، وذلك بإضافة بعض المعلومات له أو بتغيير محتوى الإشعار أو كلاهما.

وقد تحتاج أيضًا إلى إزالة الإشعار برمجيًا دون تدخل من المستخدم وذلك عند حدوث شيء محدد أو مرور وقت محدد.

أولًا للقيام بالتعديل أو بتغيير محتوى إشعار دون إصدار إشعار آخر جديد نقوم ببناء الإشعار ثم نقوم بإصداره باستخدام نفس الـ NotificationID الذي نمرره للتابع ()notify حتى يقوم بتعديل الإشعار صاحب ID ذاته.

21.png

بفرض أن لدينا هذا الإشعار عند الضغط على زر Show Notification.

shwbtn = (Button) findViewById(R.id.shw_notification);

shwbtn.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		//Step 1
		Notification.Builder mBuilder = new Notification.Builder(MainActivity.this);

		//Step 2
		mBuilder.setSmallIcon(R.drawable.ic_message);

		Bitmap img = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.ic_person);
		mBuilder.setLargeIcon(img);

		mBuilder.setContentTitle("New Message");
		mBuilder.setContentText("Hi, This is the message text.");
		mBuilder.setNumber(++totalNumber);
		mBuilder.setAutoCancel(true);

		Intent intent = new Intent(MainActivity.this,ResultActivity.class);
		intent.putExtra(DESC_KEY,"Hi, This is the message text.");
		PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
		mBuilder.setContentIntent(pIntent);

		//Step 3
		Notification notif = mBuilder.build();

		//Step 4
		NotificationManager notifyMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

		int notificationId = 103;
		notifyMngr.notify(notificationId,notif);
	}
});

ثم عند الضغط على الزر Update Notification يتم تغييرها إلى المحتوى التالي.

updatebtn = (Button) findViewById(R.id.upd_notification);

updatebtn.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		//Step 1
		Notification.Builder mBuilder = new Notification.Builder(MainActivity.this);

		//Step 2
		mBuilder.setSmallIcon(R.drawable.ic_message);
	
		Bitmap img = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.ic_person);
		mBuilder.setLargeIcon(img);

		mBuilder.setContentTitle("Updated Message");
		mBuilder.setContentText("Hi, This is an updated Message.");
		mBuilder.setNumber(++totalNumber);
		mBuilder.setAutoCancel(true);

		Intent intent = new Intent(MainActivity.this,ResultActivity.class);
		intent.putExtra(DESC_KEY,"Hi, This is an updated Message.");
		PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
		mBuilder.setContentIntent(pIntent);

		//Step 3
		Notification notif = mBuilder.build();

		//Step 4
		NotificationManager notifyMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

		int notificationId = 103;
		notifyMngr.notify(notificationId,notif);
	}
});

لاحظ أننا قمنا باستخدام نفس NotificationID في خطوة إظهار الإشعار وذلك لإخبار النظام أننا نريد التعديل على إشعار متواجد بالفعل.

والآن لإزالة الإشعار نضغط على الزر Cancel Notification.

cnclbtn = (Button) findViewById(R.id.cncl_notification);

cnclbtn.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		NotificationManager notifyMngr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		totalNumber = 0;
		int notificationId = 103;
		notifyMngr.cancel(notificationId);
	}
});

لإزالة الإشعار نستدعي التابع ()cancel باستخدام الكائن من NotificationManager ونمرر لها الـ ID الخاص بالإشعار.

لاحظ أننا قد قمنا باستخدام التابع ()setNumber عند بناء الإشعار وذلك ليُظهر عدد مرات بناء وتعديل الإشعار ذاته، ويتم بدأ العد مجددًا عند الضغط على الزر Cancel Notification.

وبتغيير ملف الواجهة في activity_main.xml ليُصبح.

<?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"
	android:gravity="center">

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Show Notification"
		android:id="@+id/shw_notification"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Update Notification"
		android:id="@+id/upd_notification"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Cancel Notification"
		android:id="@+id/cncl_notification"/>
</LinearLayout>

تستطيع أن تلاحظ الرقم المتواجد أقصى يمين الإشعار والذي يُعبر عن عدد مرات التعديل على الإشعار ذاته، ويتحكم التابع ()setNumber في القيمة التي ستظهر بناءً على قيمة المعامل الذي تم تمريره له.

22.png

تطبيق 7

هناك العديد من الإشعارات التي لا يستطيع المستخدم من إزالتها ويجب عليه انتظار انتهاء حدث معين أو القيام بمهمة معينة حتى يختفي الإشعار، مثال على ذلك عند تحميلك لملف تجد إشعار لا يمكنك إزالته يُخبرك بمعلومات عن التحميل وللتخلص منه ينبغي الانتظار حتى اكتمال تحميل الملف أو إلغاء التحميل.

23.png

لتفعيل هذه النوعية من الإشعارات داخل التطبيق لدينا طريقتان

1. نقوم بتغير قيمة إحدى خصائص الإشعار الذي قمنا ببنائه وتدعى flags، حيث نقوم بإضافة خاصيتين إلى الإشعار وهما:

  • Notification.FLAG_NO_CLEAR وهي تلغي تأثير التابع ()setAutoCancel فلا يتم مسح الإشعار عند الضغط عليه.
  • Notification.FLAG_ONGOING_EVENT وهي المسؤولة عن إخبار النظام أن هذا الإشعار لديه معلومات لا زالت لها أهمية ولا ينبغي إزالتها الآن.
//Step 3
Notification notif = mBuilder.build();

notif.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;

2. استدعاء التابع ()setOngoing باستخدام كائن البناء و تمرير له القيمة true، مع إزالة سطر استدعاء التابع ()setAutoCancel حتى لا يتم إزالة الإشعار عند الضغط عليه.

//Step 2

mBuilder.setSmallIcon(R.drawable.ic_message);
mBuilder.setContentTitle("New Message");
mBuilder.setContentText("Hi, This is the message text.");
mBuilder.setOngoing(true);

ملحوظة: لا يوجد فرق بين أي من الطريقتين من حيث الوظيفة أو التأثير.

ولإزالة هذا الإشعار عند الانتهاء من الحدث ينبغي استدعاء التابع ()cancel وتمرير له NotificationID كما سبق، ولا يمكن إزالته إلا بهذه الطريقة.

تطبيق 8

عندما يأتي تنبيه من تطبيق ما وكانت شاشة القفل مغلقة فهناك ثلاثة اختيارات للنظام للتعامل مع هذا الإشعار.

24.png

إما إظهار محتوى الإشعار على شاشة القفل، أو إظهار الإشعار مع إخفاء محتواه أو عدم إظهار الإشعار ويمكن التحكم في هذه الاختيارات برمجيًا من خلال التابع ()setVisibility باستخدام كائن البناء ويُمرر له ثابت قيمته:

  • Notification.VISIBILITY_PUBLIC إذا أردت أن يظهر محتوى الإشعار.
  • Notification.VISIBILITY_PRIVATE إذا أردت إظهار الإشعار فقط دون إظهار محتواه.
  • Notification.VISIBILITY_SECRET وذلك لعدم ظهور الإشعار على شاشة القفل ويظهر حين نتجاوز قفل الشاشة أولًا.
//Step 2
mBuilder.setSmallIcon(R.drawable.ic_message);
mBuilder.setContentTitle("New Message");
mBuilder.setContentText("Hi, This is the message text.");
mBuilder.setAutoCancel(true);
mBuilder.setVisibility(Notification.VISIBILITY_PRIVATE);

ملحوظة: حتى يعمل التابع ()setVisibility يجب أن يكون الحد الأدنى من نسخة النظام التي يدعمها التطبيق هي Lollipop API 21، حيث لا تدعم النسخ الأقدم هذه الميزة لذا تأكد من تغييرها عند عمل مشروع جديد.

تطبيق 9

يدعم أندرويد عدة أنواع من الإشعارات بجانب النوع الأساسي الذي استخدمناه في الأمثلة السابقة.

Big Text Style

25.png

حيث تستطيع أن تجمع بين الأمرين، إشعار بسيط يعرض نصًا مختصرًا ويمكن للمستخدم أن يقوم بتكبيره لعرض المزيد من التفاصيل. ويكثر استخدام هذه الطريقة عند عرض إشعار برسالة بريد إلكتروني جديدة فيمكن لك تكبيرها وقراءة تفاصيل الرسالة دون فتح التطبيق.

ويمكنك تطبيق ذلك في تطبيقك عن طريق.

  1. عمل إشعار وتحديد خصائصه كما سبق وذلك لتُعرض هذه المعلومات عندما يكون الإشعار صغير الحجم.
  2. عمل كائن من Notification.BigTextStyle وتحديد عنوان جديد وعرض تفاصيل أكثر ثم إضافته لخصائص الإشعار.
  3. بناء الإشعار.

ولتوضيح هذه الخطوات بالشيفرة نقوم بالتالي:

private void showBigTextNotification() {

	//Step 1
	mBuilder = new Notification.Builder(this);
	mBuilder.setSmallIcon(R.drawable.ic_txt);
	mBuilder.setContentTitle(“Big Text in Normal Mode”);
	mBuilder.setContentText(“Example of a Big Text Notification.”);

	//Step 2
	Notification.BigTextStyle bigText = new Notification.BigTextStyle();
	bigText.bigText(“This Text will be repeated over and over.This Text will be repeated over and over.This Text will be repeated over and over.This Text will be repeated over and over.”);
	bigText.setBigContentTitle(“Big Text in Expansion Mode”);

	mBuilder.setStyle(bigText);

	//Step 3
	Notification notfi = mBuilder.build();
	mNotificationManager.notify(200,notfi);
}

Inbox Style

26.png

يختلف هذا النوع عن النوع السابق في أنه يتيح لك عرض التفاصيل في أكثر من سطر، أما النوع السابق سيعرض كافة التفاصيل في نفس السطر دون القدرة على التحكم فيما يُعرض في كل سطر على حدا.

ويُستخدم هذا النوع عند التعديل على إشعار وإضافة المزيد من التفاصيل إليه. مثل تطبيقات البريد الإلكتروني عند عرض في نفس الإشعار سطرًا عن كل رسالة قادمة.

لتطبيق هذا النوع نمر بنفس الخطوات السابقة ولكن باستخدام كائن من الصنف Notification.InboxStyle.

لاحظ أن لكل صنف توابعه الخاصة التي تُمكنك من إضافة الخصائص له.

private void showInboxNotification() {

	//Step 1
	mBuilder = new Notification.Builder(this);
	mBuilder.setSmallIcon(R.drawable.ic_inbox);
	mBuilder.setContentTitle(“Inbox in Normal Mode”);
	mBuilder.setContentText(“Example of a Inbox Notification.”);

	lines = new String[6];
	lines[0] = Line number 1”;
	lines[1] = Line number 2”;
	lines[2] = Line number 3”;
	lines[3] = Line number 4”;
	lines[4] = Line number 5”;
	lines[5] = Line number 6”;

	//Step 2
	Notification.InboxStyle inbox = new Notification.InboxStyle();
	for(int I = 0 ; i<lines.length; i++)
		inbox.addLine(lines[i]);
	inbox.setBigContentTitle(“Inbox in Expansion Mode”);
	mBuilder.setStyle(inbox);

	//Step 3
	Notification notfi = mBuilder.build();
	mNotificationManager.notify(97,notfi);
}

Big Picture Style

27.png

عندما تكون تفاصيل الإشعار هي صورة يُفضل استخدام هذا النوع.

وأيضًا يختلف نوع الكائن المستخدم Notification.BigPictureStyle.

private void showBigPictureNotification() {

	//Step 1
	mBuilder = new Notification.Builder(this);
	mBuilder.setSmallIcon(R.drawable.ic_picture);
	mBuilder.setContentTitle(“Big Picture in Normal Mode”);
	mBuilder.setContentText(“Example of a Big Picture Notification.”);

	Bitmap img = BitmapFactory.decodeResource(getResources(),R.drawable.picture);

	//Step 2
	Notification.BigPictureStyle bigPic = new Notification.BigPictureStyle();
	bigPic.bigPicture(img);
	bigPic.setBigContentTitle(“Big Picture in Expansion Mode”);
	mBuilder.setStyle(bigPic);

	//Step 3
	Notification notfi = mBuilder.build();
	mNotificationManager.notify(6,notfi);
}

وبدمج كافة الأنواع في تطبيق واحد يعرض الإشعار عند الضغط على الزر المناسب لتُصبح الشيفرة النهائية لملف MainActivity.java هي:

package apps.noby.advancednotification;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

	private Button bigTextButton;
	private Button inboxButton;
	private Button bigPictureButton;
	private Button cancelButton;

	private Notification.Builder mBuilder;
	private NotificationManager mNotificationManager;

	private String[] lines;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		bigTextButton = (Button) findViewById(R.id.bg_txt);
		inboxButton = (Button) findViewById(R.id.inbx);
		bigPictureButton = (Button) findViewById(R.id.bg_pic);
		cancelButton = (Button) findViewById(R.id.cncl);

		mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		
      	bigTextButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick (View v){
				showBigTextNotification();
			}
		}
	);

	inboxButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			showInboxNotification();
		}
	});

	bigPictureButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			showBigPictureNotification();
		}
	});

	cancelButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			cancelNotification();
		}
	});
	}

	private void cancelNotification() {
		mNotificationManager.cancelAll();
	}

	private void showBigTextNotification() {
		mBuilder = new Notification.Builder(this);
		mBuilder.setSmallIcon(R.drawable.ic_txt);
		mBuilder.setContentTitle("Big Text in Normal Mode");
		mBuilder.setContentText("Example of a Big Text Notification.");

		Notification.BigTextStyle bigText = new Notification.BigTextStyle();
		bigText.bigText("This Text will be repeated over and over.This Text will be repeated over and over.This Text will be repeated over and over.This Text will be repeated over and over.");
		bigText.setBigContentTitle("Big Text in Expansion Mode");

		mBuilder.setStyle(bigText);

		Notification notfi = mBuilder.build();
	
		mNotificationManager.notify(200,notfi);
	}

	private void showInboxNotification() {
		mBuilder = new Notification.Builder(this);
		mBuilder.setSmallIcon(R.drawable.ic_inbox);
		mBuilder.setContentTitle("Inbox in Normal Mode");
		mBuilder.setContentText("Example of a Inbox Notification.");

		lines = new String[6];
		lines[0] = "Line number 1";
		lines[1] = "Line number 2";
		lines[2] = "Line number 3";
		lines[3] = "Line number 4";
		lines[4] = "Line number 5";
		lines[5] = "Line number 6";

		Notification.InboxStyle inbox = new Notification.InboxStyle();
		for(int i = 0 ; i<lines.length; i++)
			inbox.addLine(lines[i]);
		inbox.setBigContentTitle("Inbox in Expansion Mode");
		mBuilder.setStyle(inbox);

		Notification notfi = mBuilder.build();

		mNotificationManager.notify(97,notfi);
	}

	private void showBigPictureNotification() {
		mBuilder = new Notification.Builder(this);
		mBuilder.setSmallIcon(R.drawable.ic_picture);
		mBuilder.setContentTitle("Big Picture in Normal Mode");
		mBuilder.setContentText("Example of a Big Picture Notification.");

		Bitmap img = BitmapFactory.decodeResource(getResources(),R.drawable.picture);

		Notification.BigPictureStyle bigPic = new Notification.BigPictureStyle();
		bigPic.bigPicture(img);
		bigPic.setBigContentTitle("Big Picture in Expansion Mode");
		mBuilder.setStyle(bigPic);

		Notification notfi = mBuilder.build();
		mNotificationManager.notify(6,notfi);
	}
}

وملف واجهة المستخدم activity_main.xml:

<?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:gravity="center"
	android:orientation="vertical">

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Big Text Style"
		android:id="@+id/bg_txt"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Inbox Style"
		android:id="@+id/inbx"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Big Picture Style"
		android:id="@+id/bg_pic"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Cancel ALL"
		android:id="@+id/cncl"/>
</LinearLayout>

28.png

بهذا نكون قد وصلنا إلى نهاية هذا الدرس، في انتظار تجربتكم وآرائكم.


تفاعل الأعضاء

أفضل التعليقات

شرح رائع ,شكرا كتيير

بس ياريت لو تشرح كيف بخلي الاشعارات تظهر بوقت معين انا بحددو من البرمجة  او المستخدم بحددو من التطبيق 

Hossam Mohammed

نشر

يلغالي ابغى طريقه اظييف عداد الرسايل للتطبيقات بدون برنامج يعني مافي امر اضيفه لملفات النظام عشان يعطيني عداد الرسايل 

 



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...