Raport: Ciudin S
Raport: Ciudin S
Raport: Ciudin S
Raport
Lucrare de laborator Nr.2
Tema: Organiser Mobile Application (DAILY PLANNER)
Chișinău 2017
Obiective : Dezvoltarea unui Organiser pe platforma stabilită conform condițiilor puse.
Scopul lucrării de laborator:
De realizat aplicație tip Organiser pe platforma aleasă. La formarea și proiectarea aplicațiilor sunt
introduse puncte stricte, ce sunt obligatorii de respectat. La discreția personală rămâne designul aplicației și
API-ul/Framework-ul în care va fi dezvoltată lucrarea de laborator #2. Componentele și structura fiecărei
Activități va fi descrisă mai jos.
UI Components:
Aplicația va conține minim 3 Activități de baza care vor fi numerotate în lucrare sub forma:
1. MainActivity (structura/componente)
Calendar View (custom or default)
Buttons (Add/Remove/Update)
Căutare (caută conform cuvintelor cheie)
2. AddtActivity
Data/Time controller
Info TextBoxButtons
și altele (la discreție conform specificului aplicației)
3. UpdateActivity - practic e una și aceeași activitate de la Add, doar ca completata deja.
Datele operaționale din interiorul aplicației vor fi stocate în fișier/e XML forma cărora rămâne la
discreția personală. (cuvinte cheie, XML Serialization).
Logical/Operational Component
Toate evenimentele și acțiunile de notificare/semnalizare (sonore/vizuale) intreprinse în Organiser
vor fi tratate într-un serviciu aparte, care logic funcțional va extrage datele din acel fișier XML.
Mersul lucrării
Setarea unui layout
Setarea unui calendar view
Crearea funcționalului
Setarea layout-ului
Pentru aplicația dată am creat 3 layout-uri:
Crearea aplicației
Pentru lucrarea dată de laborator au fost create 4 activități:
MainActivity [Anexa A]
AddEventActivity [Anexa B]
Au fost create 2 clase:
Events [Anexa C]
Data [Anexa D]
A fost creat un serviciu NotificationSercive [Anexa E] și un broadcast reciver
NotificationBroadcastReciver [Anexa F].
Activitatea principală (MainActivity)
Activitatea principală conține calendarul care afișează luna întreagă. Aici utilizatorul poate vizualiza în
ce zile sunt setate ceva evenimente, zilele acestea au indicatoare de eveniment, tot din această activitate se
poate efectua căutarea unui eveniment după cuvinte cheie, conform figurii 2.
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.github.sundeepk.compactcalendarview.CompactCalendarView;
import com.github.sundeepk.compactcalendarview.domain.Event;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Random;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
delete = (Button) findViewById(R.id.button_delete);
show = (Button) findViewById(R.id.button_show);
search = (Button) findViewById(R.id.button_search);
modify = (Button) findViewById(R.id.button_modify);
searchField = (EditText) findViewById(R.id.editText);
fab = (Button) findViewById(R.id.fab);
actionBar = getSupportActionBar();
actionBar.setTitle(null);
compactCalendarView = (CompactCalendarView) findViewById(R.id.compactcalendar_view);
actionBar.setTitle(dateFormatForMonth.format(compactCalendarView.getFirstDayOfCurrentMonth()))
;
currentDate = new Date();
compactCalendarView.setListener(new CompactCalendarView.CompactCalendarViewListener()
{
@Override
public void onDayClick(Date dateClicked) {
currentDate = dateClicked;
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
deleteData();
}
});
show.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showData();
}
});
}
@Override
public void onMonthScroll(Date firstDayOfNewMonth) {
actionBar.setTitle(dateFormatForMonth.format(firstDayOfNewMonth));
}
});
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
searchData(searchField);
}
});
modify.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
modifyData();
}
});
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), AddEventActivity.class);
intent.putExtra("beginDate", currentDate.getTime());
intent.setAction(ADD_EVENT_ACTION);
startActivityForResult(intent, ADD_EVENT);
}
});
refresh();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK || (resultCode == RESULT_CANCELED && requestCode ==
MODIFY_EVENT)) {
Data event = new Data();
event
.setDescription(data.getExtras().getString("description"))
.setTitle(data.getExtras().getString("title"))
.setId(new Random().nextInt(543254))
.setCalendarDate(data.getExtras().getLong("time"));
if (events == null) events = new Events();
ArrayList<Data> datas = new ArrayList<>();
if (events.getData() == null) {
events.data = datas;
}
events.data.add(event);
saveToXML();
refresh();
}
}
} else {
InputMethodManager inputManager = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
searchField.setText("");
Toast.makeText(MainActivity.this, "No events found!",
Toast.LENGTH_SHORT).show();
}
}else Toast.makeText(MainActivity.this, "No events in calendar!",
Toast.LENGTH_SHORT).show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.search) {
return true;
} else if (id == R.id.current_day) {
compactCalendarView.setCurrentDate(Calendar.getInstance(Locale.getDefault()).getTime());
actionBar.setTitle(dateFormatForMonth.format(compactCalendarView.getFirstDayOfCurrentMonth()))
;
}
return false;
}
}
Anexa B
Codul sursă (AddEventActivity)
package com.example.misha.organiser;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.DatePicker;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
return new TimePickerDialog(getActivity(), this, hour, minute,
DateFormat.is24HourFormat(getActivity()));
}
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
TextView viewById = (TextView)getActivity().findViewById(R.id.time_label);
if(minute < 10) {
viewById.setText(hourOfDay + ":0" + minute);
}
else {
viewById.setText(hourOfDay + ":" + minute);
}
calendar.set(Calendar.HOUR_OF_DAY,hourOfDay);
calendar.set(Calendar.MINUTE,minute);
calendar.set(Calendar.SECOND,0);
calendar.set(Calendar.MILLISECOND,0);
parsedDate = calendar.getTime();
}
}
private class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
return new DatePickerDialog(getActivity(), this, year, month, day);
}
public void onDateSet(DatePicker view, int year, int month, int day) {
TextView beginDateLabel = (TextView)getActivity().findViewById(R.id.date_label);
calendar.set(Calendar.YEAR,year);
calendar.set(Calendar.MONTH,month);
calendar.set(Calendar.DAY_OF_MONTH,day);
parsedDate = calendar.getTime();
beginDateLabel.setText(dateFormatForMonth.format(parsedDate));
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.add, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.cancel_button) {
Intent intent = new Intent();
if(getIntent().getAction().equals("modify")){
intent.putExtra("title", getIntent().getExtras().getString("title"));
intent.putExtra("description",getIntent().getExtras().getString("description"));
intent.putExtra("time", getIntent().getExtras().getLong("time"));
}
setResult(RESULT_CANCELED, intent);
finish();
return true;
}else if(id == R.id.save_button){
if(parsedDate != null
&& !TextUtils.isEmpty(eventTitleLabel.getText().toString())
&& !TextUtils.isEmpty(descriptionLabel.getText().toString())) {
Intent intent = new Intent();
intent.putExtra("title", eventTitleLabel.getText().toString());
intent.putExtra("description", descriptionLabel.getText().toString());
intent.putExtra("time", parsedDate.getTime());
setResult(RESULT_OK, intent);
finish();
} else Toast.makeText(AddEventActivity.this, "Enter Dates",
Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
Intent intent = new Intent();
if(getIntent().getAction().equals("modify")){
intent.putExtra("title", getIntent().getExtras().getString("title"));
intent.putExtra("description",getIntent().getExtras().getString("description"));
intent.putExtra("time", getIntent().getExtras().getLong("time"));
}
setResult(RESULT_CANCELED, intent);
finish();
super.onBackPressed();
}
}
Anexa C
Codul sursă (Events)
package com.example.misha.organiser;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import java.util.ArrayList;
@XStreamAlias("Events")
public class Events {
@XStreamImplicit(itemFieldName = "Data")
public ArrayList<Data> data;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("Remind")
private int remind;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
public NotificationService() {
super("StudentOrganizerService");
}
@Override
protected void onHandleIntent(Intent intent) {
if (UPDATE.equals(intent.getAction())) {
executeUpdate();
} else if(CANCEL.equals(intent.getAction())) {
executeCancel(intent.getExtras().getInt("requestCode"));
}
}
private void executeCancel(int requestCode){
Intent notificationIntent = new Intent(this, NotificationBroadcastReceiver.class);
notificationIntent.setAction(requestCode+"");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
private void executeUpdate() {
XStream xstream = new XStream(new DomDriver());
xstream.processAnnotations(Events.class);
xstream.processAnnotations(Data.class);
InputStream inputStream;
try {
inputStream = new FileInputStream(new File(this.getFilesDir(), "events.xml"));
events = (Events) xstream.fromXML(inputStream);
inputStream.close();
} catch (IOException ignored) {
}
if (events != null) {
for (Data data : events.data) {
Intent notificationIntent = new Intent(this,
NotificationBroadcastReceiver.class);
notificationIntent.putExtra(NotificationBroadcastReceiver.NOTIFICATION_ID,
data.getId());
notificationIntent.putExtra("title", data.getTitle());
notificationIntent.putExtra("description", data.getDescription());
notificationIntent.setAction(data.getId() + "");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, data.getId(),
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)
getSystemService(Context.ALARM_SERVICE);
Date g = new Date();
g.setTime(data.getCalendarDate());
if (new Date().before(g)) {
if(data.getRepeating() == 0) {
alarmManager.set(AlarmManager.RTC_WAKEUP, data.getCalendarDate() -
data.getRemind(), pendingIntent);
} else
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
data.getCalendarDate(), data.getRepeating() - data.getRemind(), pendingIntent);
}
}
}
}
}
Anexa F
Codul sursă (NotificationBroadcastReciver)
package com.example.misha.organiser;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import java.util.Calendar;
public class NotificationBroadcastReceiver extends BroadcastReceiver {