call, Throwable t) {
236 | // Log.d("Error",t.getMessage());
237 | }
238 | });
239 | }
240 |
241 | private void ShowDialog(String title, String message) {
242 | Dialog.Builder builder;
243 |
244 | boolean isLightTheme = ThemeManager.getInstance().getCurrentTheme() == 0;
245 |
246 | builder = new SimpleDialog.Builder(isLightTheme ? R.style.SimpleDialogLight : R.style.SimpleDialog) {
247 | @Override
248 | public void onPositiveActionClicked(DialogFragment fragment) {
249 | Toast.makeText(MainActivity.this, "Agreed", Toast.LENGTH_SHORT).show();
250 | super.onPositiveActionClicked(fragment);
251 | }
252 |
253 | @Override
254 | public void onNegativeActionClicked(DialogFragment fragment) {
255 | Toast.makeText(MainActivity.this, "Disagreed", Toast.LENGTH_SHORT).show();
256 | super.onNegativeActionClicked(fragment);
257 | }
258 | };
259 |
260 | ((SimpleDialog.Builder) builder).message(message)
261 | .title(title)
262 | .positiveAction("OK");
263 |
264 | DialogFragment fragment = DialogFragment.newInstance(builder);
265 | fragment.show(getSupportFragmentManager(), null);
266 |
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kedevelopers/supermarketprices/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package com.kedevelopers.supermarketprices;
2 |
3 |
4 | import android.annotation.TargetApi;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.res.Configuration;
8 | import android.media.Ringtone;
9 | import android.media.RingtoneManager;
10 | import android.net.Uri;
11 | import android.os.Build;
12 | import android.os.Bundle;
13 | import android.preference.ListPreference;
14 | import android.preference.Preference;
15 | import android.preference.PreferenceActivity;
16 | import android.support.v7.app.ActionBar;
17 | import android.preference.PreferenceFragment;
18 | import android.preference.PreferenceManager;
19 | import android.preference.RingtonePreference;
20 | import android.text.TextUtils;
21 | import android.view.MenuItem;
22 |
23 | import java.util.List;
24 |
25 | /**
26 | * A {@link PreferenceActivity} that presents a set of application settings. On
27 | * handset devices, settings are presented as a single list. On tablets,
28 | * settings are split by category, with category headers shown to the left of
29 | * the list of settings.
30 | *
31 | * See
32 | * Android Design: Settings for design guidelines and the Settings
34 | * API Guide for more information on developing a Settings UI.
35 | */
36 | public class SettingsActivity extends AppCompatPreferenceActivity {
37 | /**
38 | * A preference value change listener that updates the preference's summary
39 | * to reflect its new value.
40 | */
41 | private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
42 | @Override
43 | public boolean onPreferenceChange(Preference preference, Object value) {
44 | String stringValue = value.toString();
45 |
46 | if (preference instanceof ListPreference) {
47 | // For list preferences, look up the correct display value in
48 | // the preference's 'entries' list.
49 | ListPreference listPreference = (ListPreference) preference;
50 | int index = listPreference.findIndexOfValue(stringValue);
51 |
52 | // Set the summary to reflect the new value.
53 | preference.setSummary(
54 | index >= 0
55 | ? listPreference.getEntries()[index]
56 | : null);
57 |
58 | } else if (preference instanceof RingtonePreference) {
59 | // For ringtone preferences, look up the correct display value
60 | // using RingtoneManager.
61 | if (TextUtils.isEmpty(stringValue)) {
62 | // Empty values correspond to 'silent' (no ringtone).
63 | preference.setSummary(R.string.pref_ringtone_silent);
64 |
65 | } else {
66 | Ringtone ringtone = RingtoneManager.getRingtone(
67 | preference.getContext(), Uri.parse(stringValue));
68 |
69 | if (ringtone == null) {
70 | // Clear the summary if there was a lookup error.
71 | preference.setSummary(null);
72 | } else {
73 | // Set the summary to reflect the new ringtone display
74 | // name.
75 | String name = ringtone.getTitle(preference.getContext());
76 | preference.setSummary(name);
77 | }
78 | }
79 |
80 | } else {
81 | // For all other preferences, set the summary to the value's
82 | // simple string representation.
83 | preference.setSummary(stringValue);
84 | }
85 | return true;
86 | }
87 | };
88 |
89 | /**
90 | * Helper method to determine if the device has an extra-large screen. For
91 | * example, 10" tablets are extra-large.
92 | */
93 | private static boolean isXLargeTablet(Context context) {
94 | return (context.getResources().getConfiguration().screenLayout
95 | & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
96 | }
97 |
98 | /**
99 | * Binds a preference's summary to its value. More specifically, when the
100 | * preference's value is changed, its summary (line of text below the
101 | * preference title) is updated to reflect the value. The summary is also
102 | * immediately updated upon calling this method. The exact display format is
103 | * dependent on the type of preference.
104 | *
105 | * @see #sBindPreferenceSummaryToValueListener
106 | */
107 | private static void bindPreferenceSummaryToValue(Preference preference) {
108 | // Set the listener to watch for value changes.
109 | preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
110 |
111 | // Trigger the listener immediately with the preference's
112 | // current value.
113 | sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
114 | PreferenceManager
115 | .getDefaultSharedPreferences(preference.getContext())
116 | .getString(preference.getKey(), ""));
117 | }
118 |
119 | @Override
120 | protected void onCreate(Bundle savedInstanceState) {
121 | super.onCreate(savedInstanceState);
122 | setupActionBar();
123 | }
124 |
125 | /**
126 | * Set up the {@link android.app.ActionBar}, if the API is available.
127 | */
128 | private void setupActionBar() {
129 | ActionBar actionBar = getSupportActionBar();
130 | if (actionBar != null) {
131 | // Show the Up button in the action bar.
132 | actionBar.setDisplayHomeAsUpEnabled(true);
133 | }
134 | }
135 |
136 | /**
137 | * {@inheritDoc}
138 | */
139 | @Override
140 | public boolean onIsMultiPane() {
141 | return isXLargeTablet(this);
142 | }
143 |
144 | /**
145 | * {@inheritDoc}
146 | */
147 | @Override
148 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
149 | public void onBuildHeaders(List target) {
150 | loadHeadersFromResource(R.xml.pref_headers, target);
151 | }
152 |
153 | /**
154 | * This method stops fragment injection in malicious applications.
155 | * Make sure to deny any unknown fragments here.
156 | */
157 | protected boolean isValidFragment(String fragmentName) {
158 | return PreferenceFragment.class.getName().equals(fragmentName)
159 | || GeneralPreferenceFragment.class.getName().equals(fragmentName)
160 | || DataSyncPreferenceFragment.class.getName().equals(fragmentName)
161 | || NotificationPreferenceFragment.class.getName().equals(fragmentName);
162 | }
163 |
164 | /**
165 | * This fragment shows general preferences only. It is used when the
166 | * activity is showing a two-pane settings UI.
167 | */
168 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
169 | public static class GeneralPreferenceFragment extends PreferenceFragment {
170 | @Override
171 | public void onCreate(Bundle savedInstanceState) {
172 | super.onCreate(savedInstanceState);
173 | addPreferencesFromResource(R.xml.pref_general);
174 | setHasOptionsMenu(true);
175 |
176 | // Bind the summaries of EditText/List/Dialog/Ringtone preferences
177 | // to their values. When their values change, their summaries are
178 | // updated to reflect the new value, per the Android Design
179 | // guidelines.
180 | bindPreferenceSummaryToValue(findPreference("example_text"));
181 | bindPreferenceSummaryToValue(findPreference("example_list"));
182 | }
183 |
184 | @Override
185 | public boolean onOptionsItemSelected(MenuItem item) {
186 | int id = item.getItemId();
187 | if (id == android.R.id.home) {
188 | startActivity(new Intent(getActivity(), SettingsActivity.class));
189 | return true;
190 | }
191 | return super.onOptionsItemSelected(item);
192 | }
193 | }
194 |
195 | /**
196 | * This fragment shows notification preferences only. It is used when the
197 | * activity is showing a two-pane settings UI.
198 | */
199 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
200 | public static class NotificationPreferenceFragment extends PreferenceFragment {
201 | @Override
202 | public void onCreate(Bundle savedInstanceState) {
203 | super.onCreate(savedInstanceState);
204 | addPreferencesFromResource(R.xml.pref_notification);
205 | setHasOptionsMenu(true);
206 |
207 | // Bind the summaries of EditText/List/Dialog/Ringtone preferences
208 | // to their values. When their values change, their summaries are
209 | // updated to reflect the new value, per the Android Design
210 | // guidelines.
211 | bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
212 | }
213 |
214 | @Override
215 | public boolean onOptionsItemSelected(MenuItem item) {
216 | int id = item.getItemId();
217 | if (id == android.R.id.home) {
218 | startActivity(new Intent(getActivity(), SettingsActivity.class));
219 | return true;
220 | }
221 | return super.onOptionsItemSelected(item);
222 | }
223 | }
224 |
225 | /**
226 | * This fragment shows data and sync preferences only. It is used when the
227 | * activity is showing a two-pane settings UI.
228 | */
229 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
230 | public static class DataSyncPreferenceFragment extends PreferenceFragment {
231 | @Override
232 | public void onCreate(Bundle savedInstanceState) {
233 | super.onCreate(savedInstanceState);
234 | addPreferencesFromResource(R.xml.pref_data_sync);
235 | setHasOptionsMenu(true);
236 |
237 | // Bind the summaries of EditText/List/Dialog/Ringtone preferences
238 | // to their values. When their values change, their summaries are
239 | // updated to reflect the new value, per the Android Design
240 | // guidelines.
241 | bindPreferenceSummaryToValue(findPreference("sync_frequency"));
242 | }
243 |
244 | @Override
245 | public boolean onOptionsItemSelected(MenuItem item) {
246 | int id = item.getItemId();
247 | if (id == android.R.id.home) {
248 | startActivity(new Intent(getActivity(), SettingsActivity.class));
249 | return true;
250 | }
251 | return super.onOptionsItemSelected(item);
252 | }
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kedevelopers/supermarketprices/Adapter/SuperMarketProductAdapter.java:
--------------------------------------------------------------------------------
1 | package com.kedevelopers.supermarketprices.Adapter;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.support.v7.app.AlertDialog;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.util.Log;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.EditText;
13 | import android.widget.LinearLayout;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 |
17 | import com.android.volley.AuthFailureError;
18 | import com.android.volley.NetworkError;
19 | import com.android.volley.NoConnectionError;
20 | import com.android.volley.ParseError;
21 | import com.android.volley.Request;
22 | import com.android.volley.Response;
23 | import com.android.volley.ServerError;
24 | import com.android.volley.TimeoutError;
25 | import com.android.volley.VolleyError;
26 | import com.android.volley.toolbox.ImageLoader;
27 | import com.android.volley.toolbox.NetworkImageView;
28 | import com.android.volley.toolbox.StringRequest;
29 | import com.kedevelopers.supermarketprices.AppController;
30 | import com.kedevelopers.supermarketprices.Config;
31 | import com.kedevelopers.supermarketprices.CustomVolleyRequest;
32 | import com.kedevelopers.supermarketprices.Model.SupermarketProduct;
33 | import com.kedevelopers.supermarketprices.R;
34 | import com.kedevelopers.supermarketprices.SupermarketAdminProducts;
35 |
36 | import org.json.JSONException;
37 | import org.json.JSONObject;
38 |
39 | import java.util.ArrayList;
40 | import java.util.HashMap;
41 | import java.util.List;
42 | import java.util.Map;
43 |
44 | /**
45 | * Created by BEN on 12/22/2016.
46 | */
47 |
48 | public class SuperMarketProductAdapter extends RecyclerView.Adapter {
49 |
50 | //Imageloader to load image
51 | private ImageLoader imageLoader;
52 | private Context context;
53 | private ProgressDialog mProgressDialog;
54 |
55 | //List to store all Products
56 | ArrayList Products;
57 | private ArrayList mproducts;
58 | //Constructor of this class
59 | public SuperMarketProductAdapter(ArrayList Products, Context context){
60 | super();
61 | //Getting all Products
62 | this.Products = Products;
63 | this.context = context;
64 | }
65 |
66 | @Override
67 | public SuperMarketProductAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
68 | View v = LayoutInflater.from(parent.getContext())
69 | .inflate(R.layout.products_list, parent, false);
70 | mProgressDialog = new ProgressDialog(context);
71 |
72 | SuperMarketProductAdapter.ViewHolder viewHolder = new SuperMarketProductAdapter.ViewHolder(v);
73 | return viewHolder;
74 | }
75 |
76 | @Override
77 | public void onBindViewHolder(SuperMarketProductAdapter.ViewHolder holder, int position) {
78 |
79 | //Getting the particular item from the list
80 | SupermarketProduct Product = Products.get(position);
81 |
82 | //Loading image from url
83 | imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
84 | imageLoader.get(Product.getImage(), ImageLoader.getImageListener(holder.imageView, R.drawable.image1, android.R.drawable.ic_dialog_alert));
85 |
86 | //Showing data on the views
87 | holder.imageView.setImageUrl(Product.getImage(), imageLoader);
88 | holder.textViewName.setText(Product.getName());
89 | holder.textViewDescription.setText(Product.getDescription());
90 |
91 | }
92 |
93 | @Override
94 | public int getItemCount() {
95 | return Products.size();
96 | }
97 | public void setFilter(List products){
98 | Products = new ArrayList<>();
99 | Products.addAll(products);
100 | notifyDataSetChanged();
101 | }
102 |
103 | class ViewHolder extends RecyclerView.ViewHolder {
104 | //Views
105 | public NetworkImageView imageView;
106 | public TextView textViewName;
107 | public TextView textViewDescription;
108 | public LinearLayout card_layout;
109 |
110 | //Initializing Views
111 | public ViewHolder(View itemView) {
112 | super(itemView);
113 | imageView = (NetworkImageView) itemView.findViewById(R.id.imageViewHero);
114 | textViewName = (TextView) itemView.findViewById(R.id.textViewName);
115 | textViewDescription = (TextView) itemView.findViewById(R.id.textViewDescription);
116 | card_layout = (LinearLayout) itemView.findViewById(R.id.card_layout);
117 |
118 | card_layout.setOnClickListener(new View.OnClickListener() {
119 | @Override
120 | public void onClick(View view) {
121 | final Context context = view.getContext();
122 | final int position = getAdapterPosition();
123 | LayoutInflater li = LayoutInflater.from(context);
124 | View promptsView = li.inflate(R.layout.prompt_add_product, null);
125 |
126 | TextView textView =(TextView) promptsView.findViewById(R.id.textView1);
127 |
128 | textView.setText("Add Your Supermarket Price on \n\n" + textViewName.getText() +" \n\n (ksh)");
129 | AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
130 | context);
131 |
132 | // set prompts.xml to alertdialog builder
133 | alertDialogBuilder.setView(promptsView);
134 |
135 | final EditText userInput = (EditText) promptsView.findViewById(R.id.editTextDialogUserInput);
136 |
137 | // set dialog message
138 | alertDialogBuilder
139 | .setCancelable(false)
140 | .setPositiveButton("OK",
141 | new DialogInterface.OnClickListener() {
142 | public void onClick(DialogInterface dialog, int id) {
143 | // get user input and set it to result
144 | // edit text
145 | // Toast.makeText(context, "position " +position +textViewName.getText(), Toast.LENGTH_SHORT).show();
146 | String pn = textViewName.getText().toString();
147 | String pr = userInput.getText().toString();
148 | String sm = SupermarketAdminProducts.supermarket;
149 | AddPrice(pn,pr, sm);
150 | }
151 | })
152 | .setNegativeButton("Cancel",
153 | new DialogInterface.OnClickListener() {
154 | public void onClick(DialogInterface dialog, int id) {
155 | dialog.cancel();
156 | }
157 | });
158 |
159 | // create alert dialog
160 | AlertDialog alertDialog = alertDialogBuilder.create();
161 |
162 | // show it
163 | alertDialog.show();
164 |
165 | }
166 | });
167 | card_layout.setOnLongClickListener(new View.OnLongClickListener() {
168 | @Override
169 | public boolean onLongClick(View view) {
170 |
171 | // DeleteProduct()
172 | return false;
173 | }
174 | });
175 | }
176 |
177 |
178 | private void AddPrice(final String productname,final String price,final String supermarket) {
179 |
180 | String tag_string_req = "req_save";
181 |
182 | // showProgressDialog();
183 | StringRequest strReq = new StringRequest(Request.Method.POST,
184 | Config.ADD_URL_PRICE, new Response.Listener() {
185 |
186 | @Override
187 | public void onResponse(String response) {
188 | Log.d("TAG", "Upload Response: " + response.toString());
189 |
190 | // hideProgressDialog();
191 | try {
192 | JSONObject jObj = new JSONObject(response);
193 | boolean error = jObj.getBoolean("error");
194 | String message = jObj.getString("message");
195 |
196 | if(!error){
197 | Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
198 |
199 | }
200 |
201 | else{
202 |
203 | Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
204 |
205 |
206 | }
207 |
208 |
209 | } catch (JSONException e) {
210 | e.printStackTrace();
211 | }
212 |
213 | }
214 | }, new Response.ErrorListener() {
215 |
216 | @Override
217 | public void onErrorResponse(VolleyError error) {
218 | Log.e("TAG", "Upload Error: " + error.getMessage());
219 | if (error instanceof TimeoutError || error instanceof NoConnectionError) {
220 | Toast.makeText(context,"Check your internet Connection | TimeoutError",
221 | Toast.LENGTH_LONG).show();
222 | } else if (error instanceof AuthFailureError) {
223 | //TODO
224 | Toast.makeText(context,"AuthFailureError error",
225 | Toast.LENGTH_LONG).show();
226 | } else if (error instanceof ServerError) {
227 | //TODO
228 | Toast.makeText(context,"ServerError error",
229 | Toast.LENGTH_LONG).show();
230 | } else if (error instanceof NetworkError) {
231 | //TODO
232 | Toast.makeText(context,"NetworkError error",
233 | Toast.LENGTH_LONG).show();
234 | } else if (error instanceof ParseError) {
235 | //TODO
236 | Toast.makeText(context,"ParseError error",
237 | Toast.LENGTH_LONG).show();
238 | }
239 |
240 | // hideProgressDialog();
241 | }
242 | }) {
243 |
244 | @Override
245 | protected Map getParams() {
246 | // Posting params to register url
247 | Map params = new HashMap();
248 | // params.put("tag", "upload");
249 | params.put("product_name", productname);
250 | params.put("price", price);
251 | params.put("supermarket", supermarket);
252 |
253 | return params;
254 | }
255 |
256 | };
257 |
258 | // Adding request to request queue
259 | AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
260 | }
261 | }
262 |
263 |
264 |
265 |
266 |
267 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/kedevelopers/supermarketprices/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.kedevelopers.supermarketprices;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.annotation.TargetApi;
6 | import android.content.Intent;
7 | import android.content.pm.PackageManager;
8 | import android.support.annotation.NonNull;
9 | import android.support.design.widget.Snackbar;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.app.LoaderManager.LoaderCallbacks;
12 |
13 | import android.content.CursorLoader;
14 | import android.content.Loader;
15 | import android.database.Cursor;
16 | import android.net.Uri;
17 | import android.os.AsyncTask;
18 |
19 | import android.os.Build;
20 | import android.os.Bundle;
21 | import android.provider.ContactsContract;
22 | import android.text.TextUtils;
23 | import android.view.KeyEvent;
24 | import android.view.View;
25 | import android.view.View.OnClickListener;
26 | import android.view.inputmethod.EditorInfo;
27 | import android.widget.ArrayAdapter;
28 | import android.widget.AutoCompleteTextView;
29 | import android.widget.Button;
30 | import android.widget.EditText;
31 | import android.widget.TextView;
32 |
33 | import java.util.ArrayList;
34 | import java.util.List;
35 |
36 | import static android.Manifest.permission.READ_CONTACTS;
37 |
38 | /**
39 | * A login screen that offers login via email/password.
40 | */
41 | public class LoginActivity extends AppCompatActivity implements LoaderCallbacks {
42 |
43 | /**
44 | * Id to identity READ_CONTACTS permission request.
45 | */
46 | private static final int REQUEST_READ_CONTACTS = 0;
47 |
48 | /**
49 | * A dummy authentication store containing known user names and passwords.
50 | * TODO: remove after connecting to a real authentication system.
51 | */
52 | private static final String[] DUMMY_CREDENTIALS = new String[]{
53 | "foo@example.com:hello", "bar@example.com:world"
54 | };
55 | /**
56 | * Keep track of the login task to ensure we can cancel it if requested.
57 | */
58 | private UserLoginTask mAuthTask = null;
59 |
60 | // UI references.
61 | private AutoCompleteTextView mEmailView;
62 | private EditText mPasswordView;
63 | private View mProgressView;
64 | private View mLoginFormView;
65 |
66 | @Override
67 | protected void onCreate(Bundle savedInstanceState) {
68 | super.onCreate(savedInstanceState);
69 | setContentView(R.layout.activity_login);
70 | // Set up the login form.
71 | mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
72 | populateAutoComplete();
73 |
74 | mPasswordView = (EditText) findViewById(R.id.password);
75 | mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
76 | @Override
77 | public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
78 | if (id == R.id.login || id == EditorInfo.IME_NULL) {
79 | attemptLogin();
80 | return true;
81 | }
82 | return false;
83 | }
84 | });
85 |
86 | Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
87 | mEmailSignInButton.setOnClickListener(new OnClickListener() {
88 | @Override
89 | public void onClick(View view) {
90 | attemptLogin();
91 | }
92 | });
93 |
94 | mLoginFormView = findViewById(R.id.login_form);
95 | mProgressView = findViewById(R.id.login_progress);
96 | }
97 |
98 | private void populateAutoComplete() {
99 | if (!mayRequestContacts()) {
100 | return;
101 | }
102 |
103 | getLoaderManager().initLoader(0, null, this);
104 | }
105 |
106 | private boolean mayRequestContacts() {
107 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
108 | return true;
109 | }
110 | if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
111 | return true;
112 | }
113 | if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
114 | Snackbar.make(mEmailView, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
115 | .setAction(android.R.string.ok, new View.OnClickListener() {
116 | @Override
117 | @TargetApi(Build.VERSION_CODES.M)
118 | public void onClick(View v) {
119 | requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
120 | }
121 | });
122 | } else {
123 | requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
124 | }
125 | return false;
126 | }
127 |
128 | /**
129 | * Callback received when a permissions request has been completed.
130 | */
131 | @Override
132 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
133 | @NonNull int[] grantResults) {
134 | if (requestCode == REQUEST_READ_CONTACTS) {
135 | if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
136 | populateAutoComplete();
137 | }
138 | }
139 | }
140 |
141 |
142 | /**
143 | * Attempts to sign in or register the account specified by the login form.
144 | * If there are form errors (invalid email, missing fields, etc.), the
145 | * errors are presented and no actual login attempt is made.
146 | */
147 | private void attemptLogin() {
148 | if (mAuthTask != null) {
149 | return;
150 | }
151 |
152 | // Reset errors.
153 | mEmailView.setError(null);
154 | mPasswordView.setError(null);
155 |
156 | // Store values at the time of the login attempt.
157 | String email = mEmailView.getText().toString();
158 | String password = mPasswordView.getText().toString();
159 |
160 | boolean cancel = false;
161 | View focusView = null;
162 |
163 | // Check for a valid password, if the user entered one.
164 | if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
165 | mPasswordView.setError(getString(R.string.error_invalid_password));
166 | focusView = mPasswordView;
167 | cancel = true;
168 | }
169 |
170 | // Check for a valid email address.
171 | if (TextUtils.isEmpty(email)) {
172 | mEmailView.setError(getString(R.string.error_field_required));
173 | focusView = mEmailView;
174 | cancel = true;
175 | } else if (!isEmailValid(email)) {
176 | mEmailView.setError(getString(R.string.error_invalid_email));
177 | focusView = mEmailView;
178 | cancel = true;
179 | }
180 |
181 | if (cancel) {
182 | // There was an error; don't attempt login and focus the first
183 | // form field with an error.
184 | focusView.requestFocus();
185 | } else {
186 | // Show a progress spinner, and kick off a background task to
187 | // perform the user login attempt.
188 | showProgress(true);
189 | mAuthTask = new UserLoginTask(email, password);
190 | mAuthTask.execute((Void) null);
191 | }
192 | }
193 |
194 | private boolean isEmailValid(String email) {
195 | //TODO: Replace this with your own logic
196 | if (!email.equals("admin@supermarket.com")){
197 | return false;
198 | }
199 | return email.contains("@");
200 | }
201 |
202 | private boolean isPasswordValid(String password) {
203 | //TODO: Replace this with your own logic
204 | if (!password.equals("admin1234")){
205 | return false;
206 | }
207 | return password.length() > 4;
208 | }
209 |
210 | /**
211 | * Shows the progress UI and hides the login form.
212 | */
213 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
214 | private void showProgress(final boolean show) {
215 | // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
216 | // for very easy animations. If available, use these APIs to fade-in
217 | // the progress spinner.
218 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
219 | int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
220 |
221 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
222 | mLoginFormView.animate().setDuration(shortAnimTime).alpha(
223 | show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
224 | @Override
225 | public void onAnimationEnd(Animator animation) {
226 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
227 | }
228 | });
229 |
230 | mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
231 | mProgressView.animate().setDuration(shortAnimTime).alpha(
232 | show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
233 | @Override
234 | public void onAnimationEnd(Animator animation) {
235 | mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
236 | }
237 | });
238 | } else {
239 | // The ViewPropertyAnimator APIs are not available, so simply show
240 | // and hide the relevant UI components.
241 | mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
242 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
243 | }
244 | }
245 |
246 | @Override
247 | public Loader onCreateLoader(int i, Bundle bundle) {
248 | return new CursorLoader(this,
249 | // Retrieve data rows for the device user's 'profile' contact.
250 | Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
251 | ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION,
252 |
253 | // Select only email addresses.
254 | ContactsContract.Contacts.Data.MIMETYPE +
255 | " = ?", new String[]{ContactsContract.CommonDataKinds.Email
256 | .CONTENT_ITEM_TYPE},
257 |
258 | // Show primary email addresses first. Note that there won't be
259 | // a primary email address if the user hasn't specified one.
260 | ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
261 | }
262 |
263 | @Override
264 | public void onLoadFinished(Loader cursorLoader, Cursor cursor) {
265 | List emails = new ArrayList<>();
266 | cursor.moveToFirst();
267 | while (!cursor.isAfterLast()) {
268 | emails.add(cursor.getString(ProfileQuery.ADDRESS));
269 | cursor.moveToNext();
270 | }
271 |
272 | addEmailsToAutoComplete(emails);
273 | }
274 |
275 | @Override
276 | public void onLoaderReset(Loader cursorLoader) {
277 |
278 | }
279 |
280 | private void addEmailsToAutoComplete(List emailAddressCollection) {
281 | //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
282 | ArrayAdapter adapter =
283 | new ArrayAdapter<>(LoginActivity.this,
284 | android.R.layout.simple_dropdown_item_1line, emailAddressCollection);
285 |
286 | mEmailView.setAdapter(adapter);
287 | }
288 |
289 |
290 | private interface ProfileQuery {
291 | String[] PROJECTION = {
292 | ContactsContract.CommonDataKinds.Email.ADDRESS,
293 | ContactsContract.CommonDataKinds.Email.IS_PRIMARY,
294 | };
295 |
296 | int ADDRESS = 0;
297 | int IS_PRIMARY = 1;
298 | }
299 |
300 | /**
301 | * Represents an asynchronous login/registration task used to authenticate
302 | * the user.
303 | */
304 | public class UserLoginTask extends AsyncTask {
305 |
306 | private final String mEmail;
307 | private final String mPassword;
308 |
309 | UserLoginTask(String email, String password) {
310 | mEmail = email;
311 | mPassword = password;
312 | }
313 |
314 | @Override
315 | protected Boolean doInBackground(Void... params) {
316 | // TODO: attempt authentication against a network service.
317 |
318 | try {
319 | // Simulate network access.
320 | Thread.sleep(2000);
321 | } catch (InterruptedException e) {
322 | return false;
323 | }
324 |
325 | for (String credential : DUMMY_CREDENTIALS) {
326 | String[] pieces = credential.split(":");
327 | if (pieces[0].equals(mEmail)) {
328 | // Account exists, return true if the password matches.
329 | return pieces[1].equals(mPassword);
330 | }
331 | }
332 |
333 | // TODO: register the new account here.
334 | return true;
335 | }
336 |
337 | @Override
338 | protected void onPostExecute(final Boolean success) {
339 | mAuthTask = null;
340 | showProgress(false);
341 |
342 | if (success) {
343 | Intent intent = new Intent(LoginActivity.this, ListUsers.class);
344 | startActivity(intent);
345 | finish();
346 | } else {
347 | mPasswordView.setError(getString(R.string.error_incorrect_password));
348 | mPasswordView.requestFocus();
349 | }
350 | }
351 |
352 | @Override
353 | protected void onCancelled() {
354 | mAuthTask = null;
355 | showProgress(false);
356 | }
357 | }
358 | }
359 |
360 |
--------------------------------------------------------------------------------