أندرويد للمبتدئين التنقل بين شاشات التطبيق باستخدام الـ Intents في أندرويد


أحمد النوبي

يُتيح نظام تشغيل أندرويد طريقة محددة وبسيطة للتنقل بين المكونات الأساسية للتطبيقات والتي ذكرناها سابقًا وذلك عن طريق استخدام الـ Intents.

android-intents-navigation.png

Intents

يُعتبر الـ Intent طريقة التواصل بين مكونات التطبيق المختلفة من أجل القيام بشيء ما، فهو يسمح لمكونات التطبيق (كالأنشطة Activities ، الخدمات Services وغيرها) من التفاعل مع بعضها البعض والقيام بإحدى المهام، فباستخدام الـ Intent يمكننا التنقل بين شاشات التطبيق المختلفة أو التطبيقات الأخرى فمثلًا عند الضغط على زر يقوم بفتح نشاط Activity جديد داخل نفس التطبيق وعرض صورة به، كما يسمح بتفاعل التطبيقات الأخرى المتواجدة على الهاتف مع تطبيقك، فيمكن عرض الصورة في تطبيق خارجي كتطبيق المعرض (Gallery).

وعند استخدام الـ Intent في التنقل بين مكونات نفس التطبيق يسمى بالـ Explicit Intent، لذا يستخدم Explicit Intent في ربط مكونات التطبيق الداخلية ببعضها وسنتعرف من خلال الأمثلة القادمة على كيفية استخدام الـ Explicit Intents في التنقل بين الأنشطة وإرسال واستقبال البيانات بينهم.

وعند استخدامه للتنقل إلى التطبيقات الخارجية يسمى بالـ Implicit Intent.

المثال الأول

الآن قم بفتح Android Studio وقم بعمل تطبيق جديد اسمه "Explicit Intent Example"، في هذا المثال سنقوم باستخدام زر للتنقل إلى نشاط جديد.

01.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">

	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Welcome to The First Activity"
		android:textSize="21sp"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="GO!"
		android:id="@+id/gobtn"/>
</LinearLayout>

ثانيًا للاستجابة للزر عند الضغط عليه نقوم باستخدام onClickListener.

package apps.noby.explicitintentexample;

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

public class MainActivity extends Activity {

	Button go;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		go =(Button) findViewById(R.id.gobtn);

		go.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Create your Intent Here
			}
		});
	}
}

وبداخلها سنقوم بكتابة الـ Intent المناسب ولكن قبل ذلك ينبغي أن نقوم بعمل نشاط جديد وربطه بواجهة استخدام جديدة ولعمل ذلك نضغط بالزر الأيمن على المجلد المسمى باسم الحزمة ثم اختر:

New > Activity > Empty Activity

02.png

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

03.png

بعد أن يقوم البرنامج بصنع ملفات النشاط الجديد من ملف activity_second.xml سنقوم بصنع واجهة المستخدم الخاصة بالنشاط الثاني.

وسنضع بداخلها TextView يعرض النص "Welcome to The Second 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">

	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Welcome to The Second Activity"
		android:textSize="21sp"/>
</LinearLayout>

والآن نعود مرة أخرى للنشاط الأول لنكمل التابع ()onClick، ولصنع Intent نقوم بعمل كائن من الصنف Intent وتمرير لدالة البناء الخاصة به النشاط الذي سننتقل منه وهو MainActivity.this وتمرير النشاط الذي نريد الانتقال إليه وهو SecondActivity.class.

Intent i = new Intent(MainActivity.this,SecondActivity.class);

بهذا السطر نكون قد صنعنا الهدف ولكن يتبقى أن نقوم بتفعيل هذا الهدف ليستجيب له التطبيق وذلك عن طريق التابع ()startActivity وتمرير الـ Intent الذي قمنا بصناعته إليه.

لتصبح الشيفرة النهائية هي:

package apps.noby.explicitintentexample;

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

public class MainActivity extends Activity {

	Button go;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		go =(Button) findViewById(R.id.gobtn);

		go.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Create your Intent Here
				Intent i = new Intent(MainActivity.this,SecondActivity.class);
				startActivity(i);
			}
		});
	}
}

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

04.png

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

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	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>
  
	<activity android:name=".SecondActivity"></activity>
</application>

