diff --git a/Les Horaires/build.gradle b/Les Horaires/build.gradle index 45d606d..053efb5 100644 --- a/Les Horaires/build.gradle +++ b/Les Horaires/build.gradle @@ -25,8 +25,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 } lintOptions { @@ -35,6 +35,7 @@ android { } signingConfigs { + release { } } @@ -48,11 +49,18 @@ android { } } +configurations { + compile.exclude group: 'stax' + compile.exclude group: 'xpp3' +} + dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:+' compile 'com.android.support:support-v4:+' compile 'com.android.support:recyclerview-v7:+' + compile 'com.android.support:cardview-v7:+' + compile 'com.google.android.gms:play-services:4.3.23' compile 'com.melnykov:floatingactionbutton:1.2.0' compile 'com.pnikosis:materialish-progress:1.5' diff --git a/Les Horaires/src/main/AndroidManifest.xml b/Les Horaires/src/main/AndroidManifest.xml index e568bb1..eb3e82b 100644 --- a/Les Horaires/src/main/AndroidManifest.xml +++ b/Les Horaires/src/main/AndroidManifest.xml @@ -9,7 +9,6 @@ @@ -27,37 +26,37 @@ + android:parentActivityName=".listfavorites.ListFavoritesActivity"> + android:value=".listfavorites.ListFavoritesActivity"/> + android:parentActivityName=".listfavorites.ListFavoritesActivity"> + android:value=".listfavorites.ListFavoritesActivity"/> + android:parentActivityName=".shopdetail.DetailShopActivity"> + android:value=".shopdetail.DetailShopActivity"/> diff --git a/Les Horaires/src/main/java/com/amine/horaires/App.java b/Les Horaires/src/main/java/com/amine/horaires/App.java deleted file mode 100644 index 2bb59e8..0000000 --- a/Les Horaires/src/main/java/com/amine/horaires/App.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.amine.horaires; - -import android.app.Application; - -public class App extends Application { - - public App() { - super(); - } - - @Override - public void onCreate() { - super.onCreate(); - } -} diff --git a/Les Horaires/src/main/java/com/amine/horaires/MainActivity.java b/Les Horaires/src/main/java/com/amine/horaires/MainActivity.java deleted file mode 100644 index 16ea1c3..0000000 --- a/Les Horaires/src/main/java/com/amine/horaires/MainActivity.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.amine.horaires; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.telephony.TelephonyManager; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.View; -import android.widget.TextView; -import com.amine.horaires.bdd.FavorisDao; -import com.amine.horaires.models.Shop; -import com.amine.horaires.util.Configuration; -import com.amine.horaires.util.Parseur; -import com.melnykov.fab.FloatingActionButton; -import de.cketti.library.changelog.ChangeLog; - -import java.util.ArrayList; - -public class MainActivity extends OptionsActivity { - - private static RecyclerView mRecyclerView; - private static RecyclerView.Adapter mAdapter; - private static ArrayList myDataset; - private static TextView emptyView; - - static void razOrFavs(Context c) { - FavorisDao dao = FavorisDao.getInstance(c); - dao.open(); - myDataset = dao.getAllFavoris(); - dao.close(); - - if (myDataset.isEmpty()) { - mRecyclerView.setVisibility(View.GONE); - emptyView.setVisibility(View.VISIBLE); - } else { - mAdapter = new SearchAdapter(myDataset, c); - mRecyclerView.setAdapter(mAdapter); - mRecyclerView.setVisibility(View.VISIBLE); - emptyView.setVisibility(View.GONE); - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - checkLocale(); - ChangeLog cl = new ChangeLog(this); - if (cl.isFirstRun()) { - cl.getLogDialog().show(); - } - - mRecyclerView = (RecyclerView) findViewById(R.id.favs_list); - emptyView = (TextView) findViewById(R.id.empty_list); - - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - fab.attachToRecyclerView(mRecyclerView); - - fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - final Intent i = new Intent(getBaseContext(), ShopSearch.class); - startActivityForResult(i, 0); - } - }); - - // use this setting to improve performance if you know that changes - // in content do not change the layout size of the RecyclerView - mRecyclerView.setHasFixedSize(true); - - // use a linear layout manager - RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this); - mRecyclerView.setLayoutManager(mLayoutManager); - - // specify an adapter (see also next example) - myDataset = new ArrayList(); - - razOrFavs(getBaseContext()); - } - - private void checkLocale() { - TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); - Configuration.pays = tm.getSimCountryIso().toUpperCase(); - if (Configuration.pays == null || Configuration.pays.equals("") || Configuration.pays.isEmpty()) - Configuration.pays = MainActivity.this.getResources().getConfiguration().locale.getCountry(); - - SharedPreferences settings = getSharedPreferences("UserInfo", 0); - if (settings.getString("Pays", "") == null || !settings.getString("Pays", "").equals(Configuration.pays)) { - settings = getSharedPreferences("UserInfo", 0); - SharedPreferences.Editor editor = settings.edit(); - editor.putString("Pays", Configuration.pays); - editor.apply(); - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - switch (requestCode) { - case (0): { - if (resultCode == Activity.RESULT_OK) { - myDataset = new ArrayList(); - String result = data.getStringExtra("result"); - myDataset = new Parseur().parserShops(result); - if (myDataset.isEmpty()) { - mRecyclerView.setVisibility(View.GONE); - emptyView.setVisibility(View.VISIBLE); - } else { - mAdapter = new SearchAdapter(myDataset, getBaseContext()); - mRecyclerView.setAdapter(mAdapter); - mRecyclerView.setVisibility(View.VISIBLE); - emptyView.setVisibility(View.GONE); - } - } - break; - } - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.main_activity_actions_main, menu); - return super.onCreateOptionsMenu(menu); - } -} diff --git a/Les Horaires/src/main/java/com/amine/horaires/OptionsActivity.java b/Les Horaires/src/main/java/com/amine/horaires/OptionsActivity.java index 456242a..4e29436 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/OptionsActivity.java +++ b/Les Horaires/src/main/java/com/amine/horaires/OptionsActivity.java @@ -12,9 +12,8 @@ import com.amine.horaires.bdd.FavorisDao; import com.amine.horaires.models.Shop; import com.amine.horaires.util.Configuration; -class OptionsActivity extends AppCompatActivity { - MenuItem favMenu = null; - boolean isFav = false; +public class OptionsActivity extends AppCompatActivity { + @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); @@ -22,7 +21,10 @@ class OptionsActivity extends AppCompatActivity { return super.onCreateOptionsMenu(menu); } - public boolean onOptionsItemSelected(MenuItem item) { + /* + * Default operation, when the user click on the menu. + */ + public boolean defaultOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_mail: Intent intent = new Intent(Intent.ACTION_SENDTO); // it's not ACTION_SEND @@ -42,22 +44,7 @@ class OptionsActivity extends AppCompatActivity { dialog.show(); return true; case R.id.action_reload: - MainActivity.razOrFavs(OptionsActivity.this); - return true; - case R.id.action_fav: - FavorisDao dao = FavorisDao.getInstance(OptionsActivity.this); - if (isFav) { - // REMOVE - dao.open(); - dao.deleteFavori(Configuration.currentShop.getId()); - dao.close(); - updateFavStatus(false); - } else { - dao.open(); - dao.insertFavori(Configuration.currentShop); - dao.close(); - updateFavStatus(true); - } + //MainActivity.razOrFavs(OptionsActivity.this); return true; case android.R.id.home: this.finish(); @@ -67,23 +54,4 @@ class OptionsActivity extends AppCompatActivity { } } - private void updateFavStatus(boolean state) { - if (state) { - favMenu.setIcon(R.mipmap.ic_turned_in_black_24dp); - } else { - favMenu.setIcon(R.mipmap.ic_turned_in_not_black_24dp); - } - } - - void updateFavStatus() { - FavorisDao dao = FavorisDao.getInstance(OptionsActivity.this); - dao.open(); - Shop sh = dao.getFavori(Configuration.currentShop.getId()); - dao.close(); - if (sh == null) { - updateFavStatus(false); - } else { - updateFavStatus(true); - } - } } diff --git a/Les Horaires/src/main/java/com/amine/horaires/SearchAdapter.java b/Les Horaires/src/main/java/com/amine/horaires/SearchAdapter.java deleted file mode 100644 index 318468c..0000000 --- a/Les Horaires/src/main/java/com/amine/horaires/SearchAdapter.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.amine.horaires; - -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.RelativeLayout; -import android.widget.TextView; -import com.amine.horaires.models.Shop; - -import java.util.ArrayList; - -public class SearchAdapter extends RecyclerView.Adapter { - private final ArrayList mDataset; - private final Context c; - - // Provide a suitable constructor (depends on the kind of dataset) - public SearchAdapter(ArrayList myDataset, Context c) { - mDataset = myDataset; - this.c = c; - } - - // Create new views (invoked by the layout manager) - @Override - public SearchAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, - int viewType) { - // create a new view - View v = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.fav_list_item, parent, false); - // set the view's size, margins, paddings and layout parameters - - return new ViewHolder((RelativeLayout) v, c, mDataset); - } - - // Replace the contents of a view (invoked by the layout manager) - @Override - public void onBindViewHolder(ViewHolder holder, final int position) { - // - get element from your dataset at this position - // - replace the contents of the view with that element - holder.shopAddr.setText(mDataset.get(position).getAdresse()); - holder.shopName.setText(mDataset.get(position).getName()); - } - - // Return the size of your dataset (invoked by the layout manager) - @Override - public int getItemCount() { - return mDataset.size(); - } - - // Provide a reference to the views for each data item - // Complex data items may need more than one view per item, and - // you provide access to all the views for a data item in a view holder - public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - // each data item is just a string in this case - public final TextView shopName; - public final TextView shopAddr; - private final Context c; - private final ArrayList mDataset; - - public ViewHolder(RelativeLayout v, Context c, ArrayList mDataset) { - super(v); - v.setOnClickListener(this); - shopName = (TextView) v.findViewById(R.id.shop_name); - shopAddr = (TextView) v.findViewById(R.id.shop_adress); - this.c = c; - this.mDataset = mDataset; - } - - @Override - public void onClick(View view) { - final Intent i = new Intent(view.getContext(), ShopDisplay.class); - final Handler handler = new Handler(); - Runnable t = new Runnable() { - public void run() { - i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - i.putExtra("shop", mDataset.get(getLayoutPosition())); - c.startActivity(i); - } - }; - - handler.post(t); - } - - } -} diff --git a/Les Horaires/src/main/java/com/amine/horaires/ShopSearch.java b/Les Horaires/src/main/java/com/amine/horaires/ShopSearch.java deleted file mode 100644 index b5b594f..0000000 --- a/Les Horaires/src/main/java/com/amine/horaires/ShopSearch.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.amine.horaires; - -import android.content.Intent; -import android.location.Location; -import android.os.AsyncTask; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.RelativeLayout; -import android.widget.Toast; -import com.amine.horaires.util.MyLocation; -import com.amine.horaires.util.Utils; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.ProtocolException; -import java.net.URL; -import java.util.Scanner; - -public class ShopSearch extends OptionsActivity { - private MyLocation myLocation; - private RelativeLayout loading; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.shop_search); - - final EditText name = (EditText) findViewById(R.id.name); - final EditText location = (EditText) findViewById(R.id.location); - loading = (RelativeLayout) findViewById(R.id.loading); - Button searchButton = (Button) findViewById(R.id.searchAction); - - searchButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - if (name.getText().toString().trim().length() > 0 && location.getText().toString().trim().length() > 0) { - loading.setVisibility(View.VISIBLE); - SearchTask s = new SearchTask(); - s.execute(Utils.generateUrlForTextLocation(name.getText().toString(), location.getText().toString())); - } - } - }); - - findViewById(R.id.gpsAction).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - - - loading.setVisibility(View.VISIBLE); - - MyLocation.LocationResult locationResult = new MyLocation.LocationResult() { - @Override - public void gotLocation(Location location) { - if (location == null) { - Toast.makeText(getApplicationContext(), getResources().getString(R.string.fail_localize_user), Toast.LENGTH_SHORT).show(); - } else { - URL url = Utils.generateUrlForLatLng(name.getText().toString(), location.getLatitude() + "", location.getLongitude() + ""); - SearchTask s = new SearchTask(); - s.execute(url); - } - } - }; - myLocation = new MyLocation(); - boolean gotLocation = myLocation.getLocation(getApplicationContext(), - locationResult); - if (!gotLocation) { - Toast.makeText(getApplicationContext(), getResources().getString(R.string.fail_localize_user), Toast.LENGTH_SHORT).show(); - } - } - }); - } - - private class SearchTask extends AsyncTask { - - @Override - protected String doInBackground(URL... params) { - HttpURLConnection conn = null; - InputStream is = null; - String contentAsString = ""; - URL url = null; - try { - url = params[0]; - conn = (HttpURLConnection) url.openConnection(); - conn.setReadTimeout(10000 /* milliseconds */); - conn.setConnectTimeout(15000 /* milliseconds */); - conn.setRequestMethod("GET"); - conn.setDoInput(true); - - // Starts the query - conn.connect(); - is = conn.getInputStream(); - - // Convert the InputStream into a String - - Scanner reader = new Scanner(is, "ISO-8859-1"); - while (reader.hasNextLine()) { - contentAsString = contentAsString + reader.nextLine(); - } - } catch (MalformedURLException e) { - Log.e("ShopSearch", "The API doesn't respond correctly. Asked url was " + url.toString(), e); - } catch (ProtocolException e) { - Log.e("ShopSearch", "The protocol doesn't seems to be HTTP. Url was " + url.toString(), e); - } catch (IOException e) { - Log.e("ShopSearch", "The API response is not readable. Url was " + url.toString(), e); - } finally { - // Makes sure that the InputStream is closed after the app is finished using it. - if (is != null) - try { - is.close(); - } catch (IOException e) {} - if (conn != null) - conn.disconnect(); - } - return contentAsString; - } - - @Override - protected void onPostExecute(String string) { - super.onPostExecute(string); - - loading.setVisibility(View.GONE); - Intent resultIntent = new Intent(); - resultIntent.putExtra("result", string); - setResult(MainActivity.RESULT_OK, resultIntent); - finish(); - } - } -} diff --git a/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisBdd.java b/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisBdd.java index f85a63c..b4d08fe 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisBdd.java +++ b/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisBdd.java @@ -55,4 +55,4 @@ class FavorisBdd extends SQLiteOpenHelper { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } -} +} \ No newline at end of file diff --git a/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisDao.java b/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisDao.java index d2f1ee5..bff64d8 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisDao.java +++ b/Les Horaires/src/main/java/com/amine/horaires/bdd/FavorisDao.java @@ -65,6 +65,10 @@ public class FavorisDao { bdd = maBaseSQLite.getWritableDatabase(); } + public void openReadable() { + bdd = maBaseSQLite.getWritableDatabase(); + } + public void close() { bdd.close(); } @@ -156,4 +160,4 @@ public class FavorisDao { cursor.close(); return list; } -} +} \ No newline at end of file diff --git a/Les Horaires/src/main/java/com/amine/horaires/listfavorites/ListFavoritesActivity.java b/Les Horaires/src/main/java/com/amine/horaires/listfavorites/ListFavoritesActivity.java new file mode 100644 index 0000000..1d99490 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/listfavorites/ListFavoritesActivity.java @@ -0,0 +1,134 @@ +package com.amine.horaires.listfavorites; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.telephony.TelephonyManager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import com.amine.horaires.OptionsActivity; +import com.amine.horaires.R; +import com.amine.horaires.bdd.FavorisDao; +import com.amine.horaires.listshop.ListShopsFragment; +import com.amine.horaires.models.Shop; +import com.amine.horaires.search.SearchActivity; +import com.amine.horaires.util.Configuration; +import com.melnykov.fab.FloatingActionButton; +import de.cketti.library.changelog.ChangeLog; + +import java.util.ArrayList; +import java.util.List; + +public class ListFavoritesActivity extends OptionsActivity { + + private Fragment currentFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + if (findViewById(R.id.fragmentContainer) != null) { + + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; + } + + // Create a new Fragment to be placed in the activity layout + currentFragment = new ListShopsFragment(); + + // Get all favorites shops + FavorisDao dao = FavorisDao.getInstance(getApplicationContext()); + dao.openReadable(); + ArrayList shops = dao.getAllFavoris(); + + // Update the list + ListFavoritesSingleton.getInstance().setFavoritesShops(shops); + + Bundle args = new Bundle(); + args.putParcelableArrayList("list", shops); + args.putString("errorEmptyList", getErrorMessageListFavoritesEmpty()); + + currentFragment.setArguments(args); + + // Add the fragment to the 'fragment_container' FrameLayout + getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, currentFragment).commit(); + } + + // Save user country + saveUserCountry(); + + // Display changelog + ChangeLog cl = new ChangeLog(this); + if (cl.isFirstRun()) { + cl.getLogDialog().show(); + } + + // Configure SearchButton + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + search(); + } + }); + } + + @Override + public void onResume(){ + super.onResume(); + + Log.w("com.amine.horaires", "onResume()"); + + // We should tell to the list that we have updated something + if (currentFragment != null) { + List shops = ListFavoritesSingleton.getInstance().getFavoritesShops(); + + if (!shops.isEmpty()) { + ((ListShopsFragment) currentFragment).updateList(shops); + } + } + } + + /** + * Used when the fragment want to launch the Search. + */ + private void search() { + Intent intent = new Intent(this, SearchActivity.class); + startActivity(intent); + } + + public String getErrorMessageListFavoritesEmpty() { + return getString(R.string.listvide); + } + + /** + * We save the user country to display the best api url. + */ + private void saveUserCountry() { + TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); + Configuration.pays = tm.getSimCountryIso().toUpperCase(); + if (Configuration.pays == null || Configuration.pays.equals("") || Configuration.pays.isEmpty()) + Configuration.pays = ListFavoritesActivity.this.getResources().getConfiguration().locale.getCountry(); + + SharedPreferences settings = getSharedPreferences("UserInfo", 0); + if (settings.getString("Pays", "") == null || !settings.getString("Pays", "").equals(Configuration.pays)) { + settings = getSharedPreferences("UserInfo", 0); + SharedPreferences.Editor editor = settings.edit(); + editor.putString("Pays", Configuration.pays); + editor.apply(); + } + } + + public boolean onOptionsItemSelected(MenuItem menuItem) { + return defaultOptionsItemSelected (menuItem); + } +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/listshop/ListShopsAdapter.java b/Les Horaires/src/main/java/com/amine/horaires/listshop/ListShopsAdapter.java new file mode 100644 index 0000000..f0da068 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/listshop/ListShopsAdapter.java @@ -0,0 +1,65 @@ +package com.amine.horaires.listshop; + +import android.support.v7.widget.CardView; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import com.amine.horaires.R; +import com.amine.horaires.models.Shop; + +import java.util.List; + +public class ListShopsAdapter extends RecyclerView.Adapter { + + private List shops; + + ListShopsAdapter(List shop){ + this.shops = shop; + } + + public List getShops() {return shops; } + + public void setShops(List shops) { this.shops = shops; } + + public class ShopViewHolder extends RecyclerView.ViewHolder { + + private CardView cv; + private TextView shopName; + private TextView shopAddress; + + ShopViewHolder(View itemView) { + super(itemView); + cv = (CardView)itemView.findViewById(R.id.card_view); + shopName = (TextView)itemView.findViewById(R.id.shop_name); + shopAddress = (TextView)itemView.findViewById(R.id.shop_adress); + } + + public TextView getShopName() { + return shopName; + } + + public TextView getShopAddress() { + return shopAddress; + } + } + + @Override + public ShopViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_shop_item, parent, false); + ShopViewHolder pvh = new ShopViewHolder(v); + return pvh; + } + + @Override + public void onBindViewHolder(ShopViewHolder holder, int position) { + holder.getShopName().setText(shops.get(position).getName()); + holder.getShopAddress().setText(shops.get(position).getAdresse()); + } + + @Override + public int getItemCount() { + return shops.size(); + } +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/listshop/ListShopsFragment.java b/Les Horaires/src/main/java/com/amine/horaires/listshop/ListShopsFragment.java new file mode 100644 index 0000000..a66732b --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/listshop/ListShopsFragment.java @@ -0,0 +1,90 @@ +package com.amine.horaires.listshop; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import com.amine.horaires.R; +import com.amine.horaires.models.Shop; +import com.amine.horaires.shopdetail.DetailShopActivity; +import com.amine.horaires.util.RecyclerItemClickListener; +import com.melnykov.fab.FloatingActionButton; + +import java.util.ArrayList; +import java.util.List; + +public class ListShopsFragment extends Fragment { + private List shops; + private ListShopsAdapter adapter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_list_shops, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + shops = getArguments().getParcelableArrayList("list"); + + // Get list android component + RecyclerView favsRecyclerView = (RecyclerView) getView().findViewById(R.id.list); + + if (shops.isEmpty()) { + favsRecyclerView.setVisibility(View.GONE); + + TextView emptyView = (TextView) getView().findViewById(R.id.empty_list); + emptyView.setVisibility(View.VISIBLE); + emptyView.setText(getArguments().getString("errorEmptyList")); + } + else { + // Create an Adapter: provides access to the data items and is also responsible for making a View for each item + adapter = new ListShopsAdapter(shops); + favsRecyclerView.setAdapter(adapter); + + // Create a LayoutManager: Layout Manager is responsible for measuring and positioning item views within a RecyclerView + LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext()); + favsRecyclerView.setLayoutManager(layoutManager); + + // Improve performances, the list have a fixed size + favsRecyclerView.setHasFixedSize(true); + + // Open the shop on click + favsRecyclerView.addOnItemTouchListener( + new RecyclerItemClickListener(getActivity().getApplicationContext(), + new RecyclerItemClickListener.OnItemClickListener() { + @Override + public void onItemClick(View view, final int position) { + final Intent i = new Intent(view.getContext(), DetailShopActivity.class); + final Handler handler = new Handler(); + Runnable t = new Runnable() { + public void run() { + i.putExtra("shop", shops.get(position)); + getActivity().startActivity(i); + } + }; + + handler.post(t); + } + } + ) + ); + } + } + + public void updateList (List listOfShops) { + adapter.setShops(listOfShops); + adapter.notifyDataSetChanged(); + } + + + +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/models/Shop.java b/Les Horaires/src/main/java/com/amine/horaires/models/Shop.java index 78d96b4..397dc58 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/models/Shop.java +++ b/Les Horaires/src/main/java/com/amine/horaires/models/Shop.java @@ -219,6 +219,24 @@ public class Shop implements Parcelable { return 0; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Shop shop = (Shop) o; + + if (name != null ? !name.equals(shop.name) : shop.name != null) return false; + return !(adresse != null ? !adresse.equals(shop.adresse) : shop.adresse != null); + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (adresse != null ? adresse.hashCode() : 0); + return result; + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); @@ -237,4 +255,4 @@ public class Shop implements Parcelable { dest.writeByte((byte) (wifi ? 1 : 0)); dest.writeByte((byte) (AccesHandicape ? 1 : 0)); } -} +} \ No newline at end of file diff --git a/Les Horaires/src/main/java/com/amine/horaires/search/OnSearchResult.java b/Les Horaires/src/main/java/com/amine/horaires/search/OnSearchResult.java new file mode 100644 index 0000000..3fe3f40 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/search/OnSearchResult.java @@ -0,0 +1,10 @@ +package com.amine.horaires.search; + + +import com.amine.horaires.models.Shop; + +import java.util.List; + +public interface OnSearchResult { + void onPostExecute(List result); +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/search/SearchActivity.java b/Les Horaires/src/main/java/com/amine/horaires/search/SearchActivity.java new file mode 100644 index 0000000..19ab3f8 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/search/SearchActivity.java @@ -0,0 +1,94 @@ +package com.amine.horaires.search; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import com.amine.horaires.listshop.ListShopsFragment; +import com.amine.horaires.OptionsActivity; +import com.amine.horaires.R; +import com.amine.horaires.models.Shop; +import com.melnykov.fab.FloatingActionButton; + +import java.util.ArrayList; +import java.util.List; + +public class SearchActivity extends OptionsActivity implements OnSearchResult { + + private FloatingActionButton fab; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_search); + + if (findViewById(R.id.fragmentContainer) != null) { + + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; + } + + // Create a new Fragment to be placed in the activity layout + SearchFragment firstFragment = new SearchFragment(); + + // Add the fragment to the 'fragmentContainer' FrameLayout + getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, firstFragment).commit(); + } + + // Configure SearchButton + fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + search(); + } + }); + fab.setVisibility(View.INVISIBLE); + } + + /** + * Used when the fragment want to launch the Search. + */ + private void search() { + Intent intent = new Intent(this, SearchActivity.class); + startActivity(intent); + } + + /** + * The search have found some result, need to update the fragments + */ + @Override + public void onPostExecute(List result) { + ListShopsFragment listSearchResultFragment = new ListShopsFragment(); + + Bundle args = new Bundle(); + args.putParcelableArrayList("list", (ArrayList) result); + args.putString("errorEmptyList", getErrorMessageResultListEmpty()); + + listSearchResultFragment.setArguments(args); + + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + + transaction.replace(R.id.fragmentContainer, listSearchResultFragment); + transaction.addToBackStack(null); + + // Commit the transaction + transaction.commit(); + + fab.setVisibility(View.VISIBLE); + } + + public boolean onOptionsItemSelected(MenuItem menuItem) { + return defaultOptionsItemSelected (menuItem); + } + + public String getErrorMessageResultListEmpty() { + return getString(R.string.resultatRechercheVide); + } +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/search/SearchFragment.java b/Les Horaires/src/main/java/com/amine/horaires/search/SearchFragment.java new file mode 100644 index 0000000..3766346 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/search/SearchFragment.java @@ -0,0 +1,175 @@ +package com.amine.horaires.search; + + +import android.content.Intent; +import android.location.Location; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.Toast; +import com.amine.horaires.R; +import com.amine.horaires.models.Shop; +import com.amine.horaires.shopdetail.UpdateActionBar; +import com.amine.horaires.util.MyLocation; +import com.amine.horaires.util.Parseur; +import com.amine.horaires.util.Utils; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.util.List; +import java.util.Scanner; + +public class SearchFragment extends Fragment { + + private EditText name; + private EditText location; + private Button searchButton; + + private RelativeLayout loading; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_search, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + // If the user is not connected to a network, display an error + if (!Utils.checkDeviceConnected (getActivity().getApplicationContext())) { + Toast.makeText(getActivity().getApplicationContext(), getResources().getString(R.string.fail_connexion), Toast.LENGTH_SHORT).show(); + } + else { + + // Android component form + name = (EditText) getView().findViewById(R.id.name); + location = (EditText) getView().findViewById(R.id.location); + searchButton = (Button) getView().findViewById(R.id.searchAction); + + // Load icons. Useful to show to the user, that something is loading. + loading = (RelativeLayout) getView().findViewById(R.id.loading); + + searchButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + // If the user complete the form + if (name.getText().toString().trim().length() > 0 && location.getText().toString().trim().length() > 0) { + + // Show to the user that we performs the user + loading.setVisibility(View.VISIBLE); + + SearchTask s = new SearchTask(); + s.execute(Utils.generateUrlForTextLocation(name.getText().toString(), location.getText().toString())); + } + } + }); + + getView().findViewById(R.id.gpsAction).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + if (name.getText().toString().trim().length() > 0) { + + loading.setVisibility(View.VISIBLE); + + MyLocation myLocation = new MyLocation(); + boolean gotLocation = myLocation.getLocation(getActivity().getApplicationContext(), new MyLocation.LocationResult() { + @Override + public void gotLocation(Location location) { + if (location == null) { + displayLocalizeError(); + } else { + URL url = Utils.generateUrlForLatLng(name.getText().toString(), location.getLatitude() + "", location.getLongitude() + ""); + SearchTask s = new SearchTask(); + s.execute(url); + } + } + }); + + if (!gotLocation) { + displayLocalizeError(); + } + + } else { + Toast.makeText(getActivity().getApplicationContext(), getResources().getString(R.string.fail_fill_form), Toast.LENGTH_SHORT).show(); + } + } + }); + } + } + + private void displayLocalizeError () { + Toast.makeText(getActivity().getApplicationContext(), getResources().getString(R.string.fail_localize_user), Toast.LENGTH_SHORT).show(); + } + + private class SearchTask extends AsyncTask { + + @Override + protected String doInBackground(URL... params) { + HttpURLConnection conn = null; + InputStream is = null; + String contentAsString = ""; + URL url = null; + try { + url = params[0]; + conn = (HttpURLConnection) url.openConnection(); + conn.setReadTimeout(10000 /* milliseconds */); + conn.setConnectTimeout(15000 /* milliseconds */); + conn.setRequestMethod("GET"); + conn.setDoInput(true); + + // Starts the query + conn.connect(); + is = conn.getInputStream(); + + // Convert the InputStream into a String + + Scanner reader = new Scanner(is, "ISO-8859-1"); + while (reader.hasNextLine()) { + contentAsString = contentAsString + reader.nextLine(); + } + } catch (MalformedURLException e) { + Log.e("ShopSearch", "The API doesn't respond correctly. Asked url was " + url.toString(), e); + } catch (ProtocolException e) { + Log.e("ShopSearch", "The protocol doesn't seems to be HTTP. Url was " + url.toString(), e); + } catch (IOException e) { + Log.e("ShopSearch", "The API response is not readable. Url was " + url.toString(), e); + } finally { + // Makes sure that the InputStream is closed after the app is finished using it. + if (is != null) + try { + is.close(); + } catch (IOException e) {} + if (conn != null) + conn.disconnect(); + } + return contentAsString; + } + + @Override + protected void onPostExecute(String string) { + super.onPostExecute(string); + + loading.setVisibility(View.GONE); + + List shops = new Parseur().parserShops(string); + + ((OnSearchResult) getActivity()).onPostExecute(shops); + } + } +} + + diff --git a/Les Horaires/src/main/java/com/amine/horaires/shopdetail/DetailShopActivity.java b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/DetailShopActivity.java new file mode 100644 index 0000000..60628d3 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/DetailShopActivity.java @@ -0,0 +1,82 @@ +package com.amine.horaires.shopdetail; + +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import com.amine.horaires.OptionsActivity; +import com.amine.horaires.R; +import com.amine.horaires.models.Shop; + +public class DetailShopActivity extends OptionsActivity implements UpdateActionBar { + + private MenuItem favMenu; + private DetailShopFragment detailShopFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_detail_shop); + + Shop s = getIntent().getExtras().getParcelable("shop"); + + if (findViewById(R.id.fragmentContainer) != null) { + + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; + } + + // Create a new Fragment to be placed in the activity layout + detailShopFragment = new DetailShopFragment(); + + Bundle args = new Bundle(); + args.putParcelable("shop", s); + + detailShopFragment.setArguments(args); + + // Add the fragment to the 'fragmentContainer' FrameLayout + getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, detailShopFragment).commit(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_activity_actions_shop, menu); + + favMenu = menu.findItem(R.id.action_fav); + + updateFavsIcon(detailShopFragment.getFav()); + + return super.onCreateOptionsMenu(menu); + } + + public boolean onOptionsItemSelected(MenuItem menuItem) { + boolean isActionPerformed = defaultOptionsItemSelected(menuItem); + + if (isActionPerformed) { + return isActionPerformed; + } + else { + if (menuItem.getItemId() == R.id.action_fav) { + detailShopFragment.updateFav(); + return true; + } + } + + return false; + } + + @Override + public void updateFavsIcon(boolean isFav) { + + if (isFav) { + favMenu.setIcon(R.mipmap.ic_turned_in_black_24dp); + } else { + favMenu.setIcon(R.mipmap.ic_turned_in_not_black_24dp); + } + } +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/ShopDisplay.java b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/DetailShopFragment.java similarity index 67% rename from Les Horaires/src/main/java/com/amine/horaires/ShopDisplay.java rename to Les Horaires/src/main/java/com/amine/horaires/shopdetail/DetailShopFragment.java index 89ca5a6..7a978f7 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/ShopDisplay.java +++ b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/DetailShopFragment.java @@ -1,23 +1,23 @@ -package com.amine.horaires; +package com.amine.horaires.shopdetail; -import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import com.amine.horaires.R; import com.amine.horaires.bdd.FavorisDao; +import com.amine.horaires.listfavorites.ListFavoritesSingleton; import com.amine.horaires.models.Shop; -import com.amine.horaires.util.Configuration; +import com.amine.horaires.updateshop.UpdateShopActivity; import com.amine.horaires.util.Parseur; import com.amine.horaires.util.Utils; import com.melnykov.fab.FloatingActionButton; @@ -31,41 +31,48 @@ import java.net.URL; import java.util.List; import java.util.Scanner; -public class ShopDisplay extends OptionsActivity { +public class DetailShopFragment extends Fragment implements UpdateFav { + + private boolean isFav = false; + private Shop s; @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.shop_display); - Shop s = getIntent().getExtras().getParcelable("shop"); + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_detail_shop, container, false); + } - Configuration.currentShop = s; + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); - FavorisDao dao = FavorisDao.getInstance(ShopDisplay.this); - dao.open(); + s = getArguments().getParcelable("shop"); + FavorisDao dao = FavorisDao.getInstance(getActivity().getApplicationContext()); + dao.openReadable(); List fs = dao.getAllFavoris(); - dao.close(); while (!isFav && !fs.isEmpty()) { - isFav = fs.remove(0).getId() == Configuration.currentShop.getId(); + isFav = fs.remove(0).getId() == s.getId(); } + if (isFav) { SearchTask st = new SearchTask(); st.execute(Utils.generateUrlForId(s.getId())); - s = Configuration.currentShop; + dao.open(); dao.updateFavori(s); dao.close(); } + generateView(s); - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + FloatingActionButton fab = (FloatingActionButton) getView().findViewById(R.id.fab); final Shop finalS = s; fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - final Intent i = new Intent(getBaseContext(), ShopUpdate.class); + final Intent i = new Intent(getActivity().getApplicationContext(), UpdateShopActivity.class); i.putExtra("shop", finalS); startActivity(i); } @@ -73,20 +80,19 @@ public class ShopDisplay extends OptionsActivity { } private void generateView(final Shop s) { - Configuration.currentShop = s; - ImageView imageResult = (ImageView) findViewById(R.id.imageView); + ImageView imageResult = (ImageView) getView().findViewById(R.id.imageView); ImageTask t = new ImageTask(imageResult); t.execute(s.getHoraires()); - TextView shopName = (TextView) findViewById(R.id.shopName); - TextView shopAddress = (TextView) findViewById(R.id.shopAdress); - TextView shopOpen = (TextView) findViewById(R.id.shopOpen); - TextView shopStatus = (TextView) findViewById(R.id.shopStatus); - ImageView wifi = (ImageView) findViewById(R.id.wifi); - ImageView parking = (ImageView) findViewById(R.id.parking); - ImageView access = (ImageView) findViewById(R.id.handi); + TextView shopName = (TextView) getView().findViewById(R.id.shopName); + TextView shopAddress = (TextView) getView().findViewById(R.id.shopAdress); + TextView shopOpen = (TextView) getView().findViewById(R.id.shopOpen); + TextView shopStatus = (TextView) getView().findViewById(R.id.shopStatus); + ImageView wifi = (ImageView) getView().findViewById(R.id.wifi); + ImageView parking = (ImageView) getView().findViewById(R.id.parking); + ImageView access = (ImageView) getView().findViewById(R.id.handi); shopName.setText(s.getName()); shopAddress.setText(s.getAdresse()); @@ -107,7 +113,7 @@ public class ShopDisplay extends OptionsActivity { parking.setAlpha((float) 0.1); } - findViewById(R.id.imageView).setOnClickListener(new View.OnClickListener() { + getView().findViewById(R.id.imageView).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(s.getUrl())); @@ -115,7 +121,7 @@ public class ShopDisplay extends OptionsActivity { } }); - findViewById(R.id.callButton).setOnClickListener(new View.OnClickListener() { + getView().findViewById(R.id.callButton).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { String numeroAppeler = "tel:" + s.getTel(); startActivity(new Intent(Intent.ACTION_DIAL, Uri @@ -123,7 +129,7 @@ public class ShopDisplay extends OptionsActivity { } }); - findViewById(R.id.gpsButton).setOnClickListener(new View.OnClickListener() { + getView().findViewById(R.id.gpsButton).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new @@ -135,24 +141,36 @@ public class ShopDisplay extends OptionsActivity { } }); - } - // @todo: use this to update the shop if connected. - private boolean checkDeviceConnected() { - ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - // Need permission : android.permission.ACCESS_NETWORK_STATE - NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); - - return (networkInfo != null && networkInfo.isConnected()); } @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.main_activity_actions_shop, menu); - favMenu = menu.findItem(R.id.action_fav); - updateFavStatus(); - return super.onCreateOptionsMenu(menu); + public void updateFav() { + FavorisDao dao = FavorisDao.getInstance(getActivity().getApplicationContext()); + + if (isFav) { + dao.open(); + dao.deleteFavori(s.getId()); + dao.close(); + + // Notify the favorites list that he remove a shop + ListFavoritesSingleton.getInstance().getFavoritesShops().remove(s); + + } else { + dao.open(); + dao.insertFavori(s); + dao.close(); + + // Notify the favorites list that he added a shop + ListFavoritesSingleton.getInstance().getFavoritesShops().add(s); + } + + isFav = !isFav; + ((UpdateActionBar) getActivity()).updateFavsIcon(isFav); + } + + public boolean getFav() { + return isFav; } public class ImageTask extends AsyncTask { @@ -182,7 +200,7 @@ public class ShopDisplay extends OptionsActivity { conn.disconnect(); } catch (MalformedURLException e) { - Log.e("ShopDisplay", "The API doesn't respond correctly. Asked url was "+url.toString(), e); + Log.e("ShopDisplay", "The API doesn't respond correctly. Asked url was " + url.toString(), e); } catch (ProtocolException e) { Log.e("ShopDisplay", "The protocol doesn't seems to be HTTP. Url was " + url.toString(), e); } catch (IOException e) { @@ -231,11 +249,11 @@ public class ShopDisplay extends OptionsActivity { contentAsString = contentAsString + reader.nextLine(); } } catch (MalformedURLException e) { - Log.e("ShopDisplay", "The API doesn't respond correctly. Asked url was " + url.toString(), e); + Log.e("ShopDisplay", "The API doesn't respond correctly. Asked url was " + url.toString(), e); } catch (ProtocolException e) { Log.e("ShopDisplay", "The protocol doesn't seems to be HTTP. Url was " + url.toString(), e); } catch (IOException e) { - Log.e("ShopDisplay", "The API response is not readable. Url was " + url.toString(), e); + Log.e("ShopDisplay", "The API response is not readable. Url was " + url.toString(), e); } finally { // Makes sure that the InputStream is closed after the app is finished using it. if (is != null) @@ -251,7 +269,8 @@ public class ShopDisplay extends OptionsActivity { @Override protected void onPostExecute(String string) { super.onPostExecute(string); - Configuration.currentShop = new Parseur().parserShops(string).get(0); + s = new Parseur().parserShops(string).get(0); } } + } diff --git a/Les Horaires/src/main/java/com/amine/horaires/shopdetail/UpdateActionBar.java b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/UpdateActionBar.java new file mode 100644 index 0000000..c1004d9 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/UpdateActionBar.java @@ -0,0 +1,5 @@ +package com.amine.horaires.shopdetail; + +public interface UpdateActionBar { + void updateFavsIcon (boolean isFav); +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/shopdetail/UpdateFav.java b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/UpdateFav.java new file mode 100644 index 0000000..37ee40b --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/shopdetail/UpdateFav.java @@ -0,0 +1,5 @@ +package com.amine.horaires.shopdetail; + +public interface UpdateFav { + void updateFav (); +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/UpdateAdapter.java b/Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateAdapter.java similarity index 98% rename from Les Horaires/src/main/java/com/amine/horaires/UpdateAdapter.java rename to Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateAdapter.java index db21536..8f14fd8 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/UpdateAdapter.java +++ b/Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateAdapter.java @@ -1,4 +1,4 @@ -package com.amine.horaires; +package com.amine.horaires.updateshop; import android.app.FragmentManager; import android.content.Context; @@ -6,6 +6,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; +import com.amine.horaires.R; import com.amine.horaires.models.Horaires; import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; diff --git a/Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateShopActivity.java b/Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateShopActivity.java new file mode 100644 index 0000000..a7b6a89 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateShopActivity.java @@ -0,0 +1,39 @@ +package com.amine.horaires.updateshop; + +import android.os.Bundle; +import com.amine.horaires.OptionsActivity; +import com.amine.horaires.R; +import com.amine.horaires.models.Shop; +import com.amine.horaires.shopdetail.DetailShopFragment; + +public class UpdateShopActivity extends OptionsActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_update_shop); + + Shop s = getIntent().getExtras().getParcelable("shop"); + + if (findViewById(R.id.fragmentContainer) != null) { + + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; + } + + // Create a new Fragment to be placed in the activity layout + UpdateShopFragment updateShopFragment = new UpdateShopFragment(); + + Bundle args = new Bundle(); + args.putParcelable("shop", s); + + updateShopFragment.setArguments(args); + + // Add the fragment to the 'fragmentContainer' FrameLayout + getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, updateShopFragment).commit(); + } + } +} diff --git a/Les Horaires/src/main/java/com/amine/horaires/ShopUpdate.java b/Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateShopFragment.java similarity index 78% rename from Les Horaires/src/main/java/com/amine/horaires/ShopUpdate.java rename to Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateShopFragment.java index d2e3c19..3210840 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/ShopUpdate.java +++ b/Les Horaires/src/main/java/com/amine/horaires/updateshop/UpdateShopFragment.java @@ -1,13 +1,17 @@ -package com.amine.horaires; +package com.amine.horaires.updateshop; import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.util.Log; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.Button; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Toast; +import com.amine.horaires.R; import com.amine.horaires.models.Horaires; import com.amine.horaires.models.Shop; import com.amine.horaires.util.Utils; @@ -24,28 +28,34 @@ import java.util.Collections; import java.util.HashMap; import java.util.Scanner; -public class ShopUpdate extends OptionsActivity { +public class UpdateShopFragment extends Fragment { private ArrayList h; private RelativeLayout loading; @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.update_shop); + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_update_shop, container, false); + } - loading = (RelativeLayout) findViewById(R.id.loading); + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); - final Shop s = getIntent().getExtras().getParcelable("shop"); - ListView hList = (ListView) findViewById(R.id.horaires_list); - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - Button save = (Button) findViewById(R.id.button); + loading = (RelativeLayout) getView().findViewById(R.id.loading); + + final Shop s = getArguments().getParcelable("shop"); + + ListView hList = (ListView) getView().findViewById(R.id.horaires_list); + FloatingActionButton fab = (FloatingActionButton) getView().findViewById(R.id.fab); + Button save = (Button) getView().findViewById(R.id.button); h = new ArrayList(); initializeHoraires(); - final UpdateAdapter adapter = new UpdateAdapter(this, h, getFragmentManager()); + final UpdateAdapter adapter = new UpdateAdapter(getActivity().getApplicationContext(), h, getActivity().getFragmentManager()); hList.setAdapter(adapter); @@ -137,7 +147,7 @@ public class ShopUpdate extends OptionsActivity { protected void onPostExecute(String string) { loading.setVisibility(View.GONE); super.onPostExecute(string); - Toast.makeText(getApplicationContext(), getResources().getString(R.string.success_update_shop), Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity().getApplicationContext(), getResources().getString(R.string.success_update_shop), Toast.LENGTH_SHORT).show(); } } } diff --git a/Les Horaires/src/main/java/com/amine/horaires/util/RecyclerItemClickListener.java b/Les Horaires/src/main/java/com/amine/horaires/util/RecyclerItemClickListener.java new file mode 100644 index 0000000..586af96 --- /dev/null +++ b/Les Horaires/src/main/java/com/amine/horaires/util/RecyclerItemClickListener.java @@ -0,0 +1,39 @@ +package com.amine.horaires.util; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { + private OnItemClickListener mListener; + + public interface OnItemClickListener { + void onItemClick(View view, int position); + } + + GestureDetector mGestureDetector; + + public RecyclerItemClickListener(Context context, OnItemClickListener listener) { + mListener = listener; + mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { + @Override public boolean onSingleTapUp(MotionEvent e) { + return true; + } + }); + } + + @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { + View childView = view.findChildViewUnder(e.getX(), e.getY()); + if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { + mListener.onItemClick(childView, view.getChildPosition(childView)); + return true; + } + return false; + } + + @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { } + + @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {} +} \ No newline at end of file diff --git a/Les Horaires/src/main/java/com/amine/horaires/util/Utils.java b/Les Horaires/src/main/java/com/amine/horaires/util/Utils.java index 5855140..ae551db 100644 --- a/Les Horaires/src/main/java/com/amine/horaires/util/Utils.java +++ b/Les Horaires/src/main/java/com/amine/horaires/util/Utils.java @@ -1,5 +1,8 @@ package com.amine.horaires.util; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; import android.util.Log; import java.io.UnsupportedEncodingException; @@ -10,6 +13,10 @@ import java.net.URLEncoder; public class Utils { public static URL generateUrlForTextLocation(String name, String location) { try { + System.out.print(new URL(Configuration.getAPIUrl() + "/api?key=" + + Configuration.key + "&h=" + Configuration.hashtag + + "&get=shops" + "&loc=" + URLEncoder.encode(location, "ISO-8859-1") + + "&name=" + URLEncoder.encode(name, "ISO-8859-1"))); return new URL(Configuration.getAPIUrl() + "/api?key=" + Configuration.key + "&h=" + Configuration.hashtag + "&get=shops" + "&loc=" + URLEncoder.encode(location, "ISO-8859-1") @@ -63,4 +70,12 @@ public class Utils { return null; } } + + public static boolean checkDeviceConnected(Context context) { + ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + // Need permission : android.permission.ACCESS_NETWORK_STATE + NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); + + return (networkInfo != null && networkInfo.isConnected()); + } } diff --git a/Les Horaires/src/main/res/layout/activity_detail_shop.xml b/Les Horaires/src/main/res/layout/activity_detail_shop.xml new file mode 100644 index 0000000..d236113 --- /dev/null +++ b/Les Horaires/src/main/res/layout/activity_detail_shop.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Les Horaires/src/main/res/layout/activity_main.xml b/Les Horaires/src/main/res/layout/activity_main.xml index 9dbb986..53ee727 100644 --- a/Les Horaires/src/main/res/layout/activity_main.xml +++ b/Les Horaires/src/main/res/layout/activity_main.xml @@ -1,43 +1,27 @@ + - - - + + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:layout_gravity="bottom|right" + android:layout_margin="16dp" + fab:fab_colorNormal="@color/accent" + android:src="@mipmap/plus" + fab:fab_colorPressed="@color/primary_dark"/> diff --git a/Les Horaires/src/main/res/layout/activity_search.xml b/Les Horaires/src/main/res/layout/activity_search.xml new file mode 100644 index 0000000..c9ee00b --- /dev/null +++ b/Les Horaires/src/main/res/layout/activity_search.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/Les Horaires/src/main/res/layout/activity_update_shop.xml b/Les Horaires/src/main/res/layout/activity_update_shop.xml new file mode 100644 index 0000000..42d2111 --- /dev/null +++ b/Les Horaires/src/main/res/layout/activity_update_shop.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/Les Horaires/src/main/res/layout/card_shop_item.xml b/Les Horaires/src/main/res/layout/card_shop_item.xml new file mode 100644 index 0000000..6abd853 --- /dev/null +++ b/Les Horaires/src/main/res/layout/card_shop_item.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/Les Horaires/src/main/res/layout/fav_list_item.xml b/Les Horaires/src/main/res/layout/fav_list_item.xml deleted file mode 100644 index 38d55eb..0000000 --- a/Les Horaires/src/main/res/layout/fav_list_item.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Les Horaires/src/main/res/layout/fragment_detail_shop.xml b/Les Horaires/src/main/res/layout/fragment_detail_shop.xml new file mode 100644 index 0000000..ec0c9c2 --- /dev/null +++ b/Les Horaires/src/main/res/layout/fragment_detail_shop.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Les Horaires/src/main/res/layout/fragment_list_shops.xml b/Les Horaires/src/main/res/layout/fragment_list_shops.xml new file mode 100644 index 0000000..cc1009c --- /dev/null +++ b/Les Horaires/src/main/res/layout/fragment_list_shops.xml @@ -0,0 +1,29 @@ + + + + + + + + + \ No newline at end of file diff --git a/Les Horaires/src/main/res/layout/fragment_search.xml b/Les Horaires/src/main/res/layout/fragment_search.xml new file mode 100644 index 0000000..c75d3f3 --- /dev/null +++ b/Les Horaires/src/main/res/layout/fragment_search.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + +