Ordering System Project Introduction
- Outline
- Demo
- Environment
- App Components
- Login page
- Four Fragments
- Main Fragment
- Order Fragment
- Trends Fragment
- My Fragment
- SQLite Database
- Technical Focus
- Food Showing
- Database storaging
- Recommendation Management
- Image choosing and showing
- About Tests
- Future Improvements
- Conclusion
Outline
This app, “Ordering system”, helps customers pre-order the table and some dishes as well as the exact time they may arrive at the restaurant. This is my undergraduate individual project from 15/10/2017 To 15/11/2017, and I have made some improvements afterward.
Demo
I have shown all functions of this app in this Ordering System Demo Vedio.
Ordering System
Environment
Development tool: Android studio and SQLite database in it
Language: Java and Android technology
App Components
This app contains login page and four fragments which involves many activities, let me introduce them one by one.
Login page
Detect whether the user is a new customer or an old customer. If the user is a new customer( or the first customer of the app), *** creates a new user id*** for him automatically and stores his name and password in the database, else if the name exists in the database, check whether the password is correct. If the user ticks checkbox, the system will remember the password automatically and the user can log in directly without typing the password again.
Four Fragments
Main Fragment
Main fragment involves some pages, such as main page (include start button)
Main page: this page shows some special dishes of the restaurant, the blue imageview button means “start to order”.
Table ordering page: this page includes 7 tables, initially all tables are available, but after the table has been ordered, it will show grey color, which means the user cannot order it.
Food showing page: this page shows all types of food, for example, the left menu part contains “special, main, drink, meat dish, vegetable, soup”, the right home part contains relative food. Everytime the user presses add or sub button, the number of each food will change, and the bottom of this page will show the total money. The red button in the bottom of this page means “show bill”.
Everytime the user presses the shopping car button, he can view all the food he has chosen. If he feels very expensive, he can adjust the number he have chosen.Bill showing page: this page shows after the user presses “show bill” button of the last page, he can view all the food he has ordered. After the user edits the time he arrives at the restaurant, he can submit this bill (food name, number, price) by pressing the red submit button and wait for the restaurant to accept it.
When the user presses the red button, the system will store all the bill details in the SQLite database “customer.db”, and this page shows “waiting for the restaurant to accept it!”, (note if the user presses the blue button(back to the main page), the record will not be stored), if the user waits a short period, it will show “restaurant has accepted” at last.
Order Fragment
This fragment helps the user check the bills, since one customer can preorder more than one time, when he clicks the bill, it will show the details of the bill.
Trends Fragment
This fragment allows all the customers to give their remarks to the restaurant, this fragment contains 4 elements: edit text, 3 buttons. The first button means “submit”, each customer can write down their remarks and then submit it. Since one customer can submit more than one remark, so the second button means “manage”, customers can manage(delete) their remarks. The third button means “view the remarks of other customers”, let me introduce them one by one.
Remarks submitting: After the user writes down his remark, and press the first button, the screen will show “the remark has been submitted!”
Remarks managing: After the user presses the second button, it will show all remarks, when the user presses one remark item and swipe left, “delete” button will show in his right-hand side. If he clicks this delete button, that remark will be deleted from all remarks.
Remarks viewing: When the user presses the third button, all the remarks given by all customers will show.
My Fragment
The last fragment has four main functions (buttons): Personal information management, Contact with restaurant, Software version checking and Exit.
Personal information management: This page shows the basic information of the customer, such as name, image, age and gender, when the user presses the blue button(“edit”), the user can choose his image from his own photo album and edits his age and gender (name cannot be changed)
After the user confirms the change, all the information has been changed.
Contact with restaurant, software version checking and exit
SQLite Database
The most important part is to store the customer data, such as their name, password, recommendation, ordering details, and so on, in the database.
The data detail in database: (id,name,pwd,rec,orderdetail)
The data detail in database:(age,gender,photo)
Technical Focus
Food Showing
As you can see in the food showing page, the functions are achieved by the code of FoodShowActivity.java which below mainly set up three adapters:
- Left adapter (for menu)
- Right dish home (listview of food) order adapter
- Shop car simple adapter
Orderadapter.java
Main idea: set up listeners for add or sub button and use viewholder to cope with the scrolling of the listview, which can reduce the consumption of RAM (don’t need to create many objects)
public class OrderAdapter extends BaseAdapter {
private List<DishSelect> dss = new ArrayList<>();
private Context context;
//1.set up ClickListener for sub or add button
private View.OnClickListener onAddNum;
private View.OnClickListener onSubNum;
public void setOnAddNum(View.OnClickListener onAddNum) {
this.onAddNum = onAddNum;
}
public void setOnSubNum(View.OnClickListener onSubNum) {
this.onSubNum = onSubNum;
}
public OrderAdapter(Context context) {
this.context = context;
}
public void updateData(List<DishSelect> list) {//updata data source according to the clicked left menu item
if(!dss.isEmpty()) dss.clear();
dss.addAll(list);
this.notifyDataSetChanged();
}
@Override
public int getCount() {
int ret = 0;
if (dss != null) {
ret = dss.size();
}
return ret;
}
@Override
public Object getItem(int i) {
return dss.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
View v = null;
if (view != null) {
v = view;
} else {
v = LayoutInflater.from(this.context).inflate(R.layout.food_show_listview_content, viewGroup, false);
}
ViewHolder holder = (ViewHolder) v.getTag();
if (holder == null) {
holder = new ViewHolder();
holder.item_title = (TextView) v.findViewById(R.id.title);
holder.item_img = (ImageView) v.findViewById(R.id.img_food);
holder.item_price = (TextView) v.findViewById(R.id.price);
holder.item_num = (TextView) v.findViewById(R.id.number);
//register the listeners in real layout components
holder.item_btn_add = (ImageView) v.findViewById(R.id.btn_add);
holder.item_btn_add.setOnClickListener(onAddNum);
holder.item_btn_sub = (ImageView) v.findViewById(R.id.btn_sub);
holder.item_btn_sub.setOnClickListener(onSubNum);
}
holder.item_title.setText(dss.get(i).getName());
holder.item_img.setImageResource((dss.get(i).getPic()));
holder.item_price.setText(dss.get(i).getPrice());
holder.item_num.setText(dss.get(i).getNum() + "");
//set up Tag, help locate which item of right dish home has been clicked
holder.item_btn_add.setTag(i);
holder.item_btn_sub.setTag(i);
v.setTag(holder);
return v;
}
private static class ViewHolder {
private TextView item_num;
private TextView item_title;
private ImageView item_img;
private TextView item_price;
private ImageView item_btn_add;
private ImageView item_btn_sub;
}
}
FoodShowActivity.java:
Main idea: create a List of dish groups as data sources, when the user chooses a different menu item, the data source will be changed according to the position of the menu item.
public class FoodShowActivity extends Activity implements View.OnClickListener, AdapterView.OnItemClickListener {
//Initialize all the layout components
private ListView listView_foods = null;
private ListView listview_shopcar = null;
private ListView lv_menu;
private ImageView img_order_submit = null;
private ImageView view_shopcar = null;
private TextView all_amount = null;
private int pos;//table number
private List<List<DishSelect>> alldatas;//contains different types of dish group
private List<DishSelect> datas; //List of one dish group,e.g.special or drink
private OrderAdapter adapter; //customized adapter used by right dish home
LeftAdapter leftAdapter;//adpater used by left menu
private DataSetObserver sumObserver = new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
int sum = 0;
for (int i = 0; i < alldatas.size(); i++) {
for (int j = 0; j < alldatas.get(i).size(); j++)
{
sum += alldatas.get(i).get(j).getNum() * Integer.parseInt(alldatas.get(i).get(j).getPrice());
}
}
all_amount = (TextView) findViewById(R.id.all_amount);
all_amount.setText(sum+"元");
}
@Override
public void onInvalidated() {
super.onInvalidated();//invalidate
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_food_show);
listView_foods = (ListView) findViewById(R.id.listView_foods);
all_amount = (TextView) findViewById(R.id.all_amount);
img_order_submit = (ImageView) findViewById(R.id.img_order_submit);
lv_menu = (ListView)findViewById(R.id.lv_menu);
view_shopcar = (ImageView) findViewById(R.id.shopcar);
//initialize left adapter
leftAdapter = new LeftAdapter(getBaseContext());
lv_menu.setAdapter(leftAdapter);
// initialize data source and right adapter
alldatas = DishSelect.getdishgroup();
datas = alldatas.get(0);
adapter = new OrderAdapter(this);
adapter.updateData(datas);
adapter.setOnAddNum(this);// sub button
adapter.setOnSubNum(this);
adapter.registerDataSetObserver(sumObserver);
listView_foods.setAdapter(adapter);
listView_foods.setOnItemClickListener(this);
lv_menu.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
leftAdapter.updateData(arg2);
datas = alldatas.get(arg2);
adapter.updateData(datas);
}
});
img_order_submit.setOnClickListener(listener);// sum up(calculate) imageview
view_shopcar.setOnClickListener(new View.OnClickListener() {//shopcar imageview
@Override
public void onClick(View v) {
setDialog();
}
});
Intent intent = getIntent();// get the data passed by last page
Bundle b = intent.getExtras();
pos = b.getInt("pos");
}
@Override
public void onClick(View view) {
Object tag = view.getTag();
switch (view.getId()) {
case R.id.btn_add: //add button
// get Tag set up by adapter
if (tag != null && tag instanceof Integer) {
//get position through value of Tag
int position = (Integer) tag;
int num = datas.get(position).getNum();
num++;
datas.get(position).setNum(num); //change the number of dish
adapter.notifyDataSetChanged();//when the user presses button, update the item list
}
break;
case R.id.btn_sub: //sub button,the same strategy as add
if (tag != null && tag instanceof Integer) {
int position = (Integer) tag;
int num = datas.get(position).getNum();
if (num > 0) {
num--;
datas.get(position).setNum(num);
adapter.notifyDataSetChanged();
}
}
break;
}
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
adapter.notifyDataSetChanged();
}
@Override
protected void onDestroy() {
super.onDestroy();
adapter.unregisterDataSetObserver(sumObserver);
}
//set up listener for "sum up"
private View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean exist = false;//check whether the user has chosen at least one dish
for(int i = 0; i < alldatas.size(); i ++)
{
for(int j = 0;j < alldatas.get(i).size(); j ++) {
if (alldatas.get(i).get(j).getNum() != 0) {//user has ordered at least one dish
exist = true;
}
}
}
if(exist) {// transfer data to next page
Bundle b = new Bundle();
int count = 0;
for (int i = 0; i < alldatas.size(); i++) {
for(int j = 0;j < alldatas.get(i).size(); j ++) {
b.putString("food_amount" + count, String.valueOf(alldatas.get(i).get(j).getNum()));
count++;
}
}
b.putInt("pos", pos);
Intent intent = new Intent();
intent.setClass(getApplicationContext(), OrderDetailActivity.class);//transfer data to OrderDetailActivity
intent.putExtras(b);
startActivity(intent);
}else{
Toast.makeText(FoodShowActivity.this, "请点单,谢谢!", Toast.LENGTH_SHORT).show();
}
}
};
private void setDialog(){
Dialog mCameraDialog = new Dialog(this, R.style.BottomDialog);
LinearLayout root = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.shopcar_dialog, null);
listview_shopcar = (ListView) root.findViewById(R.id.shoppingcar_listview);
SimpleAdapter adapter1 = new SimpleAdapter(getApplicationContext(), getData(),R.layout.shopcar_dialog_listview_content,
new String[]{"food_name","food_price","food_amount","food_totalprice"}, new int[]{R.id.foodname,R.id.foodprice,R.id.foodamount,R.id.foodtotalprice});
listview_shopcar.setAdapter(adapter1);
mCameraDialog.setContentView(root);//initialize view
Window dialogWindow = mCameraDialog.getWindow();
dialogWindow.setGravity(Gravity.BOTTOM);
WindowManager.LayoutParams lp = dialogWindow.getAttributes(); // get the parameters of dialog Window
lp.x = 0; // new x position
lp.y = 0; // new y position
lp.width = (int) getResources().getDisplayMetrics().widthPixels; // 宽度
root.measure(0, 10);
lp.height = root.getMeasuredHeight();
lp.alpha = 9f; // transparent
dialogWindow.setAttributes(lp);
mCameraDialog.show();
}
private List<Map<String,Object>> getData(){// data source of shop car
List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
for(int i = 0; i < alldatas.size();i++) {
for (int j = 0; j < alldatas.get(i).size(); j++) {
if (alldatas.get(i).get(j).getNum() != 0) {//only shows the food item with number larger than 0
Map map = new HashMap<String, Object>();
map.put("food_name", alldatas.get(i).get(j).getName());
map.put("food_price", alldatas.get(i).get(j).getPrice());
map.put("food_amount", alldatas.get(i).get(j).getNum());
map.put("food_totalprice", String.valueOf(alldatas.get(i).get(j).getNum() * Integer.parseInt(alldatas.get(i).get(j).getPrice())));
data.add(map);
}
}
}
return data;
}
}
Database storaging
SQLiteUtil.java
Main idea: define the DB name, table name and all types of attributes(name, age, photo, ordering detail, password, recommendation, gender)
public class SQLiteUtil extends SQLiteOpenHelper {
//define db name , table name and attributes
private static final String DBNAME = "customer.db";
private static final String TABLE_NAME = "customer_info";
private static final String TABLE_INFO_COLUM_ID = "_id";//primary key(cannot be null)
private static final String TABLE_INFO_COLUM_NAME = "name";
private static final String TABLE_INFO_COLUM_PWD = "pwd";
private static final String TABLE_INFO_COLUM_REC = "rec";
private static final String TABLE_INFO_COLUM_ORDDETAIl = "orddetail";
private static final String TABLE_INFO_COLUM_age = "age";
private static final String TABLE_INFO_COLUM_gender = "gender";
private static final String TABLE_INFO_COLUM_photo = "photo";
//constructor
public SQLiteUtil(Context context, int version) {
super(context, DBNAME, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
//create table by using StringBuffer to reduce the consumption of RAM
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("CREATE TABLE IF NOT EXISTS ");
stringBuffer.append(TABLE_NAME + "(");
stringBuffer.append(TABLE_INFO_COLUM_ID+" integer primary key autoincrement ,");
stringBuffer.append(TABLE_INFO_COLUM_NAME+" varchar(10),");
stringBuffer.append(TABLE_INFO_COLUM_PWD+" varchar(10),");
stringBuffer.append(TABLE_INFO_COLUM_REC+" varchar(100),");
stringBuffer.append(TABLE_INFO_COLUM_ORDDETAIl+" varchar(255),");
stringBuffer.append(TABLE_INFO_COLUM_age+" integer,");
stringBuffer.append(TABLE_INFO_COLUM_gender+" varchar(10),");
stringBuffer.append(TABLE_INFO_COLUM_photo+" varchar(255))");
db.execSQL(stringBuffer.toString());
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String sql = "drop table if exists "+TABLE_NAME;
db.execSQL(sql);
onCreate(db);
}
UserDao.java
Main idea: define how to search, update, delete, and insert Userinfo object to the database.
public class UserDao {
private SQLiteUtil sqLiteUtil;
public UserDao(Context context){
sqLiteUtil = new SQLiteUtil(context,1);
}
//search the database
public List search(){
List list = new ArrayList();
SQLiteDatabase db = sqLiteUtil.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from customer_info", null);
UserInfo userInfo = null;//Database object
while (cursor.moveToNext()){
int id = cursor.getInt(cursor.getColumnIndex("_id"));
String username = cursor.getString(cursor.getColumnIndex("name"));
String pwd = cursor.getString(cursor.getColumnIndex("pwd"));
String rec = cursor.getString(cursor.getColumnIndex("rec"));
String orddetail = cursor.getString(cursor.getColumnIndex("orddetail"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
String gender = cursor.getString(cursor.getColumnIndex("gender"));
String photo = cursor.getString(cursor.getColumnIndex("photo"));
userInfo = new UserInfo();
userInfo.setId(id);
userInfo.setUsername(username);
userInfo.setPwd(pwd);
userInfo.setRec(rec);
userInfo.setOrddetail(orddetail);
userInfo.setAge(age);
userInfo.setGender(gender);
userInfo.setPhoto(photo);
list.add(userInfo);
}
cursor.close();
db.close();
return list;
}
//Insert
public void insert(UserInfo userInfo){
SQLiteDatabase db = sqLiteUtil.getWritableDatabase();
//ContentValues can store the data,like Map
ContentValues contentValues = new ContentValues();
//generate id automatically!
contentValues.put("name",userInfo.getUsername());
contentValues.put("pwd",userInfo.getPwd());
contentValues.put("rec",userInfo.getRec());
contentValues.put("orddetail",userInfo.getOrddetail());
contentValues.put("age",userInfo.getAge());
contentValues.put("gender",userInfo.getGender());
contentValues.put("photo",userInfo.getPhoto());
//execute insertion
db.insert("customer_info", null, contentValues);
db.close();
}
//Delete
public void del(int id){
SQLiteDatabase db = sqLiteUtil.getWritableDatabase();
db.delete("customer_info", "_id = ?", new String[]{String.valueOf(id)});
db.close();
}
//Update
public void updateRec(UserInfo userInfo){
SQLiteDatabase db = sqLiteUtil.getWritableDatabase();
String sql = "update customer_info set rec = ? where _id = ?";
db.execSQL(sql,new Object[]{userInfo.getRec(),userInfo.getId()});
db.close();
}
Recommendation Management
MyListView.java
Main idea:Initialize the pop window, when the system detects MotionEvent.ACTION_DOWN, if the pop window is showing, dismiss it, else locate which item is clicked. When sys detects MotionEvent.ACTION_MOVE, check whether the user is swiping left to a certain distance, if true, set the “isSliding” tag to True, show the delete button on the left-hand side.
class MyListView extends ListView {
private static final String TAG = MyListView.class.getSimpleName();
private int touchSlop; //the shortest distance the user swipes the screen
private boolean isSliding; //check whether user slides
private int xDown; //pressing position
private int yDown;
private int xMove; //position when the finger moves
private int yMove;
private LayoutInflater mInflater;
private PopupWindow mPopupWindow; //pop up a Window for showing
private int mPopupWindowHeight; //the height of the popwindow
private int mPopupWindowWidth; //the width of the popwindow
private TextView delete; //when user swipes left, the delete button will show
private DeleteClickListener mListener; // set up listener for delete button
private View mCurrentView; //view of delete button
private int mCurrentViewPos; //the position of delete button view
public MyListView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
View view = mInflater.inflate(R.layout.delete_button, null); //find the layout of delete button
delete = (TextView) view.findViewById(R.id.delete)
mPopupWindow = new PopupWindow(view, LinearLayout.LayoutParams. WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT); //create a popupWindow
mPopupWindow.getContentView().measure(0, 0); //initialize
mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight(); //get the height of the popupwindow
mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth();
}
@Override public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getAction();
int x = (int) ev.getX();// the position the user touches
int y = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN: //0 action_down dismiss
xDown = x;
yDown = y;
if (mPopupWindow.isShowing()) {// if the popup window shows, dismiss it
dismissPopWindow();
return false;
}
//else get the current touching position
mCurrentViewPos = pointToPosition(xDown, yDown);
View view = getChildAt(mCurrentViewPos - getFirstVisiblePosition());//get the item the user presses
mCurrentView = view;
break;
case MotionEvent.ACTION_MOVE: //2 move
xMove = x;
yMove = y;
int dx = xMove - xDown;
int dy = yMove - yDown;
if (xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop) { //check whether the finger swipes left to a certain distance(>touchslop), it so ,pop up window
isSliding = true;
}
break;
}
return super.dispatchTouchEvent(ev);
}
@Override public boolean onTouchEvent(MotionEvent ev) {
if (mCurrentView == null) { // if the view doesn't exist ,return false
return false;
}
int action = ev.getAction();
if (isSliding) {
switch (action) {
case MotionEvent.ACTION_MOVE:
int[] location = new int[2];
mCurrentView.getLocationOnScreen(location);
mPopupWindow.update();
delete.setHeight(getMeasuredHeight()/getChildCount());//calculate the height of each delete button
int x = location[0] + mCurrentView.getWidth();
int y = location[1] + mCurrentView.getHeight() / 2 - mPopupWindowHeight;
mPopupWindow.showAtLocation(mCurrentView, Gravity.LEFT | Gravity.TOP, x, y);
delete.setOnClickListener(new OnClickListener() {
@Override public void onClick(View view) {
if (mListener != null) {
mListener.onClickDelete(mCurrentViewPos);
mPopupWindow.dismiss();
}
}
});
break;
case MotionEvent.ACTION_UP:
isSliding = false;
break;
}
return true;
}
return super.onTouchEvent(ev);
}
private void dismissPopWindow() {
if (mPopupWindow != null && mPopupWindow.isShowing()) {
mPopupWindow.dismiss();
}
}
public void setDelButtonClickListener(DeleteClickListener listener) {
mListener = listener;
}
Reference: http://www.zhanghongyang.com
PersonalTrendsManageActivity.java
Main idea: set up an adapter for listview, when the user deletes the item, update the remark attribute in the database, at the same time, the remark listview contents will also be updated.
public class PersonalTrendsManageActivity extends Activity {
SimpleAdapter simpleAdapter = null;
private MyListView mListView;
List<Map<String, Object>> lists = new ArrayList<Map<String, Object>>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.personal_trend_manage_listview);
mListView = (MyListView) findViewById(R.id.table);
simpleAdapter = new SimpleAdapter(getApplicationContext(), getData(), R.layout.personal_trend_manage_listview_content, new String[]{"Rec"}, new int[]{R.id.user_recommend});
mListView.setAdapter(simpleAdapter);
mListView.setSelector(new ColorDrawable(Color.LTGRAY));
mListView.setDelButtonClickListener(new DeleteClickListener() {
@Override
public void onClickDelete(int position) {
lists.remove(position);//remove the item
simpleAdapter.notifyDataSetChanged();
UserDao userDao = new UserDao(getApplicationContext());
FileIO io = new FileIO(getApplicationContext());
String username = io.load("CurrentUser");//get the current user name
List<UserInfo> list = userDao.search();//search all the users
UserInfo user;
for (int i = 0; i < list.size(); i++) {
user = (UserInfo) list.get(i);
//update the recommendation
if (user.getUsername().equals(username)) {
String[] allrecs = user.getRec().split(";");
ArrayList<String> all = new ArrayList<>();
for (int j = 0; j < allrecs.length; j++) {
all.add(allrecs[j]);
}
all.remove(position);
String newstr = "";
for (int j = 0; j < all.size(); j++) {
newstr += all.get(j) + ";";
}
user.setRec(newstr);
userDao.updateRec(user);//update the recommendation
}
}
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
}
private List<Map<String, Object>> getData() {//adapter data source (show the remarks in detail )
FileIO io = new FileIO(getApplicationContext());
Map<String, Object> map = null;
UserDao userDao = new UserDao(getApplicationContext());
List<UserInfo> userInfolist = userDao.search();
String username = io.load("CurrentUser");
for (int i = 0; i < userInfolist.size(); i++) {
if(userInfolist.get(i).getRec()!=null){
if (userInfolist.get(i).getUsername().equals(username)&&!userInfolist.get(i).getRec().equals("")) {
String[] checkRec = userInfolist.get(i).getRec().split(";");
if (checkRec.length > 0) {
for (int j = 0; j < checkRec.length; j++) {
String[] str = checkRec[j].split("#");
if(str.length!= 0) {
map = new HashMap<String, Object>();
map.put("Rec", "于 " + str[1] + " 评价:" + j + ":" + str[0]);
lists.add(map);
}
}
}
}
}
}
if(lists.size() == 0) {
map = new HashMap<String, Object>();
map.put("Rec", "暂未作出任何评价");
lists.add(map);
}
return lists;
}
}
Image choosing and showing
PersonalInfEditActivity.java
Main idea: open the album, parse the uri (or reconstruct URI) and get the real storage path of the photo, and show the photo in imageview
public class PersonalInfEditActivity extends Activity {
private ImageView photo;
private ImageView submit;
private EditText age;
private TextView name;
private EditText sex;
String imagePath = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_frag_personal_inf_edit);
photo=(ImageView)findViewById(R.id.image) ;
submit=(ImageView)findViewById(R.id.submit) ;
age = (EditText)findViewById(R.id.age);
name = (TextView)findViewById(R.id.name);
sex = (EditText)findViewById(R.id.gender);
initView();
submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FileIO io = new FileIO(getApplicationContext());
String username = io.load("CurrentUser");//current user name
UserDao userDao = new UserDao(getBaseContext());
List<UserInfo> userlist = userDao.search();
name.setText(username);
UserInfo user;
if(userlist.size() > 0) {
for (int i = 0; i < userlist.size(); i++) {
user = (UserInfo) userlist.get(i);
if (user.getUsername().equals(username)) {
if(!age.getText().equals("")&& !sex.getText().equals("") && imagePath!=null) {
user.setAge(Integer.parseInt(age.getText().toString()));
userDao.updateAge(user);
user.setGender(sex.getText().toString());
userDao.updateGender(user);
user.setPhoto(imagePath);
userDao.updatephoto(user);
Intent intent = new Intent();
intent.setClass(getApplicationContext(), MainActivity.class);
startActivity(intent);
}
else
{
Toast.makeText(PersonalInfEditActivity.this, "请输入完整信息后提交!", Toast.LENGTH_SHORT).show();
}
}
}
}
}
});
}
private void initView() {
ImageView pick = (ImageView) findViewById(R.id.button2);
pick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openAlbum();
}
});
}
private void openAlbum() {
Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image
Uri uri = data.getData();
if (DocumentsContract.isDocumentUri(this, uri)) {
String docId = DocumentsContract.getDocumentId(uri);
if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
String id = docId.split(":")[1];
String selection = MediaStore.Images.Media._ID + "=" + id;
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
Long.valueOf(docId));
imagePath = getImagePath(contentUri, null);
}
} else if ("content".equals(uri.getScheme())) {
imagePath = getImagePath(uri, null);
} else if ("file".equals(uri.getScheme())) {
imagePath = uri.getPath();
}
displayImage(imagePath);
}
//method to display image
private void displayImage(String imagePath) {
if (!TextUtils.isEmpty(imagePath)) {
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
int w,h;
w = bitmap.getWidth();
h = bitmap.getHeight();
Bitmap scale = Bitmap.createScaledBitmap(bitmap,500,500*h/w,false);
photo.setImageBitmap(scale);
} else {
Toast.makeText(this, "cannot find the path of the photo", Toast.LENGTH_SHORT).show();
}
}
private String getImagePath(Uri uri, String selection) {
String path = null;
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
// Method to get image path and display when API<19
private void handleImageBeforeOnKitKat(Intent data) {
Uri uri = data.getData();
String imagePath = getImagePath(uri, null);
displayImage(imagePath);
}
}
Reference: https://blog.csdn.net/wuhun_166/article/details/80000521
About Tests
I mainly do some manual tests in this project, sometimes the screen shows “unfortunately the app closed” and exit the app directly. According to the running record, I observe that NULL object error occurs frequently, so I have monitored the operation related to insertion, deletion, and update of data. In this condition, I could fix the problem after I check the format of data in the database in detail.
Future Improvements
Store the data to the cloud database rather than the local database
Create a restaurant website to manage the preorder bill
More types of food can be stored, JSON can be introduced
Conclusion
This app helps customers pre-order the table and some dishes and tell the restaurant the exact time they may arrive, which means the restaurant can prepare the dishes and table in advance and customers don’t need to wait for a long time after they arrive at the restaurant. In this project, initially, the UI interface is a bit simple, so I re-design all the pages and try to store the customer data in the local database, which helps me obtain the needed data conveniently, the app features can be viewed in this blog. I think more improvements could be made in the future, for example, a cloud database can be used to store a large amount of customer information. I will keep learning the knowledge of android and make this project more perfect. Thanks for reading!