You are on page 1of 68

‫אורי ריבלוב ‪Talentder -‬‬

‫פורטל למציאת עבודות ‪“Talentder” -‬‬

‫עבודת גמר – תכנון ותכנות מערכות בטלפונים ניידים תחת מערכת הפעלה ‪Android‬‬

‫שם המגיש‪ :‬אורי ריבלוב‬

‫תעודת זהות‪326367588 :‬‬

‫שם המורה‪ :‬לביא זהבה‬

‫תאריך הגשה‪15.6.22 :‬‬

‫‪1‬‬
Talentder - ‫אורי ריבלוב‬
‫תוכן עניינים‬
4.................................................................................................................................................. ‫מבוא‬
4.................................................................................................................................... ‫הרקע לפרויקט‬
5.............................................................................................................................................. :‫סקרים‬
6........................................................................................................................................... :‫סקר שוק‬
7........................................................................................................................................... :‫חידושים‬
7............................................................................................................................... :‫אתגרים מרכזיים‬
8................................................................................................ ‫מבנה הפרויקט \ ארכיטקטורת הפרויקט‬
9...................................................................................................................................... ‫מסכי פרויקט‬
9............................................................................................................................ Activity_splash
11 ........................................................................................................................... activity_log_in
13 ......................................................................................................................... activity_sign_up
16 ..............................................................................................................................activity_main
18 ................................................................................................................. activity_profile_page
20 ......................................................................................................... activity_profile_page_edit
24 ............................................................................................................. activity_resume_viewer
25 ................................................................................................ activity_company_Profile_page
27 .................................................................................................. activity_company_profile_edit
30 ......................................................................................................................... activity_add_job
32 ....................................................................................................................... activity_job_view
33 ................................................................................................. activity_company_browse_jobs
35 ..................................................................................................................... chats_users_layout
36 ...................................................................................................................... activity_my_chats
38 .......................................................................................................................... message_layout
39 ............................................................................................................................... activity_chat
42 ................................................................................................................. activity_job_browser
47 .......................................................................................................... activity_internet_problem
48 ........................................................................................................................................... ‫מחלקות‬
48 .................................................................................................................. ServiceManager.java

2
Talentder - ‫אורי ריבלוב‬
49 ................................................................................................... NetworkChangeReceiver.java
50 .............................................................................................................................. Message.java
51 ...................................................................................................................................... Job.java
52 .................................................................................................................................... User.java
53 .......................................................................................................................... jobAdapter.java
54 ....................................................................................................................... UserAdapter.java
55 ................................................................................................................. MessageAdapter.java
56 ...................................................................................................................... :‫ קבצים‬+ ‫בסיס נתונים‬
56 ..............................................................................................................FireBaseAuthentication
56 ...................................................................................................... FireBase Realtime Database
58 ......................................................................................................................... FireBaseStorage
60 ................................................................................................................................ ‫מדריך למשתמש‬
66 .......................................................................................................................................... ‫רפלקציה‬
67 ...................................................................................................................................... ‫ביבליוגרפיה‬
68 ............................................................................................................................................ ‫נספחים‬

3
‫אורי ריבלוב ‪Talentder -‬‬

‫מבוא‬
‫מסמך זה יתאר על אופן פיתוח האפליקציה" ‪ " Talentder‬בסביבת אנדרואיד סטודיו‪ .‬המסמך יכלול את‬
‫הפרקים ‪:‬מבנה הפרויקט‪ ,‬מדריך למשתמש‪ ,‬מדריך למתכנת‪ ,‬מסכי האפליקציה )תיאור והסבר על מטרתם(‪,‬‬
‫בסיס הנתונים ועל אופן שמירת הנתונים‪.‬‬

‫הרקע לפרויקט‬
‫עם תחילת שנת הלימודים האחרונה שלי‪ ,‬והצורך להגיש פרויקט בדמות אפליקציית אנדרואיד שתשקף את‬
‫הכישורים שלי על מנת לקבל את ‪ 5‬היחידות האלו‪ ,‬חשבתי על רעיון פשוט‪.‬‬

‫”‪ “Talentder‬היא אפליקציה פשוטה למציאת עבודה‪ .‬האפלקציה מאפשרת הירשמות קלה למערכת ומרכזת‬
‫את כל מקומות העבודה הפוטנציאליים במקום אחד ומקשרת בין מחפשי עבודה למעסיקים באפליקציה‬
‫פשוטה וקלה להבנה‪.‬‬

‫במיוחד לאור מגפת הקורונה אשר פגעה בכולנו בשלוש השנים האחרונות‪ ,‬הרבה מאוד אנשים לצערנו איבדו‬
‫את עבודתם לרבים מאנשים אלו ישנם ילדים והוצאות שוטפות שלא עצרו ולכן בזמן הזה במיוחד האפלקציה‬
‫שבניתי תיתן אפשרות לאנשים אלו למצוא עבודה ביעילות ובמהירות‪.‬‬

‫בנוסף הרבה מאוד בני נוער בגילאי ‪ 16-18‬מחפשים עבודות מזדמנות בכדי לחסוך כסף בחופשים ובסופי שבוע‬
‫ומכיוון שרוב בני הנוער נמצאים זמן רב מיומם בטלפון ולכן אני מאמין שאפלקציה למציאת עבודה‬
‫תהיה פופולרית במיוחד בקרב בני נוער‬

‫‪4‬‬
‫אורי ריבלוב ‪Talentder -‬‬
‫סקרים‪:‬‬
‫בשביל לבדוק האם לפרויקט שלי יש ביקוש ערכתי סקר בין חברים ומשפחה שיבדוק ביקוש לאפלציה כמו‬
‫שבניתי‪ ,‬ואלו תוצאות הסקר‪:‬‬

‫‪5‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫רוב מוחלט של הנשאלים בסקר ענו כי הם מחפשים עבודה דרך האינטרנט כלומר יש ביקוש לפתרון טכנולוגי‬
‫לתהליך מציאת העבודה ‪,‬בנוסף כמעט כל המשיבים ענו כי הם מאמינים שיעבדו לפחות בשני עבודות כל‬
‫החיים מה שמראה שיש להרבה משתמשים פוטנציאל לחזור לאפלקציה מחדש‪.‬‬

‫על פי תוצאות הסקר הסקתי שיש שוק לאפלקציה שפיתחתי ושוק חיפוש העבודה הוא שוק גדול‪.‬‬

‫סקר שוק‪:‬‬
‫כיום ישנו שוק יחסית גדול של אפלקציות דומות למציאת עבודה‪:‬‬

‫‪ – AllJobs‬האפלקציה המובילה בשוק אך מתמקדת בעיקר באתר ופחות מושקעת באפלקציה‬ ‫‪-‬‬
‫‪ – Drusimil‬גם אפלקציה פופולרית מאוד אבל האפלקציה אינה הכי מותאמת מכיוון שהיא האתר‬ ‫‪-‬‬
‫הרגיל בפורמט טלפוני‬
‫‪ - jobnet‬פחות פופולרית מהשניים האחרות אבל גם עם נתח שוק לא קטן אבל ללא אפלקציה רק‬ ‫‪-‬‬
‫אתר‬

‫מסקנה‪ :‬קיים שוק גדול וצורך גדול לאפלקציות למציאת עבודה‪ ,‬אך האפלקציות הנוכחיות אינן נוחות ולא‬
‫כולן מותאמות לפורמט טלפוני ולכן יש מקום בשוק לאפלקציה נוספת שתפתור בעיות אלו באפלקציות‬
‫הקיימות‪.‬‬

‫‪6‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫חידושים‪:‬‬
‫ממשק משתמש יפה‪ ,‬נקי‪ ,‬אלגנטי והכי חשוב ‪ -‬נוח ואינטואיטיבי לשימוש‬ ‫‪-‬‬
‫גיבוי וסנכרון אקטיבי )בזמן אמת( עם הענן‬ ‫‪-‬‬
‫צאט פשוט עם מעסיקים פוטנציאלים‬ ‫‪-‬‬
‫אפשרות להוציא את העבודות הפוטנציאליות ל‪Excel‬‬ ‫‪-‬‬
‫אפשרות להוסיף מסמך קורות חיים לפרופיל‬ ‫‪-‬‬

‫אתגרים מרכזיים‪:‬‬
‫פיתוח אפלקציה זאת אינו היה פשוט‪ ,‬אמנם תרגלנו את המיומניות שקשורות בכתיבת פרויקט במהלך כל‬
‫השנה אך לחבר את כל המרכיבים השונים לפרויקט אחד מכיל אינו היה פשוט אך בסופו של דבר אני מאוד‬
‫מרוצה מהתוצאה הסופית שיצרתי‪.‬‬

‫‪7‬‬
Talentder - ‫אורי ריבלוב‬

‫מבנה הפרויקט \ ארכיטקטורת הפרויקט‬


https://mega.nz/file/i6pAWJaQ#3s5BVcK50UVT6Vv7mO6-6olojnEw4zuJcF4twq2Mzk4

8
Talentder - ‫אורי ריבלוב‬

‫מימוש הפרויקט‬

‫מסכי פרויקט‬
Activity_splash
‫המסך הזה הוא המסך הראשון שרואים באפלקציה הוא מסך מעבר ומסך זה נמשך שלוש‬
.‫שניות‬

‫ולאחר שלוש שניות האפלקציה בודקת האם ישנו מידע שנשמר על ידי המשתמש הקודם‬
: shared Preference ‫באפלקציה באמצעות‬

SharedPreferences settings = getSharedPreferences("details1",0);


String mail = settings.getString("Mail","");
String password = settings.getString("Password","");

:‫ האפלקציה בודקת האם המידע אינו ריק‬Shared Preference -‫לאחר קבלת המידע מה‬

if(!mail.isEmpty()&&!password.isEmpty()&&((ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE)).getNetworkInfo(ConnectivityMa
nager.TYPE_WIFI).isConnected()) {

activity_login - ‫אם המידע ריק אז האפליקציה עוברת למסך ה‬

Intent intent = new Intent(splash.this, LogIn.class);


if(!mail.isEmpty()&&!password.isEmpty()) {
intent.setClass(splash.this, Main.class);
intent.putExtra("email",mail);
}
startActivity(intent);

9
Talentder - ‫אורי ריבלוב‬

:‫אם המידע אינו ריק אז האפלקציה מנסה להיתחבר למשתמש‬

Auth.signInWithEmailAndPassword(mail,
password).addOnCompleteListener(splash.this, new
OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Intent data = new Intent(getApplicationContext(), Main.class);
data.putExtra("email",mail);
finish();
startActivity(data);
Toast.makeText(getApplicationContext(), " ",
Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
}
});

10
Talentder - ‫אורי ריבלוב‬
activity_log_in

Firebase ‫באמצעות מסך הז משתמש יכול להתחבר לפרופיל שלו באמצעות‬

:‫המסך כולל‬

‫ – להכנסת כתובת מייל‬EditText

‫ – להכנסת סיסמא‬EditText

‫ – לסימון אם המשתמש רוצה להישאר מחובר‬CheckBox

‫ – הרשמה למערכת על ידי יצירת משתמש חדש‬Button

‫ – התחברות למערכת עם הערכים שהוזנו‬Button

: SignUp -‫כאשר לוחצים על כפתור ה‬

activity_sign_up - ‫האפלקציה עוברת ל‬

if (view == SignUp) {
Intent i = new Intent(this, sign_up.class);
startActivity(i);
}

:SignIn-‫כאשר לוחצים על כפתור ה‬

:‫בודקים שהמידע שניתן אינו ריק‬


if (!_mail.getText().toString().isEmpty() ||
!_password.getText().toString().isEmpty())

:‫אם הוא ריק מודיעים למשתמש‬


else {
Toast.makeText(getApplicationContext(), " ",
Toast.LENGTH_LONG).show();
}

: EditText -‫שומרים את הכתוב ב‬


mail = _mail.getText().toString();
pass = _password.getText().toString();

:‫ומנסים להתחבר למשתמש קיים‬

11
Talentder - ‫אורי ריבלוב‬
Auth.signInWithEmailAndPassword(mail, pass).addOnCompleteListener(this, new
OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Intent data = new Intent(getApplicationContext(),Main.class);
data.putExtra("email", mail);
data.putExtra("password", pass);
finish();
startActivity(data);
Toast.makeText(getApplicationContext(), " ",
Toast.LENGTH_LONG).show();
activity_main – ‫אם תהליך החיבור עובד מעבירים את המשתמש ל‬

:‫ מסומן אז האפלקציה שומרת את המייל והסיסמא בקובץ שישמר על המכשיר‬CheckBox – ‫ואם ה‬

if(stayConnected.isChecked()){
SharedPreferences.Editor editor = sp.edit();
editor.putString("Mail",_mail.getText().toString());
editor.putString("Password",_password.getText().toString());
editor.apply();
}

12
Talentder - ‫אורי ריבלוב‬
activity_sign_up

‫ פרופיל בסיסי זה כולל מייל סיסמא‬,‫באמצעות מסך זה יכול משתמש ליצור לעצמו פרופיל אישי באפלקציה‬
.‫ותמונה‬

:‫מסך זה כולל‬

‫ להכנסת כתובת מייל‬- EditText

‫ להכנסת סיסמא‬- EditText

‫ לסימון אם המשתמש הוא מעסיק‬- CheckBox

‫ שמראה את המתמונה שנבחרה כתמונת פרופיל‬- ImageView

‫ להוספת תמונה לפרופיל המשתמש‬- Button

‫ אישור הנתונים והשלמת התהליך‬- Button

createUser:‫ האפליקציה מריצה את הפונקציה‬submit:‫כאשר לוחצים על כפתור ה‬

if (view == submit) {
createUser();
}

:firebase ‫ויוצרת מהם משתמש ב‬-EditText ‫הפונקציה לוקחת את הערכים מה‬

String name = userName.getText().toString();


String pass = Password.getText().toString();
//
firebaseAuth.createUserWithEmailAndPassword(name.toLowerCase(),
pass).addOnCompleteListener(this,new OnCompleteListener<AuthResult>()

:‫מסומן אז המערכת יוצרת משתמש שהוא מעסיק‬-CheckBox ‫אם ה‬

if(Employer.isChecked()) {
u = new User(userName.getText().toString().toLowerCase(),
Password.getText().toString(), true); }

:‫אינו מסומן אז המערכת יוצרת משתמש רגיל‬-checkBox ‫ואם ה‬

else {u = new User(userName.getText().toString().toLowerCase(),


Password.getText().toString(),false); }

13
Talentder - ‫אורי ריבלוב‬

:ProgressDialog ‫ המשתמש רואה‬user ‫כאשר נוצר‬

p = new ProgressDialog(this);
p.setMessage("Registration...");
p.show();

: showFileChooser ‫ האפלקציה מריצה את הפונקציה‬upload Photo – ‫כאשר לוחצים על כפתור ה‬

if (view == upload_buttun) {
shwoFileChooser();
}

:‫ חדש שמטרתו להשיג תמונה מהזכרון של המכשיר‬intent ‫הפונקציה מתחילה‬

private void shwoFileChooser(){


Intent i=new Intent();
i.setType("image/*");
i.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(i,"select picture"), 100);
}

ImageView-‫ מחזירה את התמונה שנבחרה האפלקציה מכניסה את התמונה ל‬activity-‫שה‬

protected void onActivityResult(int requestCode, int resultCode, @Nullable


Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==100 && data!=null && data.getData() != null){
filePath = data.getData();
try {
imageView.setImageURI(filePath);
} catch (IOException e) {
e.printStackTrace();
}
}

14
Talentder - ‫אורי ריבלוב‬

firebase Storage - ‫ התמונה שנבחרה מהמכשיר נשמרת ב‬Button submit -‫בנוסף שלוחצים על ה‬

private void uploadFile(String name) {


if (filePath != null) {
StorageReference riversRef =
storageRef.child("profile/profilePicture");
riversRef.putFile(filePath).addOnSuccessListener(new
OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(getApplicationContext(), "Uploaded
successfully", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(getApplicationContext(), "Failed " +
e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}

15
Talentder - ‫אורי ריבלוב‬

activity_main
:‫המסך הראשי של האפלקציה אשר כולל‬

‫ – מראה את הלוגו של האפלקצייה‬ImageView

:‫ – שמוביל לצאטים של המשתמש הנוכחי‬Button

if(view ==Chat){
Intent i = new Intent(this,MyChats.class);
startActivity(i);
}

:‫ – שמוביל לפרופיל של המשתמש הנוכחי‬Button

:shared Preference – ‫ – שמנתק את המשתמש הנוכחי ומוחק את המידע השמור ב‬Button

if(view == Log_Out){
finish();
SharedPreferences settings = getSharedPreferences("details1",0);
settings.edit().remove("Mail").apply();
settings.edit().remove("Password").apply();
Intent i = new Intent(this,splash.class);
startActivity(i);
}

‫ – שמוביל למסך שבו המשתמש יכול לצפות בעבודות פוטנציאליות‬Button

if(view == ExploreJobs){
Intent i = new Intent(this, Job_Browser.class);
startActivity(i);
}

16
Talentder - ‫אורי ריבלוב‬

:‫אם המשתמש הנוכחי הואר מעסיק אז‬,‫ – שמוביל לפרופיל של המשתמש הנוכחי‬Button

//direct to Employer user page


if(u.isEmployer()){
Intent i = new Intent(getApplicationContext(),
Company_Profile_page.class);
i.putExtra("email", getIntent().getStringExtra("email"));
i.putExtra("password", getIntent().getStringExtra("password"));
startActivity(i);
}

:‫ואם ההמשתמש הוא מחפש עבודה אז‬

//direct to normal user page


else {
Intent i = new Intent(getApplicationContext(), Profile_page.class);
i.putExtra("email", getIntent().getStringExtra("email"));
i.putExtra("password", getIntent().getStringExtra("password"));
startActivity(i);
}

:menu ‫אפשר להשתמש בכל הכפתורים האלו באמצעות‬

//fill menu with menu_main


public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.menu_main,menu);
return true;
}

17
Talentder - ‫אורי ריבלוב‬

activity_profile_page
:‫מסך פרופיל של משתמש רגיל אשר כולל‬

:‫ אשר מכיל את תמונת הפרופיל של המשתמש‬ImageView

StorageReference storageRef = FirebaseStorage.getInstance()


.getReference(email.getText().toString()).child("pro-
file").child("profilePicture");
storageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>()
{
@Override
public void onSuccess(Uri uri) {
Picasso.get().load(uri).into(UserImage);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {}
});

.‫ המדינה והעיר והשם של המשתמש‬,‫ מספר הטלפון‬,‫ אשר מכילים את מייל‬EditText

myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot:snapshot.getChildren()){
if
((dataSnapshot.child("mail").getValue().toString().toLowerCase()).equals(fire
baseAuth.getCurrentUser().getEmail().toString().toLowerCase())){

phone.setText(dataSnapshot.child("phone_Number").getValue().toString());

CityAndCountry.setText(dataSnapshot.child("cityAndCountry").getValue().toStri
ng());

email.setText(dataSnapshot.child("mail").getValue().toString());

name.setText(dataSnapshot.child("fullName").getValue().toString());
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {}
});

:‫ – אשר מוביל למסך של עריכת פרטי המשתמש‬Button

if (view == settings){
Intent i = new Intent(getApplicationContext(),Profile_page_edit.class);
i.putExtra("mail",email.getText().toString());
startActivityForResult(i,1);
}

18
Talentder - ‫אורי ריבלוב‬

:‫ – אשר מוביל למסך שבו אפשר לראות את הקורות חיים של המועמד‬Button

if(view==MyResume){
Intent i = new Intent(this,ResumeViewer.class);
i.putExtra("ResumeEmail",email.getText().toString());
startActivity(i);
}
:‫ במסך‬editText -‫שהמשתמש חוזר מהמסך של עריכת הפרופיל האפלקציה מעדכנת את ה‬

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==1){
if (resultCode== Activity.RESULT_OK){
name.setText(data.getStringExtra("fullName"));
email.setText(data.getStringExtra("Mail"));
CityAndCountry.setText(data.getStringExtra("CityAndCountry"));
phone.setText(data.getStringExtra("phoneNumber"));
}
}
}

19
Talentder - ‫אורי ריבלוב‬
activity_profile_page_edit
:‫ המסך כולל‬,‫מסך זה מאפשר למשתמש לערוך את פרטי המשתמש שלו‬

‫ שמראה את המייל של המשתמש נוכחי‬TextView

‫ שמאפשרים לערוך את השם המיקום ומספר הטלפון של המשתמש‬EditText

‫ הקודם‬activity - ‫ ששומר את השינויים במידע על המשתמש וחוזר ל‬Button

if (view == SaveChanges) {
saveChanges();
Intent returnIntent = new Intent();
returnIntent.putExtra("Mail", Mail.getText().toString());
returnIntent.putExtra("fullName", Full_Name.getText().toString());
returnIntent.putExtra("CityAndCountry",
CityAndCountry.getText().toString());
returnIntent.putExtra("phoneNumber", phoneNumber.getText().toString());
setResult(Activity.RESULT_OK, returnIntent);
finish();
}

private void saveChanges() {


String Name = Full_Name.getText().toString();
String Location = CityAndCountry.getText().toString();
String PhoneNumber = phoneNumber.getText().toString();
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
if
((dataSnapshot.child("mail").getValue().toString().toLowerCase()).equals(fire
baseAuth.getCurrentUser().getEmail().toString().toLowerCase())) {
if (!PhoneNumber.isEmpty())

myRef.child(mailRefactor(dataSnapshot.child("mail").getValue().toString()))
.child("phone_Number").setValue(PhoneNumber);
if (!Location.isEmpty())

myRef.child(mailRefactor(dataSnapshot.child("mail").getValue().toString()))
.child("cityAndCountry").setValue(Location);
if (!Name.isEmpty())

myRef.child(mailRefactor(dataSnapshot.child("mail").getValue().toString()))
.child("fullName").setValue(Name);
}}}
@Override
public void onCancelled(@NonNull DatabaseError error) {}});}

