Saturday, January 26, 2013

תכנות לאנדרואיד בקלות פרק 10 – ניידות בין מסכים שונים והעברת מידע בין Activities (Implicit, Explicit)

אוקיי, עד עכשיו יצרנו כמה מסכים עם כמה ממשקים נחמדים וצבעוניים, יש תפריט שהגדרנו שמאפשר לגשת להגדרות וכו.. איך אנחנו מחברים את הכל?
1. קריאה לactivity מתוך activity קיים (מעבר למסך חדש)
2. העברה של מידע ל activity
3. קבלת תשובה מactivity ל activity שקרא לו (onActivityResult)
4. implicit intent


בפרק זה נלמד:

הגדרה:
Intent הינו אחד מהרכיבים המרכזיים במערכת ההפעלה ומהווה אבן בניין מאוד חשובה בבנית אפליקציה.
Intent למעשה הוא מסר, שמכיל מספר מאפיינים וניתן להעמיס עליו data.
1. קריאה ל activity מתוך activity קיים (מעבר למסך חדש)
על מנת להתחיל activity מתוך activity נוכחי יש ליצור Intent חדש, הבנאי של Intent מקבל שני פרמטרים (יש לו עוד כמה overloads אבל נתרכז כרגע באחד מהם).

 
Intent intent = new Intent(getApplicationContext(),NewActvitity.class);


הפרמטר הראשון הוא ה context של ה activity הנוכחי, והפרמטר השני הוא השם של ה class של ה Activity השני .שאליו רוצים לעבור.
לאחר הגדרת ה Intent יש לקרוא למתודה startActivity באופן הבא:
startActivity(intent);

