Commit 3684606e authored by Nastuzzi Samy's avatar Nastuzzi Samy
Browse files

Application totaly functionnal

Force portrait orientation
Permit activity to reload themselves
Add payment fonction
Add cancel function
Add config class (only change the default view for articles)
Optimize view generations
Better information are shown
Change background color and vibrate when a transaction is made
parent 64348618
......@@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:allowBackup="true"
......@@ -12,17 +13,28 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<activity android:name=".MainActivity"
android:configChanges="orientation"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BaseActivity" />
<activity android:name=".FoundationListActivity" />
<activity android:name=".ArticleCategoryActivity" />
<activity android:name=".BuyerInfoActivity" />
<activity android:name=".BaseActivity"
android:configChanges="orientation"
android:screenOrientation="portrait" />
<activity android:name=".FoundationListActivity"
android:configChanges="orientation"
android:screenOrientation="portrait" />
<activity android:name=".ArticleCategoryActivity"
android:configChanges="orientation"
android:screenOrientation="portrait" />
<activity android:name=".BuyerInfoActivity"
android:configChanges="orientation"
android:screenOrientation="portrait" />
</application>
</manifest>
\ No newline at end of file
package fr.utc.simde.payutc;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
......@@ -11,12 +13,14 @@ import android.widget.Toast;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import fr.utc.simde.payutc.articles.GroupFragment;
import fr.utc.simde.payutc.tools.HTTPRequest;
/**
* Created by Samy on 27/10/2017.
......@@ -111,13 +115,18 @@ public class ArticleCategoryActivity extends BaseActivity {
});
}
this.deleteButton.setOnClickListener(new View.OnClickListener() {
this.paramButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
for (GroupFragment groupFragment : groupFragmentList)
groupFragment.clear();
config.setInGrid(!config.getInGrid());
startCategoryArticlesActivity(ArticleCategoryActivity.this);
}
});
panier.clear();
this.deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clearPanier();
}
});
}
......@@ -130,8 +139,89 @@ public class ArticleCategoryActivity extends BaseActivity {
pay(badgeId);
}
public void clearPanier() {
for (GroupFragment groupFragment : groupFragmentList)
groupFragment.clear();
panier.clear();
}
public void setBackgroundColor(int color) {
this.tabHost.setBackgroundColor(color);
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2500);
runOnUiThread(new Runnable() {
@Override
public void run() {
tabHost.setBackgroundColor(getResources().getColor(R.color.white));
}
});
} catch (Exception e) {
Log.e(LOG_TAG, "error: " + e.getMessage());
}
}
}.start();
}
protected void pay(final String badgeId) {
Toast.makeText(this, "A faire payer", Toast.LENGTH_LONG).show();
dialog.startLoading(this, getResources().getString(R.string.paiement), getResources().getString(R.string.transaction_in_progress));
new Thread() {
@Override
public void run() {
try {
nemopaySession.setTransaction(badgeId, panier.getArticleList());
Thread.sleep(100);
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
Toast.makeText(ArticleCategoryActivity.this, "Paiement effectué", Toast.LENGTH_LONG).show();
setBackgroundColor(getResources().getColor(R.color.success));
((Vibrator) getSystemService(ArticleCategoryActivity.VIBRATOR_SERVICE)).vibrate(250);
clearPanier();
}
});
} catch (final Exception e) {
Log.e(LOG_TAG, "error: " + e.getMessage());
try {
final JsonNode response = nemopaySession.getRequest().getJSONResponse();
if (response.has("error") && response.get("error").has("message")) {
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
dialog.errorDialog(ArticleCategoryActivity.this, getString(R.string.paiement), response.get("error").get("message").textValue());
setBackgroundColor(getResources().getColor(R.color.error));
((Vibrator) getSystemService(ArticleCategoryActivity.VIBRATOR_SERVICE)).vibrate(500);
}
});
}
else
throw new Exception("");
} catch (Exception e1) {
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
dialog.errorDialog(ArticleCategoryActivity.this, getString(R.string.paiement), e.getMessage());
setBackgroundColor(getResources().getColor(R.color.error));
((Vibrator) getSystemService(ArticleCategoryActivity.VIBRATOR_SERVICE)).vibrate(500);
}
});
}
}
}
}.start();
}
protected void createCategories(final JsonNode categoryList, final JsonNode articleList) throws Exception {
......@@ -159,12 +249,12 @@ public class ArticleCategoryActivity extends BaseActivity {
if (articlesForThisCategory == null || articlesForThisCategory.size() == 0)
continue;
createNewCategory(category.get("name").textValue(), new ObjectMapper().readTree(articlesForThisCategory.toString()));
createNewCategory(category.get("name").textValue(), (ArrayNode) new ObjectMapper().readTree(articlesForThisCategory.toString()));
}
}
protected void createNewCategory(final String name, final JsonNode articleList) throws Exception {
GroupFragment articleGroupFragment = new GroupFragment(ArticleCategoryActivity.this, articleList, this.panier);
protected void createNewCategory(final String name, final ArrayNode articleList) throws Exception {
GroupFragment articleGroupFragment = new GroupFragment(ArticleCategoryActivity.this, articleList, this.panier, this.config.getInGrid());
TabHost.TabSpec newTabSpec = this.tabHost.newTabSpec(name);
newTabSpec.setIndicator(name);
......
......@@ -3,6 +3,7 @@ package fr.utc.simde.payutc;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import com.fasterxml.jackson.databind.JsonNode;
......@@ -21,6 +22,27 @@ public abstract class BaseActivity extends NFCActivity {
protected static Dialog dialog;
protected static NemopaySession nemopaySession;
protected static CASConnexion casConnexion;
protected static Config config;
protected class Config {
private SharedPreferences sharedPreferences;
private Boolean inGrid;
protected Config(final SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
this.inGrid = sharedPreferences.getBoolean("config_in_grid", true);
}
public Boolean getInGrid() { return this.inGrid; }
public void setInGrid(final Boolean inGrid) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("config_in_grid", inGrid);
editor.apply();
this.inGrid = inGrid;
}
}
protected void disconnect() {
nemopaySession.disconnect();
......@@ -99,6 +121,10 @@ public abstract class BaseActivity extends NFCActivity {
@Override
public void run() {
dialog.stopLoading();
if (activity.getClass().getSimpleName().equals("FoundationListActivity"))
finish();
activity.startActivity(intent);
}
});
......@@ -204,6 +230,10 @@ public abstract class BaseActivity extends NFCActivity {
@Override
public void run() {
dialog.stopLoading();
if (activity.getClass().getSimpleName().equals("ArticleCategoryActivity"))
finish();
activity.startActivity(intent);
}
});
......@@ -250,11 +280,16 @@ public abstract class BaseActivity extends NFCActivity {
if (!buyerInfo.has("lastname") || !buyerInfo.has("username") || !buyerInfo.has("firstname") || !buyerInfo.has("solde") || !buyerInfo.has("last_purchases") || !buyerInfo.get("last_purchases").isArray())
throw new Exception("Unexpected JSON");
intent.putExtra("badgeId", badgeId);
intent.putExtra("buyerInfo", request.getResponse());
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
if (activity.getClass().getSimpleName().equals("BuyerInfoActivity"))
finish();
activity.startActivity(intent);
}
});
......
......@@ -33,10 +33,12 @@ import fr.utc.simde.payutc.tools.HTTPRequest;
public class BuyerInfoActivity extends BaseActivity {
private static final String LOG_TAG = "_BuyerInfoActivity";
private String lastname;
private String badgeId;
private String username;
private String lastname;
private String firstname;
private JsonNode lastPurchases;
private ArrayNode lastPurchaseList;
private ArrayNode lastArticleList;
private TextView textBuyerName;
private TextView textSolde;
......@@ -56,14 +58,20 @@ public class BuyerInfoActivity extends BaseActivity {
try {
JsonNode buyerInfo = new ObjectMapper().readTree(getIntent().getExtras().getString("buyerInfo"));
this.badgeId = getIntent().getExtras().getString("badgeId");
if (!buyerInfo.has("lastname") || !buyerInfo.has("username") || !buyerInfo.has("firstname") || !buyerInfo.has("solde") || !buyerInfo.has("last_purchases") || !buyerInfo.get("last_purchases").isArray())
throw new Exception("Unexpected JSON");
this.textBuyerName.setText(buyerInfo.get("firstname").textValue() + " " + buyerInfo.get("lastname").textValue());
this.username = buyerInfo.get("username").textValue();
this.lastname = buyerInfo.get("lastname").textValue();
this.firstname = buyerInfo.get("firstname").textValue();
this.lastPurchaseList = (ArrayNode) buyerInfo.get("last_purchases");
this.textBuyerName.setText(this.firstname + " " + this.lastname);
this.textSolde.setText("Solde: " + String.format("%.2f", new Float(buyerInfo.get("solde").intValue()) / 100.00f) + "€");
generatePurchases((ArrayNode) buyerInfo.get("last_purchases"));
generatePurchases();
} catch (Exception e) {
Log.e(LOG_TAG, "error: " + e.getMessage());
dialog.errorDialog(this, getResources().getString(R.string.information_collection), getResources().getString(R.string.error_view), new DialogInterface.OnClickListener() {
......@@ -76,12 +84,10 @@ public class BuyerInfoActivity extends BaseActivity {
}
@Override
protected void onIdentification(final String badgeId) {
}
protected void onIdentification(final String badgeId) { }
protected void generatePurchases(final ArrayNode purchaseList) throws Exception {
if (purchaseList.size() == 0) {
protected void generatePurchases() throws Exception {
if (this.lastPurchaseList.size() == 0) {
String foundationName = nemopaySession.getFoundationName();
TextView noPurchase = new TextView(this);
noPurchase.setText(getString(R.string.no_purchases) + (foundationName.equals("") ? "" : "\n(" + foundationName + ")"));
......@@ -95,14 +101,110 @@ public class BuyerInfoActivity extends BaseActivity {
this.linearLayout.addView(noPurchase);
}
else {
generateArticleList(purchaseList);
generateArticleList();
this.listView = new ListView(this);
this.linearLayout.addView(listView);
this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
final JsonNode article = lastArticleList.get(position);
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(BuyerInfoActivity.this);
alertDialogBuilder
.setTitle(R.string.cancel_transaction)
.setMessage(getString(R.string.ask_cancel_transaction) + " " + Integer.toString(article.get("quantity").intValue()) + "x " + article.get("name").textValue() + " (total: " + String.format("%.2f", new Float(article.get("price").intValue()) / 100.00f) + "€) ?")
.setCancelable(true)
.setPositiveButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int id) {
new Thread() {
@Override
public void run() {
if (nemopaySession.getFoundationId() != -1) {
try {
nemopaySession.cancelTransaction(nemopaySession.getFoundationId(), article.get("purchase_id").intValue());
Thread.sleep(100);
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(BuyerInfoActivity.this);
alertDialogBuilder
.setTitle(R.string.cancel_transaction)
.setMessage(getString(R.string.transaction_canceled))
.setCancelable(true)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int id) {
try {
startBuyerInfoActivity(BuyerInfoActivity.this, badgeId);
} catch (Exception e) {
Log.e(LOG_TAG, "error: " + e.getMessage());
dialog.errorDialog(BuyerInfoActivity.this, getResources().getString(R.string.information_collection), getResources().getString(R.string.error_view), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int id) {
finish();
}
});
}
}
});
dialog.createDialog(alertDialogBuilder);
}
});
} catch (final Exception e) {
Log.e(LOG_TAG, "error: " + e.getMessage());
try {
final JsonNode response = nemopaySession.getRequest().getJSONResponse();
if (response.has("error") && response.get("error").has("message")) {
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
dialog.errorDialog(BuyerInfoActivity.this, getString(R.string.cancel_transaction), response.get("error").get("message").textValue());
}
});
}
else
throw new Exception("");
} catch (Exception e1) {
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.stopLoading();
dialog.errorDialog(BuyerInfoActivity.this, getString(R.string.cancel_transaction), e.getMessage());
}
});
}
}
}
}
}.start();
}
})
.setNegativeButton(R.string.do_nothing, null);
dialog.createDialog(alertDialogBuilder);
}
});
this.listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
listAdapater.toast(position, Toast.LENGTH_LONG);
return true;
}
});
}
}
public void generateArticleList(final ArrayNode purchaseList) {
public void generateArticleList() {
dialog.startLoading(this, getString(R.string.information_collection), getString(R.string.article_list_collecting));
new Thread() {
......@@ -137,13 +239,15 @@ public class BuyerInfoActivity extends BaseActivity {
final ArrayNode articleList = new ObjectMapper().createArrayNode();
Boolean hasRight = true; //
for (JsonNode purchase : purchaseList) {
for (JsonNode purchase : lastPurchaseList) {
int articleId = purchase.get("obj_id").intValue();
Boolean isIn = false;
for (JsonNode article : articleFoundationList) {
if (article.get("id").intValue() == articleId) {
((ObjectNode) article).put("info", getString(R.string.realized) + " " + purchase.get("pur_date").textValue().substring(purchase.get("pur_date").textValue().length() - 8));
((ObjectNode) article).put("quantity", Math.round(purchase.get("pur_qte").floatValue()));
((ObjectNode) article).put("purchase_id", purchase.get("pur_id").intValue());
articleList.add(article);
isIn = true;
......@@ -156,7 +260,9 @@ public class BuyerInfoActivity extends BaseActivity {
articleList.add(new ObjectMapper().readTree("{" +
"\"name\":\"" + "N°: " + Integer.toString(purchase.get("obj_id").intValue()) + "\", " +
"\"price\":" + Integer.toString(purchase.get("pur_price").intValue()) + ", " +
"\"info\":\"Non annulable\", " +
"\"quantity\":" + Math.round(purchase.get("pur_qte").floatValue()) + ", " +
"\"purchase_id\":" + purchase.get("pur_id").intValue() + ", " +
"\"info\":\"" + getString(R.string.realized_by_other) + "\", " +
"\"image_url\":\"\"}"
));
}
......@@ -183,6 +289,7 @@ public class BuyerInfoActivity extends BaseActivity {
@Override
public void run() {
try {
lastArticleList = articleList;
listAdapater = new ListAdapater(BuyerInfoActivity.this, articleList);
listView.setAdapter(listAdapater);
dialog.stopLoading();
......
......@@ -33,22 +33,24 @@ public class MainActivity extends BaseActivity {
private static final String LOG_TAG = "_MainActivity";
private static final String service = "https://assos.utc.fr";
private static SharedPreferences sharedPreferences;
private static TextView AppConfigText;
private static TextView AppRegisteredText;
private static Button usernameButton;
private static SharedPreferences sharedPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sharedPreferences = getSharedPreferences("payutc", Activity.MODE_PRIVATE);
dialog = new Dialog(MainActivity.this);
nemopaySession = new NemopaySession(MainActivity.this);
casConnexion = new CASConnexion(nemopaySession);
sharedPreferences = getSharedPreferences("payutc", Activity.MODE_PRIVATE);
config = new Config(sharedPreferences);
final String key = sharedPreferences.getString("key", "");
if (!key.equals(""))
setKey(key);
......
......@@ -16,6 +16,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.InputStream;
import java.net.HttpURLConnection;
......@@ -38,9 +39,9 @@ abstract class ArticlesAdapter extends BaseAdapter {
protected Integer[] nbrClicksList;
protected TextView[] clickViewList;
protected JsonNode articleList;
protected ArrayNode articleList;
public ArticlesAdapter(final Activity activity, final JsonNode articleList) throws Exception {
public ArticlesAdapter(final Activity activity, final ArrayNode articleList) throws Exception {
this.activity = activity;
this.articleList = articleList;
this.imageList = new Bitmap[articleList.size()];
......@@ -90,7 +91,6 @@ abstract class ArticlesAdapter extends BaseAdapter {
this.nbrClicksList[position]++;
setClickView(position);
toast(position, Toast.LENGTH_SHORT);
}
public void clear() {
......
......@@ -9,6 +9,7 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import fr.utc.simde.payutc.R;
......@@ -21,7 +22,7 @@ public class GridAdapter extends ArticlesAdapter {
private int size;
public GridAdapter(final Activity activity, final JsonNode articleList, final int nbrColumns) throws Exception {
public GridAdapter(final Activity activity, final ArrayNode articleList, final int nbrColumns) throws Exception {
super(activity, articleList);
switch (nbrColumns) {
......@@ -51,22 +52,22 @@ public class GridAdapter extends ArticlesAdapter {
if (view == null) {
LayoutInflater layoutInflater = LayoutInflater.from(this.activity);
view = layoutInflater.inflate(R.layout.fragment_article_grid, null);
}
ImageView imageView = view.findViewById(R.id.image_article);
ImageView imageView = view.findViewById(R.id.image_article);
if (clickViewList[position] == null)
clickViewList[position] = view.findViewById(R.id.text_nbr_clicks);
if (clickViewList[position] == null)
clickViewList[position] = view.findViewById(R.id.text_nbr_clicks);
TextView textView = view.findViewById(R.id.text_article);
textView.setText(article.get("name").textValue());
TextView textView = view.findViewById(R.id.text_article);
textView.setText(article.get("name").textValue());
int imageSize = this.size;
RelativeLayout.LayoutParams parms = new RelativeLayout.LayoutParams(imageSize, imageSize);
imageView.setLayoutParams(parms);
int imageSize = this.size;
RelativeLayout.LayoutParams parms = new RelativeLayout.LayoutParams(imageSize, imageSize);
imageView.setLayoutParams(parms);
setImage(imageView, article.get("image_url").textValue(), position);
setClickView(position);
setImage(imageView, article.get("image_url").textValue(), position);
setClickView(position);