20
Talentder - ‫אורי ריבלוב‬

:‫ – שמוחק את הקורות חיים של המשתמש הנוכחי‬Button

if(view == removeResume){

// Here we are initialising the progress dialog box


dialog = new ProgressDialog(this);
dialog.setMessage("Deleting");

// this will show message uploading


// while pdf is uploading
dialog.show();
StorageReference storageReference =
FirebaseStorage.getInstance().getReference();
// Here we are uploading the pdf in firebase storage with the name of
current time
final StorageReference filepath =
storageReference.child(firebaseAuth.getCurrentUser().getEmail().toString() +
"." + "pdf");
Toast.makeText(Profile_page_edit.this, filepath.getName(),
Toast.LENGTH_SHORT).show();

filepath.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void unused) {
Toast.makeText(Profile_page_edit.this, "Deleting Complete",
Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(Profile_page_edit.this, "Deleting Failed",
Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});

:‫ שמאפשר למשתמש להוסיף לפרופיל שלו קורות חיים‬Button

if (view == addResume) {
Intent galleryIntent = new Intent();
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("application/pdf");
startActivityForResult(galleryIntent, 1);
}

21
Talentder - ‫אורי ריבלוב‬
protected void onActivityResult(int requestCode, int resultCode, @Nullable
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
// Here we are initialising the progress dialog box
dialog = new ProgressDialog(this);
dialog.setMessage("Uploading");

// this will show message uploading


// while pdf is uploading
dialog.show();
imageuri = data.getData();
StorageReference storageReference =
FirebaseStorage.getInstance().getReference();
Toast.makeText(Profile_page_edit.this, imageuri.toString(),
Toast.LENGTH_SHORT).show();
// Here we are uploading the pdf in firebase storage with the name of
current time
final StorageReference filepath =
storageReference.child(firebaseAuth.getCurrentUser().getEmail().toString() +
"." + "pdf");
Toast.makeText(Profile_page_edit.this, filepath.getName(),
Toast.LENGTH_SHORT).show();
filepath.putFile(imageuri).continueWithTask(new Continuation() {
@Override
public Object then(@NonNull Task task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return filepath.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
@Override
public void onComplete(@NonNull Task<Uri> task) {
if (task.isSuccessful()) {
// After uploading is done it progress
// dialog box will be dismissed
dialog.dismiss();
Uri uri = task.getResult();
String myurl;
myurl = uri.toString();
Toast.makeText(Profile_page_edit.this, "Uploaded
Successfully", Toast.LENGTH_SHORT).show();
} else {
dialog.dismiss();
Toast.makeText(Profile_page_edit.this, "UploadedFailed",
Toast.LENGTH_SHORT).show();
}
}
});
}
}

22
‫אורי ריבלוב ‪Talentder -‬‬

‫‪23‬‬
Talentder - ‫אורי ריבלוב‬
activity_resume_viewer
:pdf ‫המסך הזה מאפשר לראות את הקורות חיים של המשתמש כקובץ‬

storageReference.getStream().addOnSuccessListener(new OnSuccessLis-
tener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onSuccess(StreamDownloadTask.TaskSnapshot taskSnapshot) {
pdfView.fromStream(taskSnapshot.getStream()).load();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {}
});

" AndroidPdfViewer":‫ באפלקציה השתמשתי בספרייה שנקראת‬pdf ‫בשביל לאפשר צפייה בקבצי‬
:‫" אשר נראה ככה‬PDFView" :‫ אלמנט בשם‬XML‫ספרייה זאת נותנת למתכנת להוסיף ל‬

<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

24
Talentder - ‫אורי ריבלוב‬

activity_company_Profile_page
:‫המסך הזה מאפשר לראות מידע על חשבון של מעסיק והוא כולל‬

.‫ מספר טלפון והסבר קצר על החברה‬,‫ מייל‬,‫ שם חברה‬:‫ של‬TextView

.‫ של הלוגו של החברה‬ImageView

StorageReference storageRef = FirebaseStorage.getInstance()


.getReference().child(Email.toLowerCase())
.child("profile").child("profilePicture");

storageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>()
{
@Override
public void onSuccess(Uri uri) {

Picasso.get().load(uri).into(UserImage);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {

Toast.makeText(getApplicationContext(),"SHIT",Toast.LENGTH_SHORT).show();
}
});

‫ שמאפשר לערוך את המידע על החברה‬Button

if (view == settings){
Intent i = new
Intent(getApplicationContext(),Company_Profile_edit.class);
i.putExtra("mail",email.getText().toString());
startActivityForResult(i,1);
}

‫ שמוביל למסך שמראה את כל המשרות של אותה חברה‬Button

Intent i = new Intent(this, Company_Browse_jobs.class);


i.putExtra("mail",email.getText().toString());
startActivity(i);

25
‫אורי ריבלוב ‪Talentder -‬‬

‫‪26‬‬
Talentder - ‫אורי ריבלוב‬
activity_company_profile_edit
‫המסך מאפשר לערוך מידע על משתמש של חברה וכולל‬

.‫ מספר טלפון והסבר קצר על החברה‬,‫ שם חברה‬:‫ שדרכם אפשר לערוך את‬- EditText

‫ – שמראה את המייל של החברה‬TextView

‫ – שמראה את הלוגו של החברה‬ImageView

StorageReference storageRef = FirebaseStorage.getInstance().getReference()


.child(getIntent().getStringExtra("mail").toLowerCase())
.child("profile").child("profilePicture");
storageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>()
{
@Override
public void onSuccess(Uri uri) {

Picasso.get().load(uri).into(UserImage);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
}
});

‫ שמעביר למסך שדרכו אפשר להוסיף תקן עבודה לחברה‬Button

if(view == addJob){
Intent i = new Intent(this, com.example.firebaselogin.addJob.class);
i.putExtra("mail",mail);
startActivity(i);
}

27
Talentder - ‫אורי ריבלוב‬

‫ ששומר את השינויים במידע על החברה‬Button

if(view==settings)
{
saveChanges();
Intent returnIntent = new Intent();
returnIntent.putExtra("Mail",Mail.getText().toString());
returnIntent.putExtra("Phone",Phone.getText().toString());
returnIntent.putExtra("CompanyName",CompanyName.getText().toString());
returnIntent.putExtra("CompanyDescription",CompanyDescription.getText().toStr
ing());
setResult(Activity.RESULT_OK,returnIntent);
finish();
}
private void saveChanges(){
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot:snapshot.getChildren()){
if
((dataSnapshot.child("mail").getValue().toString().toLowerCase()).equals(fire
baseAuth.getCurrentUser().getEmail().toString().toLowerCase())){
if (!Phone.getText().toString().isEmpty())

myRef.child(mailRefactor(dataSnapshot.child("mail").getValue().toString()))

.child("phone_Number").setValue(Phone.getText().toString());
if (!CompanyDescription.getText().toString().isEmpty())

myRef.child(mailRefactor(dataSnapshot.child("mail").getValue().toString()))

.child("companyDescription").setValue(CompanyDescription.getText().toString()
);
if (!CompanyName.getText().toString().isEmpty())

myRef.child(mailRefactor(dataSnapshot.child("mail").getValue().toString()))

.child("companyName").setValue(CompanyName.getText().toString());

}
}
}

@Override
public void onCancelled(@NonNull DatabaseError error) {

}
});
}

28
‫אורי ריבלוב ‪Talentder -‬‬

‫‪29‬‬
Talentder - ‫אורי ריבלוב‬

activity_add_job
:‫ המסך כולל‬.‫המסך מאפשר למשתמש של חברה להוסיף משרות‬

‫ שכר מצופה‬,‫ דרישות משרה‬,‫ מיקום‬,‫ הסבר על המשרה‬,‫ שם משרה‬:‫ – של‬EditText

:‫ – ששומר את המידע שהמשתמש מלא ומוסיף אותו למידע על המשתמש‬Button

if(view == submit){
jobtitle = jobTitle.getText().toString();
jobdescription = jobDescription.getText().toString();
joblocation = jobLocation.getText().toString();
jobrequairments = jobRequairments.getText().toString();
expectedsalary = ExpectedSalary.getText().toString();

if(!jobtitle.isEmpty()){
if(!jobdescription.isEmpty()){
if(!joblocation.isEmpty()){
if(!jobrequairments.isEmpty()){
if(!expectedsalary.isEmpty()){
tempJob.setTitle(jobtitle);
tempJob.setDescription(jobdescription);
tempJob.setLocation(joblocation);
tempJob.setRequirements(jobrequairments);
tempJob.setExpected_salary(expectedsalary);

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child("jo
bs").child(String.valueOf(jobCount)).setValue(tempJob);

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child(("j
obCount")).setValue(jobCount+1);
jobCount++;
System.out.println("job ADDEd");
finish();
finish();
}
}
}
}
}
}

30
‫אורי ריבלוב ‪Talentder -‬‬

‫‪31‬‬
Talentder - ‫אורי ריבלוב‬

activity_job_view
:‫המסך הזה מאפשר לראות מידע על משרה מסוימת וכולל‬

‫ דרישות ושכר משוער‬,‫ מיקום‬,‫ תיאור המשרה‬,‫ שם המשרה‬:‫ – של מידע על‬TextView

‫ – שמעביר למסך הצאט בין המשתמש לחברה‬Button

if(v==Chat){
Intent I =new Intent(this,Chat.class);
I.putExtra("SentEmail",current.getStringExtra("email"));
startActivity(I);
}

:‫ – שנמעביר למסך הפרופיל של החברה‬Button

if(v==companyPage){
Intent I =new Intent(this,Company_Profile_page.class);
I.putExtra("email",current.getStringExtra("email"));
startActivity(I);
}

32
Talentder - ‫אורי ריבלוב‬

activity_company_browse_jobs
. ListView ‫ וכולל‬,‫המסך מאפשר לראות את כל המשרות שאותה חברה מציעה‬

:‫האפלקציה עוברת על כל המשרות שיש לאותה חברה להציע ומוסיפה אותה לרשימה‬

myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot:snapshot.getChildren()){
if
((dataSnapshot.child("mail").getValue().toString().toLowerCase())

.equals(getIntent().getStringExtra("mail").toLowerCase()))
{

DataSnapshot tempDataSnapshot =
dataSnapshot.child("jobs");
for (DataSnapshot dataSnapshot1 :
tempDataSnapshot.getChildren()){
temp = dataSnapshot1.getValue(job.class);
jobList.add(temp);
}
}
}
}

@Override
public void onCancelled(@NonNull DatabaseError error) {

}
});

: ‫ בשביל לבנות את הרשימה‬jobAdapter ‫לאחר מכן השתמשתי ב‬

jobAdapter = new JobAdapter( this,0,0,jobList);


lv.setAdapter(jobAdapter);

33
Talentder - ‫אורי ריבלוב‬

: jobView ‫ ברשימה הוא עובר למסך של‬jobs - ‫כאשר המשתמש לוחץ על כל אחד מה‬

Intent i = new Intent(this,Job_View.class);


lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int
position, long id) {
temp = jobAdapter.getItem(position);
i.putExtra("Title",temp.getTitle().toString());
i.putExtra("Location",temp.getLocation().toString());
i.putExtra("description",temp.getDescription().toString());
i.putExtra("requirements",temp.getRequirements().toString());
i.putExtra("Expected_salary",temp.getExpected_salary().toString());
jobAdapter.notifyDataSetChanged();
startActivity(i);
}
});

34
‫אורי ריבלוב ‪Talentder -‬‬

‫‪chats_users_layout‬‬
‫המסך הזה ישומש בהמשך בתוך‪ , activity_my_chats:‬כאשר כל אחד ממנו מייצג צאט קיים של משתמש‬
‫נוכחי עם משתמש אחר‪.‬‬

‫המסך כולל רק ‪ TextView‬שמתאר את המייל של השמתמש השני שיש איתו צאט פעיל‬

‫‪35‬‬
Talentder - ‫אורי ריבלוב‬
activity_my_chats
:‫ המסך כולל‬,‫במסך זה יכול משתמש לראות את כל הצאטים הפעילים שלו‬

My Chats :‫ – שעליו כתוב‬TextView

chats_users_layout - ‫ שכולל רשימה של‬- ListView

-‫האפלקציה טוענת את כל הצאטים הפעילים בכך שהיא עוברת על המידע ששמור על המשתמש הנוכחי ב‬
:‫ ומוסיפה את כל המיילים שהמשתמש הנוכחי שלח להם הודעה ושמשתמשים שלחו לו הודעה‬firebase

myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot:snapshot.getChildren()) {
DataSnapshot dataSnapshot1 = dataSnapshot.child("MessageSent");
//get all the emails that have chat with current user
for (DataSnapshot dataSnapshot2 : dataSnapshot1.getChildren()) {
MailsList.add(dataSnapshot2.child("sentEmail").get-
Value().toString());
MailsList.add(dataSnapshot2.child("sentEmail").get-
Value().toString());
}
}

:‫ואז האפלקציה מורידה מהרשימה את כל הערכים הכפולים ואת המייל של המשתמש הנוכחי‬

Set<String> s = new LinkedHashSet<String>(MailsList);


MailsList.clear();
MailsList.addAll(s);
MailsList.remove(firebaseAuth.getCurrentUser().getEmail().toString());

:‫ויוצרת רשימה של משתמשים לפי המיילים‬

for (String i: MailsList) {


temp = new User(i);
UsersList.add(temp);
}

:‫ מתמלה ברשימת המשתמשים‬ListView –‫ואז ה‬

UsersAdapter = new UsersAdapter(this,0,0,UsersList);


lv.setAdapter(UsersAdapter);

36
Talentder - ‫אורי ריבלוב‬
‫וכאשר לוחצים על כל אחד מהפריטים ברשימה האפלקציה מעבירה את המשתמש לצאט עם המשתמש שעליו‬
:‫לחץ‬

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int
position, long id) {
temp = UsersAdapter.getItem(position);
I.putExtra("SentEmail",temp.getMail());
startActivity(I);
}
});

37
‫אורי ריבלוב ‪Talentder -‬‬
‫‪message_layout‬‬
‫המסך הזה ישומש בהמשך בתוך‪ , activity _chat:‬כאשר כל אחד ממנו מייצג הודעה של המשתמש נוכחי עם‬
‫משתמש אחר‪ .‬וכולל‪:‬‬

‫‪ TextView‬שכולל את המייל של שולח ההודעה‬

‫‪ TextView‬שכולל את תוכן ההודעה‬

‫‪38‬‬
Talentder - ‫אורי ריבלוב‬
activity_chat
:‫ והוא כולל‬,‫דרך מסך זה יכול המשתמש לשלוח הודעה למשתמש אחר‬

‫ – שדרכו המשתמש מזין את הטקסט שהוא רוצה לשלוח‬EditText

‫ – שכאשר לוחצים עליו הטקסט נשלח‬ImageView

‫ – שתוכנו הוא המייל של נמען ההודעות‬TextView

‫ – שדרכו רואים את ההודעות שנשלחו בין המשתמשים‬ListView

:‫בפתיחת המסך האפלקציה טוענת את כל ההודעות בין שני המשתמשים לרשימה‬

myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren())
if ((dataSnapshot.child("mail").getValue().toString().toLower-
Case())
.equals(firebaseAuth.getCurren-
tUser().getEmail().toString().toLowerCase())) {
Long I = (Long) (dataSnapshot.child("messageCount").get-
Value());
currentMessageCount = I.intValue();
DataSnapshot tempDataSnapshot = dataSnapshot.child("Messag-
eSent");
for (DataSnapshot dataSnapshot1 : tempDataSnap-
shot.getChildren()){
if((dataSnapshot1.child("sentEmail").get-
Value().toString()).equals(SentEmail)){
Message temp = new Message(dataSnap-
shot1.child("text").getValue().toString(),
firebaseAuth.getCurren-
tUser().getEmail().toString(),
dataSnapshot1.child("sentEmail").get-
Value().toString());
MessageList.add(temp);

}
}
}
}

@Override
public void onCancelled(@NonNull DatabaseError error) {

}
});

39
Talentder - ‫אורי ריבלוב‬

myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren())
if
((dataSnapshot.child("mail").getValue().toString().toLowerCase())
.equals(SentEmail.toLowerCase())) {
DataSnapshot tempDataSnapshot =
dataSnapshot.child("MessageSent");

for (DataSnapshot dataSnapshot1 :


tempDataSnapshot.getChildren()){

if((dataSnapshot1.child("sentEmail").getValue().toString())

.equals(firebaseAuth.getCurrentUser().getEmail().toString())){
Message temp = new
Message(dataSnapshot1.child("text").getValue().toString(),

dataSnapshot1.child("sentEmail").getValue().toString(),

firebaseAuth.getCurrentUser().getEmail().toString());
MessageList.add(temp);
}
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {}});

‫ של ההודעה‬Timestamp-‫ולאחר מכך מסדרת את הרשימה לפי ה‬

Collections.sort(MessageList, new Comparator<Message>() {


@Override
public int compare(Message o1, Message o2) {
return o1.getTimestamp().compareTo(o2.getTimestamp());
}
});

:‫ ברשימה של ההודעות‬ListView - ‫ואזה ממלאת את ה‬

messageAdapter = new MessageAdapter(this,0,0,MessageList);


lv.setAdapter(messageAdapter);

40
Talentder - ‫אורי ריבלוב‬
:‫כאשר לוחצים על המייל של נמען ההודעות האפלקציה מובילה לפרופיל של הנמען‬

if(isCurrentCompany) {
Intent i = new Intent(this, Profile_page.class);
i.putExtra("mail", Name.getText().toString());
startActivity(i);
}
else{
Intent i = new Intent(this, Company_Profile_page.class);
i.putExtra("email", Name.getText().toString());
i.putExtra("code",1);
startActivity(i);

‫ הודעה חדשה בתקיית‬Firebase - ‫ האפלקציה מוסיף ב‬,‫כאשר משתמש לוחץ על כפתור שליחת ההודעה‬
:‫ההודעות היוצאות של המשתמש‬

if(view == sendMessege){
//add to List View
String text = text_to_send.getText().toString();
Message temp = new
Message(text,firebaseAuth.getCurrentUser().getEmail().toString(),SentEmail);
MessageList.add(temp);
messageAdapter = new MessageAdapter(this,0,0,MessageList);
lv.setAdapter(messageAdapter);
text_to_send.setText("");

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child("me
ssageCount").setValue(currentMessageCount+1);

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child("Me
ssageSent").child(String.valueOf(currentMessageCount+1)).setValue(temp);
}

41
Talentder - ‫אורי ריבלוב‬

activity_job_browser
:‫ המסך כולל‬,‫דרך מסך זה יכול המשתמש לחפש עבודות פוטנצאליות‬

‫ – שמראה למשתמש את כל העבודות הפואנצאליות‬ListView

:‫ראשית האפלקציה מוסיפה את כל המשרות לרשימה‬

myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot:snapshot.getChildren()){
DataSnapshot tempDataSnapshot = dataSnapshot.child("jobs");
for (DataSnapshot dataSnapshot1 :
tempDataSnapshot.getChildren()){
temp = dataSnapshot1.getValue(job.class);
jobList.add(temp);
Toast.makeText(Job_Browser.this, temp.toString(),
Toast.LENGTH_SHORT).show();
}
}
}

@Override
public void onCancelled(@NonNull DatabaseError error) {

}
});

:ListView -‫ואז מציגה אותם ב‬

jobAdapter = new JobAdapter( this,0,0,jobList);


lv.setAdapter(jobAdapter);

42
Talentder - ‫אורי ריבלוב‬

: JobView - ‫ האליקציה עוברת ל‬ListView ‫כל פעם שלוחצים על אחד מהאלמנטים ב‬

Intent i = new Intent(this,Job_View.class);


lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int
position, long id) {
temp = jobAdapter.getItem(position);
i.putExtra("Title",temp.getTitle().toString());
i.putExtra("Location",temp.getLocation().toString());
i.putExtra("description",temp.getDescription().toString());
i.putExtra("requirements",temp.getRequirements().toString());
i.putExtra("Expected_salary",temp.getExpected_salary().toString());
startActivity(i);
}
});

:menu ‫ באצעות‬CSV-‫ וגם כ‬Excel-‫האפלקציה גם מאפשרת למשתמש לייצא את רשימת המשרות גם כ‬

Job_browser_fliter.xml:

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
app:showAsAction="never"
android:title="save as Excel"
android:id="@+id/DownloadExcel"
android:orderInCategory="100"
/>
<item
app:showAsAction="never"
android:title="save as CSV"
android:id="@+id/DownloadCSV"
android:orderInCategory="200"
/>

</menu>

43
Talentder - ‫אורי ריבלוב‬
:‫ האפלקצייה מבקשת רשות לכתיבה בזכרון המכשיר ואז יוצרת את הקובץ‬Excel-‫בשביל להוריד את קובץ ה‬

if (id == R.id.DownloadExcel) {

ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE},
PackageManager.PERMISSION_GRANTED);

File filePath = new


File(Environment.getExternalStorageDirectory().toString(),
"Download/jobs.xls");

Workbook workbook = new HSSFWorkbook();


Sheet sheet = workbook.createSheet("Jobs");
Row row = sheet.createRow(0);
row.createCell(0).setCellValue("Title");
row.createCell(1).setCellValue("Location");
row.createCell(2).setCellValue("description");
row.createCell(3).setCellValue("requirements");
row.createCell(4).setCellValue("Expected_salary");
int j = 1;
for (int i = 0; i < jobList.size(); i++) {
Row Row = sheet.createRow(j);
Row.createCell(0).setCellValue(jobList.get(i).getTitle());
Row.createCell(1).setCellValue(jobList.get(i).getLocation());
Row.createCell(2).setCellValue(jobList.get(i).getDescription());
Row.createCell(3).setCellValue(jobList.get(i).getRequirements());
Row.createCell(4).setCellValue(jobList.get(i).getExpected_salary());
j++;

try {
filePath.createNewFile();

FileOutputStream fileOutputStream = new FileOutputStream(filePath);


workbook.write(fileOutputStream);
System.out.println("job list has been downloaded");

if (fileOutputStream != null) {
fileOutputStream.flush();
fileOutputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}

44
Talentder - ‫אורי ריבלוב‬

: CSV ‫וישנה גם אפשרות להוריד המשרות בתור קובץ‬

if (id == R.id.DownloadCSV) {

List<String[]> csvData = new ArrayList<>();


for (int i = 0; i < jobList.size(); i++) {
String[]temp = new String[5];
temp[0]=(jobList.get(i).getTitle());
temp[1]=(jobList.get(i).getLocation());
temp[2]=(jobList.get(i).getDescription());
temp[3]=(jobList.get(i).getRequirements());
temp[4]=(jobList.get(i).getExpected_salary());
csvData.add(temp);
}

// default all fields are enclosed in double quotes


// default separator is a comma
try (CSVWriter writer = new CSVWriter(new
FileWriter(Environment.getExternalStorageDirectory()+"/Download/jobs.csv")))
{

System.out.println(Environment.getExternalStorageDirectory()+"/Download/jobs.
csv");
writer.writeAll(csvData);
//writer.close();
} catch (IOException e) {
e.printStackTrace();
}

"Technical Customer Support Associate","Remote","Providing prompt, efficient,


detailed service by engaging directly with Blink’s customers via phone and
email","1+ years of experience in technical support that is focused first and
foremost in customer success","70k"
"Amazon Fresh Grocery Associate","1701 S Commons, Federal Way, WA","Operating
the cash register in a fun, efficient and trustworthy manner","Candidates
must be at least 18 years of age.","$18.30/hour"
"Amazon Warehouse Team Member","Lebanon, TN","Become part of the dedicated
team that gets orders ready for people relying on Amazon’s
service","Candidates must be 18 years or older with ability to read and speak
English for safety.","$17.50/hr"
"Senior Product Designer","Seattle, USA","Senior Product Designer","2 years
of Experiance","90K"

45
‫אורי ריבלוב ‪Talentder -‬‬

‫‪46‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫‪activity_internet_problem‬‬
‫המשתמש יופנה למסך זה כאשר יתבררר כי מכשירו אינו מחובר לאינטרנט‪ ,‬מכיוון שלא חיבור לאינטרנט אי‬
‫אפשר להשתמש באפלקצייה‪ ,‬המסך כולל רק כפתור אחד שכאשר לוחצים אליו האפלקציה בודקת אם ישנו‬
‫חיברו אינטרנטי ועם יש האפלקציה חוזרת למסך הקודם‪:‬‬

‫{)‪if(v == reset‬‬
‫;)‪ServiceManager s = new ServiceManager(this‬‬
‫;)(‪NetworkChangeReceiver n = new NetworkChangeReceiver‬‬
‫))(‪if(String.valueOf(s.isNetworkAvailable‬‬
‫{))‪.equals("true")&&n.checkInternet(this‬‬
‫;)(‪finish‬‬
‫}‬

‫}‬

‫‪47‬‬
Talentder - ‫אורי ריבלוב‬
‫מחלקות‬
ServiceManager.java
‫ כאשר המשתמש רוצה לבצע כל‬,‫קלאס זה משומש בכדי לבדוק את המצב של החיבור האינטרנטי של המכשיר‬
‫ אם יש חיבור אינטרנטי אז האפלקציה‬,‫פעולה באפלקציה האפלקציה בודקת האם ישנו חיבור אינטרנטי‬
activity_internet_problem.xml :‫ממשיכה בתוכנית אבל אם אין חיבור אינטרנטי אז האפליקציה עוברת ל‬

:‫האפלקציה בודקת האם ישנו חיבור אינטרנטי בדרך הבאה‬

public boolean isNetworkAvailable() {


ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}

48
Talentder - ‫אורי ריבלוב‬
NetworkChangeReceiver.java
‫ בכדי‬reset :‫ בכאשר המשתמש לוחץ על כפתור ה‬activity_internet_problem.xml ‫קלאס זה משומש בתוך‬
:‫לבדוק האם ישנו חיבור אינטרנטי בצורה הבאה‬

boolean checkInternet(Context context) {


ServiceManager serviceManager = new ServiceManager(context);
return serviceManager.isNetworkAvailable();
}

49
‫אורי ריבלוב ‪Talentder -‬‬

‫‪Message.java‬‬
‫מחלקה זו מתארת הודעה בין שני אנשים באפלקציה הכולל‪:‬‬

‫‪ – text‬תוכן ההודעה‬

‫‪ – FromEmail‬המייל של המשתמש שממנו נשלחה ההודעה‬

‫‪ – SentEmail‬המייל של המשתמש שאליו נשלחה ההודעה‬

‫‪ – timestamp‬אשר הוא אובייקט שמתאר את זמן שליחת ההודעה ובנוי כך‪:‬‬

‫‪50‬‬
‫אורי ריבלוב ‪Talentder -‬‬
‫‪Job.java‬‬
‫מחלקה זו מתארת משרה והיא כוללת‪:‬‬

‫‪ – Title‬שם המשרה‬

‫‪ – Location‬מיקום המשרה‬

‫‪ – description‬תיאור המשרה‬

‫‪ – requirements‬דרישות המשרה‬

‫‪ – Expected_salary‬שכר משוער‬

‫‪ – email‬המייל של יוצר המשרה‬

‫‪ – companyName‬שם החברה שעליה משוייכת המשרה‬

‫‪51‬‬
‫אורי ריבלוב ‪Talentder -‬‬
‫‪User.java‬‬
‫האובייקט כולל את הערכים המתאימים גם לחשבון פרטי וגם לחשבון חברה והוא כולל‪:‬‬

‫‪ – mail‬מייל המשתמש‬

‫‪ – pass‬סיסמת המשתמש‬

‫‪ – phone_Number‬מספר הפלפון של המשתמש‬

‫‪ – cityAndCountry‬המיקום של המשתמש‬

‫‪ – fullname‬שם מלא של המשתמש‬

‫‪ – ArrayList<job>jobs‬רשימה של משרות של אותו מעסיק‬

‫‪ – isEmployer‬האם המשתמש הוא מעסיק‬

‫‪ – companyDescription‬תיאור החברה‬

‫‪ – companyName‬שם חברה‬

‫‪ – jobCount‬סופר את מספר המשרות של אותה חברה‬

‫‪ – ArrayList<Message>MessageSent‬רשימת ההודעות שנשלחו מהמשתמש‬

‫‪ - int MessageCount‬סופר את מספר ההודעות שנשלחו מהמשתמש‬

‫‪52‬‬
Talentder - ‫אורי ריבלוב‬
jobAdapter.java
activity_company_browse_jobs.xml ‫ ו‬activity_job_browser.xml ‫המחלקה הזאתי משומשת ב‬

:‫ והוא כולל‬ListView - ‫בכדי להכניס את רשימת המשרות לתוך‬

Firebase ‫ – חיבור למערכת המשתמשים של‬FireBaseAuth

‫ – מיקום בתוך הפרויקט‬context

ListView-‫ – רשימת המשרות שיטענו לתוך ה‬List<job>objects

53
‫אורי ריבלוב ‪Talentder -‬‬

‫‪UserAdapter.java‬‬
‫מחלקה זו משומשת ב–‪ activity_my_chats.xml‬בכדי לטעון את רשימת המשתמשים לתוך ‪ ListView‬וכולל‪:‬‬

‫‪ – FireBaseAuth‬חיבור למערכת המשתמשים של ‪Firebase‬‬

‫‪ – context‬מיקום בתוך הפרויקט‬

‫‪ – List<User>objects‬רשימת המשתמשים שיטענו לתוך ה‪ListView-‬‬

‫‪54‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫‪MessageAdapter.java‬‬
‫מחלקה זו משומשת ב – ‪ activity _chat.xml‬בכדי לטעון את רשימת ההודעות לתוך ‪ ListView‬וכולל‪:‬‬

‫‪ – FireBaseAuth‬חיבור למערכת המשתמשים של ‪Firebase‬‬

‫‪ – context‬מיקום בתוך הפרויקט‬

‫‪ – List<Message>objects‬רשימת המשתמשים שיטענו לתוך ה‪ListView-‬‬

‫‪55‬‬
Talentder - ‫אורי ריבלוב‬

:‫ קבצים‬+ ‫בסיס נתונים‬


FireBaseAuthentication
:‫ דרכו אני מאמת את המשתמשים שמתחברים למערכת‬.‫בסיס נתונים מטעם גוגל‬

FireBase Realtime Database


- ‫ המידע שעל המשתמש נשמר גם ב‬FireBaseAuthentication - ‫כל פעם שיוצרים משתמש חדש דרך‬
: FireBase Realtime Database

firebaseAuth.createUserWithEmailAndPassword(name.toLowerCase(),
pass).addOnCompleteListener(this,new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
User u;
// User
if(Employer.isChecked()) {
u = new User(userName.getText().toString().toLowerCase(),
Password.getText().toString(), true); }
else {u = new User(userName.getText().toString().toLowerCase(),
Password.getText().toString(),false); }
myref.child(mailRefactor(u.getMail())).setValue(u);
storageRef = storage.getReference(name.toLowerCase());
uploadFile(userName.getText().toString());
finish();
Toast.makeText(sign_up.this, " !",
Toast.LENGTH_LONG).show();

}
}

: FireBase‫כל פעם שנשלחת הודעה ההודעה נוספת לרשימת ההודעות של המשתמש ב‬

56
Talentder - ‫אורי ריבלוב‬
myRef = FirebaseDatabase.getInstance().getReference("Users");
if(view == sendMessege){
//add to List View
String text = text_to_send.getText().toString();
Message temp = new
Message(text,firebaseAuth.getCurrentUser().getEmail().toString(),SentEmail);
MessageList.add(temp);
messageAdapter = new MessageAdapter(this,0,0,MessageList);
lv.setAdapter(messageAdapter);
text_to_send.setText("");

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child("me
ssageCount").setValue(currentMessageCount+1);

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child("Me
ssageSent").child(String.valueOf(currentMessageCount+1)).setValue(temp);
}

: FireBase‫כל פעם שנוספת משרה המשרה נוספת לרשימת המשרות של המשתמש ב‬

myRef = FirebaseDatabase.getInstance().getReference("Users");
if(!jobtitle.isEmpty()){
if(!jobdescription.isEmpty()){
if(!joblocation.isEmpty()){
if(!jobrequairments.isEmpty()){
if(!expectedsalary.isEmpty()){
tempJob.setTitle(jobtitle);
tempJob.setDescription(jobdescription);
tempJob.setLocation(joblocation);
tempJob.setRequirements(jobrequairments);
tempJob.setExpected_salary(expectedsalary);

tempJob.setEmail(firebaseAuth.getCurrentUser().getEmail().toString());

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child("jo
bs").child(String.valueOf(jobCount)).setValue(tempJob);

myRef.child(mailRefactor(firebaseAuth.getCurrentUser().getEmail())).child(("j
obCount")).setValue(jobCount+1);
jobCount++;
System.out.println("job ADDEd");
finish();
finish();
}
}
}
}
}

57
Talentder - ‫אורי ריבלוב‬

FireBaseStorage
‫ בפרויקט שלי השתמשתי בו בכדי לשמור תמונת פרופיל‬,‫ משמש לשמירת קבצים דרך הענן‬FireBaseStorage
.pdf ‫למשתמשים ובשביל לשמור קורות חיים כקובץ‬

:‫שמירת תמונת פרופיל‬

private void shwoFileChooser(){


Intent i=new Intent();
i.setType("image/*");
i.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(i,"select picture"), 100);
}
//this method will upload the file
private void uploadFile(String name) {
//if there is a file to upload
if (filePath != null) {
//displaying a progress dialog while upload is going on
StorageReference riversRef =
storageRef.child("profile/profilePicture");
riversRef.putFile(filePath).addOnSuccessListener(new
OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(getApplicationContext(), "Uploaded
successfully", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(getApplicationContext(), "Failed " +
e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
//if there is not any file
else {

}
}

58
Talentder - ‫אורי ריבלוב‬

: pdf – ‫שמירת קורות חיים כ‬

if (view == addResume) {
Intent galleryIntent = new Intent();
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("application/pdf");
startActivityForResult(galleryIntent, 1);
}

imageuri = data.getData();
StorageReference storageReference =
FirebaseStorage.getInstance().getReference();
// Here we are uploading the pdf in firebase storage with the name of current
time
final StorageReference filepath =
storageReference.child(firebaseAuth.getCurrentUser().getEmail().toString() +
"." + "pdf");
Toast.makeText(Profile_page_edit.this, filepath.getName(),
Toast.LENGTH_SHORT).show();
filepath.putFile(imageuri).continueWithTask(new Continuation() {
@Override
public Object then(@NonNull Task task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return filepath.getDownloadUrl();
}
})

59
‫אורי ריבלוב ‪Talentder -‬‬
‫מדריך למשתמש‬
‫הוראות התקנה‬

‫מורידים קובץ ‪ apk‬למכשיר אנדרואיד‪ ,‬לא נתמך על ידי מערכות הפעלה אחרות‪ ,‬לאחר הורדה ניתן לפתוח את‬

‫האפליקציה בלחיצה על האייקון‪.‬‬

‫האפלקציה פותחה על גבי אימולטור עם ‪API 25‬‬

‫מסכים‪:‬‬

‫בפעם הראשונה שתיכנס לאפלקציה תגיע למסך התחברות‪ ,‬עליך ללחוץ על כפתור ה ‪ SignUp‬ואז תגיע למסך‬
‫זה‪:‬‬

‫עליך למלא את כתובת המייל שלך ולהזין סיסמא‪ ,‬אם אתה רוצה ישנה אפשרות להוסיף תמונת פרופיל בכך‬
‫שתלחץ על כתפור ה – ‪ ,Uploud Photo‬כפתור זה יעביר אותך לבחירת תמונה מהזיכרון של הטלפון‪ ,‬אם אתה‬
‫מעוניין לפתוח פרופיל של חברה אנא סמן את התיבה שכתוב עליה‪ .I am Employer :‬שאתה מסיים למלא את‬
‫כל השדות אנא לחץ על כפתור ה – ‪ submit‬בכדי להמשיך בתהליך‪.‬‬

‫לאחר מכך האפלקציה תעבור חזרה למסך הפתיחה בו תידרש למלא את המייל והסיסמא שלך בכדי להתחבר‬
‫לחשבון שלך‪ ,‬אם אתה מעוניין בכך אתה יכול לסמן את התיבה – ‪ stay Connected‬אשר תגרום לכך שבפעם‬
‫הבאה שתתחבר לאפלקציה תשאר מחובר ולא תדרש למלא את המייל והסיסמא שלך מחדש‪.‬‬

‫‪60‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫לאחר מכן תגיע למסך הראשי של האפלקציה‪ ,‬שנראה ככה‪:‬‬

‫במסך זה יש לך ארבע כפתורים‪ ,‬כפתור ה ‪ Log Out‬ינתק אותך מהמשתמש שלך ויחזיר אותך למסך הקודם‪.‬‬

‫כפתור ה ‪ Explore jobs -‬יעביר אותך למסך שבו תוכל לראות משרות פוטנצאליות‪ ,‬מסך זה נראה רק‬
‫למשתמשים עם משתמש שאינו משתמש חברה‬

‫כפתור ה‪ chat -‬יעביר אותף למסך שבו תוכל לראות ולהיכנס לכל הצאטים הפעילים שלך‬

‫כפתור ה‪ Profile -‬יעביר אותך לראות את הפרופיל שלך ויתן לך אפשרות לערוך אותו‪.‬‬

‫אפשר לגשת לכל הכפתורים האלו גם באמצעות שלוש הנקודות בצד ימין למעלה של המסך‬

‫אני ממליץ בתחילת השימוש באפלקציה גם לחברות וגם למשתמשים רגילים להיכן לעמוד הפרופיל שלהם‬
‫בשביל להוסיף מידע שימושי‪ ,‬לפרופיל חברה כדי להוסיף את שם החברה‪ ,‬תיאור של החברה ומספר משרות‬
‫ולפרופיל רגיל כדי להוסיף מספר טלפון ‪,‬שם מלא וקורות חיים‪.‬‬

‫‪61‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫פרופיל משתמש יחיד‬ ‫פרופיל חברה‪:‬‬

‫מתוך דף הפרופיל אפשר לגשת לדף עריכת הפרופיל בעזרת לחיצה על גלגל השיניים בצד ימין למעלה של‬
‫המסך‪ :‬למשתמש רגיל לחיצה על כפתור זה יתן לערוך את‪ :‬מספר הטלפון‪ ,‬השם המלא‪ ,‬המיקום ולהוסיף‬
‫קורות חיים בתור קובץ ‪.pdf‬‬

‫ולמשתמש של חברה לחיצה על כפתור זה יאפשר לערוך את‪ :‬שם החברה‪ ,‬מספר הטלפון ולהוסיף משרות‬
‫לחברה‪.‬‬

‫‪62‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫לאחר עריכת הפרופיל אפשר להתחיל בחיפוש העבודה‪ ,‬באמצעות לחיצה על כפתור ה‪Explore jobs -‬‬
‫האפלקציה עוברת למסך שבו אפשר לראות משרות שחברות פרסמו‪:‬‬

‫ישנה אפשרות להוריד את המשרות בתור קובץ ‪ Excel‬או בתור קובץ‬


‫‪ CSV‬באמצעות ‪ 3‬הנקודות בצד ימין למעלה של העמוד‬

‫כאשר תלחץ על כל אחד מהמשרות תעבור לעמוד עם עוד מידע על כל משרה ועם כפתורים‪ ,‬אחד לעבוד לעמוד‬
‫הפרופיל של החברה המפרסמת ואחד לצאט עם החברה המפרסמת‪:‬‬

‫‪63‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫כאשר לוחצים על כפתור ה ‪ Chat -‬במסך הבית האפלקציה עוברת לרשימה של כל הצאטים הפעילים‪:‬‬

‫‪64‬‬
‫אורי ריבלוב ‪Talentder -‬‬

‫כאשר תלחץ על כל אחד מהפריטים ברשימה תועבר לצאט שלך עם המשתמש עם המייל המוצג‪:‬‬

‫‪65‬‬
‫אורי ריבלוב ‪Talentder -‬‬
‫רפלקציה‬
‫היעד המרכזי שלי בפרויקט היה להוציא פרויקט מוגמר שאני אוכל להיות גאה בו‪ ,‬לפי דעתי הצלחתי חלקית‬
‫במטרה שלי אני גאה מאוד בפרויקט שלי‪ ,‬כיף לדעת שבניתה משהוא בשתי ידיך אבל אני מרגיש שאם הייתי‬
‫מתחיל את הפרויקט מוקדם יותר ומקדיש אליו יותר משאבים הייתי יכול ליצור תוצר שהייתי יותר מרוצה‬
‫ממנו אבל בסך הכול אני מרוצה מאוד‪.‬‬

‫הדרך לבניית הפרויקט הזה אינה הייתה פשוטה‪ ,‬אחד הדברים שהכי הקשו עליי בפרויקט היו השעות‬
‫הארוכות אך באמצעות סבלנות והתמדה הצלחתי לצלוח את בעיה זו אבל כאשר הצלחתי לפתח פיצר הסיפוק‬
‫שקיבלתי מההצלחה היה גדול משמעותית מהתסכול וזה אחד מהסיבות שהצלחתי להתמיד‪.‬‬

‫פרויקט זה שונה מאוד מפרויקטים במקצועות אחרים‪ ,‬במקצועות אחרים רוב העבודות כוללות העתקת מידע‬
‫לעומת זאת בפרויקט הזה אחד הדברים שאני מאוד אוהב הוא העובדה שיוצרים אפלקציה מאפס בעזרת‬
‫הטמעת אלמטים שונים לתור פרויקט מלא‪.‬‬

‫ישנם מספר אפשרויות נוספות להמשך הפיתוח של התוכנה‪ ,‬אחד מהרעיונות להמשך פיתוח האפליקציה‬
‫שהייתי רוצה לעשות הוא לפתח פיצר באפלקציה שהיה מושך משרות קיימות מאתרים אחרים ולייבא את‬
‫אותם משרות לאפלקציה שלי בנוסף הייתי שמח לעצב את האפלקציה בצורה יותר יפה ‪.‬‬

‫דרך הפרויקט למדתי על עצמי שאני יכול להשיג כל מה שאני רוצה באמצעות התמדה וסבלנות‪ ,‬כלי זה יהיה לי‬
‫שימושי בהמשך החיים גם בפן האקדמי וגם בכל דבר שאני יעשה בחיי האישיים‪.‬‬

‫בסך הכול נהנתי מאוד מהתהליך של בניית האפליקציה ואני שמח מאוד על כך שבחרתי לעשות פרויקט זה‪.‬‬

‫‪66‬‬
Talentder - ‫אורי ריבלוב‬

‫ביבליוגרפיה‬
‫כפתור תמונת פרופיל עגול‬

pdf ‫התמאת קובץ‬

)‫צאט )לא בדיוק אותו דבר אבל השתמשתי בזה‬

android‫דוקומנטציה של‬

‫בדיקת חיבור לאינטרנט‬

FireBase:

Installation & Setup on Android | Firebase Documentation (google.com)

Authenticate with Firebase using Password-Based Accounts on Android | Firebase


Documentation (google.com)

Get started with Cloud Storage on Android | Firebase Documentation (google.com)

67
Talentder - ‫אורי ריבלוב‬

‫נספחים‬
:‫קטעי הקוד‬

https://github.com/oririb/FireBaseLogin

:APK ‫קובץ‬

https://mega.nz/file/Ln4jSJ6I#JbGiSumzi8baFju1xuldMNd2xb8RHDXU3JwZLKoe-Wk

:‫סקר השוק‬

https://docs.google.com/forms/d/e/1FAIpQLSfGK_rhmALJGzU-
vR5hYkO8NFI_A231Hv5nHuzPdqYsFHIRzg/viewform?usp=sf_link

68

You might also like