או את שני השלבים בצורה מקוצרת:
startActivity(new Intent(getApplicationContext(),NewActivity.class);

** יש לשים לב כי NewActivity.class מוגדר בקובץ ה manifest של הפרוייקט, אחרת נקבל שגיאה.
2. העברה של מידע ל activityנוסף בפרוייקט
סביר להניח כי ברגע שנפעיל Activity חדש נרצה להעביר לו מידע מסוים, בין אם זה מידע פרימיטיבי כמו int , string או אפילו אובייקט מורכב. בואו נראה כיצד זה מתבצע:
אותו Intent שהגדרנו בסעיף 1, נעמיס עליו מידע לפני שנעביר אותו ל Activity הבא:
Intent intent = new Intent(getApplicationContext(),NewActivity.class);
נעמיס עליו משתנה מסוג string, וניתן לו key מסוים , לדוגמא:
intent.putExtra(“name”,”moshe ben aharon”);
נעמיס עליו משתנה מסוג int, וניתן לו key מסוים, לדוגמא:
intent.putExtra(“age”,10);
נעמיס עליו אובייקט וניתן לו key מסוים, לדוגמא:
intent.putExtra(“car”,car1);
(הערה – על מנת שניתן יהיה להעמיס אובייקט, יש לוודא כי ה class אשר מייצג אותו ממש Serializable, זאת נעשה ע"י הוספה בהצהרת ה class :
Class Car implements Serializable{…}


בואו ניזכר:
String name = getIntent().getStringExtra(“name”);
Int age = getIntent().getIntExtra(“age”);
Car car1 = getIntent.getSerializableExtra(“car”);
 נעמיס עליו אובייקט וניתן לו key מסוים, לדוגמא:
intent.putExtra(“car”,car1);
(הערה – על מנת שניתן יהיה להעמיס אובייקט, יש לוודא כי ה class אשר מייצג אותו ממש Serializable, זאת נעשה ע"י הוספה בהצהרת ה class :
Class Car implements Serializable{…}





אוקיי, הצלחנו להעביר את ה intent ל Activity השני, כעת אנחנו צריכים לשלוף את המידע הזה ב Activity השני, כיצד נעשה זאת? באופן פשוט מאוד, ע"י הקוד הבא:
3. קבלת תשובה מactivity ל activity שקרא לו (onActivityResult)
במקרים רבים נרצה להתחיל activity חדש ולקבל ממנו מידע בחזרה ל activity הנוכחי.
לדוגמא:
נניח ואני במסעדה ואני רוצה להזמין מנה ראשונה, מנה עיקרית, קינוח ושתייה.
התפריט שלי יכול להראות כמו משהו כזה:
בחר מנה ראשונה
בחר עיקרית
בחר קינוח
בחר שתייה
מנה עיקרית:
מנה עיקרית 1
מנה עיקרית 2
מנה עיקרית 3
...


קינוח:
קינוח 1
קינוח 2
קינוח 3
..


מנה ראשונה:
מנה ראשונה 1
מנה ראשונה 2
מנה ראשונה 3
..


שתייה:
שתיה 1
שתיה 2
שתיה 3
...



מבחינת ה flow של המשתמש , מהתפריט הראשי הוא מגיע לתת activity וחוזר ל activity הראשי, משמע הוא צריך לשמור את הבחירה שלו בכל פעם שהוא מסיים תת activity.
זאת על מנת שבסוף יוכל להשלים הזמנה שלמה ולשלוח למטבח/מלצר.
נעשה זאת בצורה הבאה:
ב Activity הראשי במתודה של onCreate() נעבור ל Activity השני ע"י startActivityForResult().
ובמתודה הנקראית onActivityResult() ב activity הראשון נקבל בחזרה את המידע המבוקש מה Activity של המנה העיקרית.
בואו נבחן את ה flow מול activity ראשי אל מול ה activity של בחירת מנה עיקרית:
Activity Main:
Private static final String REQUEST_MAIN_DISH = 100;
Private static final String REQUEST_APPETIZER= 100;
Private static final String REQUEST_DESERT = 100;
Private static final String REQUEST_DRINK = 100;
//In onCreate do this :
startActivityForResult(new Intent(getApplicationContext(),MainCourse.class));
//in onActivityResult do this:
onActivityResult(int requestCode,int resultCode, Intent data)
{
//1 //2
If ((requestCode==REQUEST_MAIN_DISH) && (resultCode==RESULT_OK))
{
String mainCourse == data.getString(“main_course”);
}
}
//In Activity Main Course:
Intent returnIntent = new Intent();
returnIntent.putExtra(“main_course”,selectedDish);
setResult(RESULT_OK,returnIntent);
finish();


אנו למעשה מוודאים שני דברים ב flow הנ"ל:
1. האם הבקשה תואמת לסוג התשובה?
2. האם הבקשה החזירה תשובה חיובית, דהיינו משהו אכן נבחר ונשלח בחזרה.
4. Implicit Intent
יש מצבים שבהם נרצה להפעיל Activites ספציפיים של מערכת ההפעלה, למשל, נרצה לשלוח מייל מתוך האפליקציה.
בואו נראה כיצד נעשה הדבר ומה השוני לעומת מה שראינו עד עכשיו:
** הערה- על מנת לאפשר שליחת מייל דרך האפליקציה יש תת הרשאה מתאימה בקובץ ה manifest של הפרוייקט.
// create new intent with the constructor to take one const to specify the action parameter of the intent
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
// create string arrays of recepients, cc recepients and bcc recepients
String aEmailList[] = { "user@fakehost.com","user2@fakehost.com" };
String aEmailCCList[] = { "user3@fakehost.com","user4@fakehost.com"};
String aEmailBCCList[] = { "user5@fakehost.com" };
// load the arrays as extras on the intent itself with matching const keys
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, aEmailList);
emailIntent.putExtra(android.content.Intent.EXTRA_CC, aEmailCCList);
emailIntent.putExtra(android.content.Intent.EXTRA_BCC, aEmailBCCList);
// load the subject of the email message on the intent with the const key
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My subject");
// set the type of the intent to take “plain/text”
emailIntent.setType("plain/text");
// load the body message to the intent
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "My message body.");
// start the activity
startActivity(emailIntent);



יוצרים Intent כרגיל, אך הבנאי שלו יקבל קבוע אשר מורה למערכת ההפעלה כי ברצונו לבצע שליחת מייל עם ה intent הנ"ל.
לאחר מכן אנו בונים את רשימת הנמענים (שימו לב שניתן להבחין בין נמענים רגילים ל CC BCC.
כל מערך string-י שכזה מועמס כextra כל ה intent עם מפתחות מתאימים.
אנו מקנפגים את ה type של ה intent להיות “plain/text” ובסופו של דבר את המלל של הודעת ה email, ובסופו של דבר מפעילים את ה intent עם startActivity רגיל כפי שראינו.
באותה הצורה ניתן גם להגדיר פתיחת לינק בדפדפן, גישה לספר הטלפונים, ל ringtones ו וכו.. עם ההרשאות המתאימות כמובן. מידע נוסף ניתן למצוא באתר המפתחים של אנדרואיד בכתובת :
http://developer.android.com