المثال الثاني

سنقوم في هذا المثال بإرسال بيانات من نشاط وعرضها في نشاط آخر.

05.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">
  
	<EditText
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:hint="Your Name"
		android:textSize="21sp"
		android:id="@+id/editt"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Send"
		android:id="@+id/sendbtn"/>
</LinearLayout>

ثم سنقوم بالاستجابة لضغط الزر كما سبق وبداخل التابع ()onClick يتم تعريف الـ Intent وحفظ البيانات المكتوبة في الـ EditText بداخله ثم استدعاء النشاط الجديد.

ولإرسال البيانات داخل الـ Intent يتم ذلك عن طريق التابع ()putExtra ونمرر له عنصرين وهما المفتاح و القيمة.

المفتاح هو نص نميز به القيمة التي يتم إرسالها عبر الـ Intent ويُستخدم مرة أخرى لاستعادة البيانات التي أرسلناها.

والقيمة هي البيانات التي نرغب في إرسالها.

package apps.noby.explicitintentexample;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {

	final public static String NAME_TAG = "name";
	private Button send;
	private EditText et;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		send =(Button) findViewById(R.id.sendbtn);
		et = (EditText)findViewById(R.id.editt);

		send.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Create your Intent Here
				Intent i = new Intent(MainActivity.this, SecondActivity.class);
				String name = et.getText().toString();
				i.putExtra(NAME_TAG,name);
				startActivity(i);
			}
		});
	}
}

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

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

<?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">

	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Hello, "
		android:textSize="21sp"
		android:id="@+id/hellotxt"/>
</LinearLayout>

ولاستقبال النص الذي أرسلناه بداخل الـ Intent يجب علينا أولًا أن نستعيد الـ Intent الذي قام بفتح النشاط باستخدام التابع ()getIntent.

Intent actIntent = getIntent();

ولاستعادة النص الذي حفظناه نستخدم ()getText().toString ونمرر لها المفتاح الذي قمنا بحفظ البيانات به، ثم بعد ذلك نعرض هذا النص بداخل TextView.

package apps.noby.explicitintentexample;

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

public class SecondActivity extends AppCompatActivity {

	private TextView tv;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_second);
		tv =(TextView) findViewById(R.id.hellotxt);
		Intent actIntent = getIntent();
		String name = actIntent.getExtras().getString(MainActivity.NAME_TAG);
		tv.setText("Hello, " + name);
	}
}

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

06.png


المثال الثالث

سنقوم في هذا المثال بإعادة البيانات من النشاط الثاني إلى النشاط الأول عند الانتهاء من التفاعل مع النشاط الثاني.

07.png

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

<?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:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Register"
		android:id="@+id/regbtn"/>

	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="NO Name"
		android:textSize="30sp"
		android:id="@+id/regtxt"/>
</LinearLayout>

وبداخل النشاط الأول نقوم باستدعاء النشاط الثاني عند الضغط على الزر المتواجد بالواجهة ولكن في هذا المثال لإخبار نظام التشغيل بأننا ننتظر بيانات من النشاط الآخر سنقوم بفتح النشاط الآخر بالتابع ()startActivityForResult بدلًا من التابع ()startActivity.

private static final int ACTIVITY_REQUEST_CODE = 6 ;
private Button reg;
private TextView tv;

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	reg =(Button) findViewById(R.id.regbtn);
	tv = (TextView)findViewById(R.id.regtxt);

	reg.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			//Create your Intent Here
			Intent i = new Intent(MainActivity.this, SecondActivity.class);
			startActivityForResult(i,ACTIVITY_REQUEST_CODE);
		}
	});
}

ونمرر للتابع ()startActivityForResult الـ Intent كالمعتاد والرقم الخاص بالطلب وهذا الرقم هو أي رقم صحيح، وفائدته عند رجوع البيانات للنشاط مرة أخرى التمييز بين أي الأنشطة التي قامت بإرسال هذه البيانات.

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

والآن نقوم بصنع الواجهة الخاصة بالنشاط الآخر في ملف activity_second.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">

	<EditText
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:hint="Enter Your Name"
		android:textSize="21sp"
		android:id="@+id/edttxt"/>

	<Button
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Enter"
		android:id="@+id/entbtn"
		android:layout_gravity="right"/>
</LinearLayout>

بعد ذلك نكتب شيفرة التحكم الخاصة بهذا النشاط.

package apps.noby.explicitintentexample;

import android.content.Intent;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class SecondActivity extends Activity {

	public static final String REG_NAME_TAG ="name" ;
	private EditText et;
	private Button enter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_second);
		et =(EditText) findViewById(R.id.edttxt);
		enter = (Button) findViewById(R.id.entbtn);

		enter.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				String str = et.getText().toString();
				Intent in = new Intent();
				in.putExtra(REG_NAME_TAG,str);
				setResult(RESULT_OK,in);
				finish();
			}
		});
	}
}

فعند الضغط على الزر Enter نقوم بتسجيل النص المتواجد بداخل العنصر EditText، إنشاء Intent جديد وحفظ النص بداخله ثم استدعاء التابع ()setResult والذي يمكننا من إرسال البيانات التي قمنا بتخزينها داخل Intent إلى من قام باستدعاء هذا النشاط.

ونمرر للتابع ()setResult الثابت RESULT_OK والمعرّف داخل الـ (API (android.app.Activity كما نمرر لها الـ Intent الذي قمنا بإنشائه وحفظ البيانات بداخله.

أخيرًا نستخدم التابع ()finish وهو المسؤول عن غلق النشاط.

لاستقبال هذه البيانات في النشاط الأول نقوم بتضمين التابع ()onActivityResult في النشاط كما يلي.

package apps.noby.explicitintentexample;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

	private static final int ACTIVITY_REQUEST_CODE = 6 ;
	private Button reg;
	private TextView tv;


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		reg =(Button) findViewById(R.id.regbtn);
		tv = (TextView)findViewById(R.id.regtxt);

		reg.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Create your Intent Here
				Intent i = new Intent(MainActivity.this, SecondActivity.class);
				startActivityForResult(i,ACTIVITY_REQUEST_CODE);
			}
		});
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if ( (resultCode == RESULT_OK) && (requestCode == ACTIVITY_REQUEST_CODE)){
			String name = data.getExtras().getString(SecondActivity.REG_NAME_TAG);
			tv.setText(name);
		}
	}
}

وبداخل هذا التابع نتأكد من أن النشاط السابق تم إغلاقه بشكل صحيح ولم يحدث له مشكلة عن طريق التأكد من أن المتغير resultCode يساوي RESULT_OK التي قمنا بتمريرها للتابع ()setResult ثم نتأكد أيضًا من أن النشاط الذي يُعيد هذه البيانات له رقم طلب يساوي رقم الطلب الذي قمنا باستخدامه مسبقًا، بعد ذلك نبدأ في استقبال البيانات.

ثم نقوم بتشغيل التطبيق على المحاكي.

08.png

الأمثلة السابقة كانت باستخدام Explicit Intent للقيام بالوظيفة المطلوبة ولربط مكونات التطبيق المختلفة ببعضها فيمكنك من صنع تطبيق متعدد الأنشطة، في الأمثلة القادمة سنقوم باستخدام الـ Implicit Intents والتعامل معها.

المثال الرابع

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

09.png

قم بإنشاء تطبيق جديد يُدعى "Implicit Intent Example" ثم نبدأ بصنع واجهة المستخدم في ملف 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="Open Hsoub Academy"
		android:id="@+id/opnbtn"/>
</LinearLayout>

وعند الضغط على الزر نقوم بفتح الرابط.

Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://academy.hsoub.com"));
startActivity(i);

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

لتصبح الشيفرة النهائية الخاصة بالبرنامج كما يلي:

package apps.noby.explicitintentexample;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends Activity {

	private Button open;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		open = (Button) findViewById(R.id.opnbtn);

		open.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//Create your Intent Here
				Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://academy.hsoub.com"));
				startActivity(i);
			}
		});
	}
}

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

10.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="Dial Number"
		android:id="@+id/dialbtn"/>
</LinearLayout>

وعند الضغط على الزر نقوم بالاتصال بالرقم التالي:

Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:0123456789"));
startActivity(i);

ونمرر لدالة البناء الخاصة بالـ Intent نوع الفعل الذي نريده وهو الاتصال بالرقم، ثم نمرر له الرقم.

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

11.png

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



1 شخص أعجب بهذا


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


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن