Java tutorial
/* * Copyright 2014 Jacopo Aliprandi, Dario Archetti * Copyright 2015 Stefano Cappa * * This file is part of SPF. * * SPF is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * SPF is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPF. If not, see <http://www.gnu.org/licenses/>. * */ package it.polimi.spf.demo.couponing.client; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import it.polimi.spf.lib.notification.SPFNotification; import it.polimi.spf.lib.profile.SPFLocalProfile; import it.polimi.spf.shared.model.ProfileField; import it.polimi.spf.shared.model.ProfileFieldContainer; import it.polimi.spf.shared.model.SPFAction; import it.polimi.spf.shared.model.SPFActionIntent; import it.polimi.spf.shared.model.SPFError; import it.polimi.spf.shared.model.SPFQuery; import it.polimi.spf.shared.model.SPFTrigger; import it.polimi.spf.shared.model.SPFTrigger.IllegalTriggerException; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; import android.support.v7.internal.widget.ListViewCompat; import android.util.Log; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; public class CategoryFragment extends Fragment { public static CategoryFragment newInstance() { return new CategoryFragment(); } private static final String TAG = "CategoryFragment"; private static final String INTENT_ACTION = "it.polimi.spf.demo.couponing.client.TRIGGER_INTENT"; private static final long SLEEP_PERIOD = 60 * 1000; private static final String PREF_FILE = "trigger_cache"; private SPFLocalProfile mLocalProfile; private SPFNotification mNotificationService; private ProfileFieldContainer mContainer; private ListView mList; private ArrayAdapter<String> mAdapter; private ActionMode mActionMode; private final SPFLocalProfile.Callback mProfileCallbacks = new SPFLocalProfile.Callback() { @Override public void onServiceReady(SPFLocalProfile service) { mLocalProfile = service; mContainer = mLocalProfile.getValueBulk(ProfileField.INTERESTS); } @Override public void onError(SPFError errorMsg) { Log.e(TAG, "Error in local profile: " + errorMsg); mLocalProfile = null; } @Override public void onDisconnect() { mLocalProfile = null; } }; private final SPFNotification.Callback mNotificationCallbacks = new SPFNotification.Callback() { @Override public void onServiceReady(SPFNotification service) { mNotificationService = service; } @Override public void onError(SPFError errorMsg) { Log.e(TAG, "Error in notification service: " + errorMsg); mNotificationService = null; } @Override public void onDisconnect() { mNotificationService = null; } }; private final AbsListView.MultiChoiceModeListener mChoiceListener = new AbsListView.MultiChoiceModeListener() { private Set<Integer> mSelectedPositions; @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { if (checked) { mSelectedPositions.add(position); } else { mSelectedPositions.remove(position); } } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.menu_category_action_mode, menu); mActionMode = mode; mSelectedPositions = new HashSet<>(); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { if (item.getItemId() == R.id.action_category_delete) { for (int i : mSelectedPositions) { String category = (String) mList.getItemAtPosition(i); //remove category in this app deleteCategory(category); //remove category in SPFApp + Framework removeCategoryFromProfile(category); } loadCategoryList(); mActionMode.finish(); } return true; } @Override public void onDestroyActionMode(ActionMode mode) { mSelectedPositions = null; mActionMode = null; } }; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_category_list, container, false); TextView mEmptyView = (TextView) root.findViewById(R.id.category_list_empty); mList = (ListView) root.findViewById(R.id.category_list); mList.setEmptyView(mEmptyView); mAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_activated_1); mList.setAdapter(mAdapter); mList.setMultiChoiceModeListener(mChoiceListener); mList.setChoiceMode(ListViewCompat.CHOICE_MODE_MULTIPLE_MODAL); return root; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setHasOptionsMenu(true); loadCategoryList(); } @Override public void onResume() { super.onResume(); SPFLocalProfile.load(getActivity(), mProfileCallbacks); SPFNotification.load(getActivity(), mNotificationCallbacks); } @Override public void onPause() { super.onPause(); if (mLocalProfile != null) { mLocalProfile.disconnect(); } if (mNotificationService != null) { mNotificationService.disconnect(); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_category, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_category_add) { onCategoryAdd(); return true; } return super.onOptionsItemSelected(item); } public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (mActionMode != null && !isVisibleToUser) { mActionMode.finish(); } } public void onCategoryAdd() { List<String> categories = ClientApplication.get().getCouponDatabase().getCategories(); Set<String> selected = getPreferences().getAll().keySet(); categories.removeAll(selected); if (categories.size() == 0) { Toast.makeText(this.getActivity(), this.getResources().getString(R.string.error_no_categories_available), Toast.LENGTH_SHORT) .show(); return; } final CategoryDialogView view = new CategoryDialogView(getActivity(), categories); new AlertDialog.Builder(getActivity()).setTitle("Add category").setView(view) .setPositiveButton("Add", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String category = view.getSelectedCategory(); if (!saveCategory(category)) { return; } if (view.isProfileOptionChecked()) { addCategoryToProfile(category); } loadCategoryList(); } }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).show(); } private boolean saveCategory(String category) { if (mNotificationService == null) { toast(R.string.error_notification_service_unavailable); return false; } SPFQuery q = new SPFQuery.Builder().setTag(category) .setAppIdentifier("it.polimi.spf.demo.couponing.provider").build(); SPFAction a = new SPFActionIntent(INTENT_ACTION); SPFTrigger t; try { t = new SPFTrigger("Category " + category + " trigger", q, a, SLEEP_PERIOD); } catch (IllegalTriggerException e) { toast(R.string.error_notification_service_unavailable); return false; } if (!mNotificationService.saveTrigger(t)) { toast(R.string.error_cannot_save_trigger); return false; } getPreferences().edit().putLong(category, t.getId()).apply(); return true; } private void deleteCategory(String category) { if (mNotificationService == null) { toast(R.string.error_notification_service_unavailable); return; } SharedPreferences pf = getPreferences(); long triggerId = pf.getLong(category, -1); if (!mNotificationService.deleteTrigger(triggerId)) { toast(R.string.error_cannot_delete_trigger); //return; } getPreferences().edit().remove(category).apply(); } private void addCategoryToProfile(String category) { if (mContainer == null) { toast(R.string.error_profile_service_not_available); return; } String[] catArray = mContainer.getFieldValue(ProfileField.INTERESTS); if (catArray == null) { catArray = new String[0]; } List<String> cat = new ArrayList<>(Arrays.asList(catArray)); if (cat.indexOf(category) == -1) { cat.add(category); mContainer.setFieldValue(ProfileField.INTERESTS, cat.toArray(new String[cat.size()])); mLocalProfile.setValueBulk(mContainer); mContainer.clearModified(); } } private void removeCategoryFromProfile(String category) { if (mContainer == null) { toast(R.string.error_profile_service_not_available); return; } String[] catArray = mContainer.getFieldValue(ProfileField.INTERESTS); if (catArray == null) { catArray = new String[0]; } List<String> cat = new ArrayList<>(Arrays.asList(catArray)); if (cat.indexOf(category) != -1) { cat.remove(category); mContainer.setFieldValue(ProfileField.INTERESTS, cat.toArray(new String[cat.size()])); mLocalProfile.setValueBulk(mContainer); mContainer.clearModified(); } } private void loadCategoryList() { Set<String> categories = getPreferences().getAll().keySet(); mAdapter.clear(); mAdapter.addAll(categories); } private SharedPreferences getPreferences() { return getActivity().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); } private void toast(int resId) { Toast.makeText(getActivity(), resId, Toast.LENGTH_SHORT).show(); } private class CategoryDialogView extends LinearLayout { private final Spinner mCategorySpinner; private final CheckBox mProfileCheckbox; public CategoryDialogView(Context context, List<String> categories) { super(context); inflate(getContext(), R.layout.view_category_dialog, this); mCategorySpinner = (Spinner) findViewById(R.id.category_dialog_spinner); mProfileCheckbox = (CheckBox) findViewById(R.id.category_dialog_profile_check); ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, categories); mCategorySpinner.setAdapter(adapter); } public String getSelectedCategory() { return (String) mCategorySpinner.getSelectedItem(); } public boolean isProfileOptionChecked() { return mProfileCheckbox.isChecked(); } } }