Skip to content

Commit 332e759

Browse files
committed
New update - 1.19.1
Included notifications that show an image with the latest BitCoin evolution of the latest 7 days. Also, a little code clean-up and optimization was done, with minor bug fixes corrections.
1 parent e9b9b4c commit 332e759

File tree

6 files changed

+142
-129
lines changed

6 files changed

+142
-129
lines changed

app/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ android {
1313
applicationId "javinator9889.bitcoinpools"
1414
minSdkVersion 21
1515
targetSdkVersion 28
16-
versionCode 100
16+
versionCode 105
1717
versionName "1.19.1"
1818
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1919
}
@@ -125,8 +125,9 @@ dependencies {
125125
implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
126126
implementation "com.mikepenz:aboutlibraries:6.2.0"
127127
implementation 'androidx.recyclerview:recyclerview:1.0.0'
128-
implementation 'androidx.annotation:annotation:1.0.0'
128+
implementation 'androidx.annotation:annotation:1.0.1'
129129
implementation 'androidx.cardview:cardview:1.0.0'
130130
implementation 'org.sufficientlysecure:donations:2.6'
131+
implementation group: 'com.googlecode.charts4j', name: 'charts4j', version: '1.3'
131132
}
132133
apply plugin: 'com.google.gms.google-services'

app/src/main/java/javinator9889/bitcoinpools/BackgroundJobs/JobSchedulerService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public boolean handleMessage(Message msg) {
3838
public boolean onStartJob(JobParameters params) {
3939
Log.d(Constants.LOG.JTAG, Constants.LOG.STARTING_JOB + Constants.JOB_ID);
4040
jobWorking = true;
41-
notificationHandler = NotificationHandler.newInstance(this);
41+
notificationHandler = NotificationHandler.newInstance();
4242
jobHandler.sendMessage(Message.obtain(jobHandler, Constants.JOB_ID, params));
4343
return jobWorking;
4444
}

app/src/main/java/javinator9889/bitcoinpools/BackgroundJobs/NotificationHandler.java

Lines changed: 131 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,45 @@
77
import android.content.Context;
88
import android.content.Intent;
99
import android.content.SharedPreferences;
10-
import android.content.res.TypedArray;
1110
import android.graphics.Bitmap;
12-
import android.graphics.Canvas;
13-
import android.graphics.Color;
14-
import android.graphics.DashPathEffect;
11+
import android.graphics.BitmapFactory;
12+
import android.os.AsyncTask;
1513
import android.os.Build;
1614
import android.util.Log;
1715

18-
import com.github.mikephil.charting.charts.LineChart;
19-
import com.github.mikephil.charting.data.Entry;
20-
import com.github.mikephil.charting.data.LineData;
21-
import com.github.mikephil.charting.data.LineDataSet;
22-
import com.github.mikephil.charting.formatter.LargeValueFormatter;
23-
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
16+
import com.googlecode.charts4j.AxisLabels;
17+
import com.googlecode.charts4j.AxisLabelsFactory;
18+
import com.googlecode.charts4j.AxisStyle;
19+
import com.googlecode.charts4j.AxisTextAlignment;
20+
import com.googlecode.charts4j.Color;
21+
import com.googlecode.charts4j.Data;
22+
import com.googlecode.charts4j.Fills;
23+
import com.googlecode.charts4j.GCharts;
24+
import com.googlecode.charts4j.Line;
25+
import com.googlecode.charts4j.LineChart;
26+
import com.googlecode.charts4j.LineStyle;
27+
import com.googlecode.charts4j.Plots;
28+
import com.googlecode.charts4j.Shape;
2429

2530
import org.json.JSONException;
2631

32+
import java.io.IOException;
33+
import java.net.URL;
2734
import java.text.SimpleDateFormat;
2835
import java.util.ArrayList;
2936
import java.util.Calendar;
37+
import java.util.Collection;
38+
import java.util.Collections;
3039
import java.util.Date;
40+
import java.util.List;
3141
import java.util.Locale;
3242
import java.util.Map;
3343
import java.util.concurrent.ExecutionException;
3444

3545
import androidx.annotation.NonNull;
36-
import androidx.constraintlayout.widget.ConstraintLayout;
37-
import androidx.core.content.ContextCompat;
3846
import javinator9889.bitcoinpools.BitCoinApp;
3947
import javinator9889.bitcoinpools.Constants;
4048
import javinator9889.bitcoinpools.DataLoaderScreen;
41-
import javinator9889.bitcoinpools.FragmentViews.CustomMarkerView;
4249
import javinator9889.bitcoinpools.JSONTools.JSONTools;
4350
import javinator9889.bitcoinpools.MainActivity;
4451
import javinator9889.bitcoinpools.NetTools.net;
@@ -47,8 +54,7 @@
4754
import static javinator9889.bitcoinpools.Constants.API_URL;
4855

4956
/**
50-
* Created by Javinator9889 on 23/01/2018.
51-
* Based on: https://stackoverflow.com/a/46991229
57+
* Created by Javinator9889 on 23/01/2018. Based on: https://stackoverflow.com/a/46991229
5258
*/
5359

5460
class NotificationHandler {
@@ -57,11 +63,9 @@ class NotificationHandler {
5763
private static boolean NOTIFIED_LOW = false;
5864
private static int SPECIFIC_VALUE = 0;
5965
private static float MPU;
60-
private Context mContext;
6166

62-
private NotificationHandler(@NonNull Context context) {
67+
private NotificationHandler() {
6368
final SharedPreferences sp = BitCoinApp.getSharedPreferences();
64-
mContext = context;
6569
Log.d(Constants.LOG.NTAG, Constants.LOG.CREATING_NOTIFICATION);
6670
NOTIFICATIONS_ENABLED = sp.getBoolean(Constants.SHARED_PREFERENCES.NOTIFICATIONS_ENABLED,
6771
false);
@@ -70,11 +74,11 @@ private NotificationHandler(@NonNull Context context) {
7074
SPECIFIC_VALUE = sp.getInt(Constants.SHARED_PREFERENCES.VALUE_TO_CHECK, 1000);
7175
MPU = initMPU();
7276
Log.d(Constants.LOG.NTAG, Constants.LOG.CURRRENT_NOT_SETTINGS
73-
+ NOTIFICATIONS_ENABLED + "\n"
74-
+ NOTIFIED_HIGH + "\n"
75-
+ NOTIFIED_LOW + "\n"
76-
+ SPECIFIC_VALUE + "\n"
77-
+ MPU);
77+
+ NOTIFICATIONS_ENABLED + "\n"
78+
+ NOTIFIED_HIGH + "\n"
79+
+ NOTIFIED_LOW + "\n"
80+
+ SPECIFIC_VALUE + "\n"
81+
+ MPU);
7882
}
7983

8084
void putNotification() {
@@ -106,17 +110,20 @@ void putNotification() {
106110
notificationTitle = BitCoinApp.getAppContext().getString(R.string.morePrice);
107111
notificationTextLong = BitCoinApp.getAppContext().getString(R.string.morePriceX)
108112
+ SPECIFIC_VALUE + ". " + BitCoinApp.getAppContext().getString(R.string.actualCost) + MPU;
113+
109114
notificationText = BitCoinApp.getAppContext().getString(R.string.morePriceX)
110115
+ SPECIFIC_VALUE;
111116
NOTIFIED_HIGH = true;
112117
NOTIFIED_LOW = false;
113118
notify = (MPU != -1);
114119
}
120+
String notificationTitleLong = BitCoinApp
121+
.getAppContext()
122+
.getString(R.string.actualCost) + MPU;
115123
if (notify) {
116124
Log.d(Constants.LOG.NTAG, Constants.LOG.NOTIFYING);
117125
updatePreferences();
118-
final LineChart chart = new LineChart(mContext);
119-
Bitmap chartBitmap = generateLineChart(chart);
126+
AsyncTask<String, Void, Bitmap> lineChartTask = generateLineChart();
120127
String name = BitCoinApp.getAppContext().getString(R.string.alerts);
121128
String description = BitCoinApp.getAppContext().getString(R.string.description);
122129
Notification.Builder notification;
@@ -155,69 +162,110 @@ void putNotification() {
155162
.setStyle(new Notification.BigTextStyle()
156163
.bigText(notificationTextLong));
157164
}
158-
if (chartBitmap != null) {
159-
notification.setLargeIcon(chartBitmap);
160-
notification.setStyle(new Notification.BigPictureStyle()
161-
.bigPicture(chartBitmap)
162-
.bigLargeIcon((Bitmap) null));
165+
try {
166+
if (lineChartTask != null) {
167+
Bitmap lineChart = lineChartTask.get();
168+
if (lineChart != null)
169+
notification.setStyle(new Notification.BigPictureStyle()
170+
.bigPicture(lineChart)
171+
.setBigContentTitle(notificationTitleLong));
172+
}
173+
} catch (ExecutionException | InterruptedException ignored) {
174+
175+
} finally {
176+
notification.setContentIntent(clickIntent);
177+
assert notificationManager != null;
178+
notificationManager.notify(Constants.NOTIFICATION_ID, notification.build());
163179
}
164-
notification.setContentIntent(clickIntent);
165-
assert notificationManager != null;
166-
notificationManager.notify(Constants.NOTIFICATION_ID, notification.build());
167-
} else
168-
Log.d(Constants.LOG.NTAG, Constants.LOG.NNOTIFYING);
169-
}
180+
}
181+
} else
182+
Log.d(Constants.LOG.NTAG, Constants.LOG.NNOTIFYING);
170183
}
171184

172-
private Bitmap generateLineChart(@NonNull final LineChart lineChart) {
185+
private AsyncTask<String, Void, Bitmap> generateLineChart() {
173186
Map<Date, Float> pricesMap;
174187
Calendar start = Calendar.getInstance();
175188
start.add(Calendar.DAY_OF_MONTH, -7);
176189
String startDate = String.format(Locale.US, "%d-%02d-%02d",
177190
start.get(Calendar.YEAR),
178-
start.get(Calendar.MONTH),
191+
(start.get(Calendar.MONTH) + 1),
179192
start.get(Calendar.DAY_OF_MONTH));
180193
String url = API_URL + "?start=" + startDate + "&end=" +
181194
new SimpleDateFormat("yyyy-MM-dd", Locale.US).format(Calendar.getInstance().getTime());
182195
pricesMap = getValuesByDatedURL(url);
183196
if (pricesMap == null)
184197
return null;
185-
// lineChart.setDrawingCacheEnabled(true);
186-
lineChart.setDrawGridBackground(false);
187-
lineChart.getDescription().setEnabled(false);
188-
CustomMarkerView markerView = new CustomMarkerView(mContext, R.layout.marker_view);
189-
markerView.setChartView(lineChart);
190-
lineChart.setMarker(markerView);
191-
ArrayList<Entry> values = new ArrayList<>(pricesMap.size());
198+
199+
int divider = getDivider(pricesMap);
200+
Line bitcoinPricesLine = Plots.newLine(getNormalizedData(pricesMap), Color.DARKBLUE);
201+
bitcoinPricesLine.setLineStyle(LineStyle.MEDIUM_DOTTED_LINE);
202+
bitcoinPricesLine.addShapeMarkers(Shape.CIRCLE, Color.BLACK, 8);
203+
bitcoinPricesLine.setFillAreaColor(Color.CYAN);
204+
205+
final LineChart bitcoinPricesChart = GCharts.newLineChart(bitcoinPricesLine);
206+
bitcoinPricesChart.setSize(760, 380);
207+
bitcoinPricesChart.setGrid(25, 25, 3, 2);
208+
209+
AxisStyle axisStyle = AxisStyle.newAxisStyle(Color.BLACK, 11, AxisTextAlignment.CENTER);
210+
AxisLabels xAxis = AxisLabelsFactory.newAxisLabels(getDates(pricesMap));
211+
AxisLabels yAxis = AxisLabelsFactory.newAxisLabels(getValues(pricesMap, divider));
212+
xAxis.setAxisStyle(axisStyle);
213+
yAxis.setAxisStyle(axisStyle);
214+
215+
bitcoinPricesChart.addXAxisLabels(xAxis);
216+
bitcoinPricesChart.addYAxisLabels(yAxis);
217+
bitcoinPricesChart.setBackgroundFill(Fills.newSolidFill(Color.WHITE));
218+
ImageDownloader downloader = new ImageDownloader();
219+
return downloader.execute(bitcoinPricesChart.toURLString());
220+
}
221+
222+
private int getDivider(@NonNull Map<Date, Float> pricesMap) {
223+
Float maximum = Collections.max(pricesMap.values());
224+
int iterations = 0;
225+
while (maximum >= 10) {
226+
maximum /= 10;
227+
++iterations;
228+
}
229+
return (int) Math.pow(10, iterations);
230+
}
231+
232+
private List<String> getDates(@NonNull Map<Date, Float> pricesMap) {
233+
List<String> dates = new ArrayList<>(pricesMap.keySet().size());
234+
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
235+
for (Date currentDate : pricesMap.keySet())
236+
dates.add(formatter.format(currentDate));
237+
return dates;
238+
}
239+
240+
private List<String> getValues(@NonNull Map<Date, Float> pricesMap, int divider) {
241+
Collection<Float> values = pricesMap.values();
242+
List<String> formattedValues = new ArrayList<>(6);
243+
float maximum = Collections.max(values);
244+
float minimum = Collections.min(values);
245+
float difference = maximum - minimum;
246+
float amount = difference / 5;
247+
formattedValues.add(0, String.format(Locale.US, "%.2fK", (minimum / divider)));
248+
float latest = minimum;
249+
for (int i = 1; i < 5; ++i) {
250+
latest += amount;
251+
formattedValues.add(i, String.format(Locale.US, "%.2fK", (latest / divider)));
252+
}
253+
formattedValues.add(5, String.format(Locale.US, "%.2fK", (maximum / divider)));
254+
return formattedValues;
255+
}
256+
257+
private Data getNormalizedData(@NonNull Map<Date, Float> pricesMap) {
258+
double[] normalizedValues = new double[pricesMap.values().size()];
259+
float maximum = Collections.max(pricesMap.values());
260+
float minimum = Collections.min(pricesMap.values());
261+
float difference = maximum - minimum;
192262
int i = 0;
193-
for (Date currentDate : pricesMap.keySet()) {
194-
values.add(new Entry(i, pricesMap.get(currentDate)));
263+
for (Float currentValue : pricesMap.values()) {
264+
float actualDifference = currentValue - minimum;
265+
normalizedValues[i] = (100 * actualDifference) / difference;
195266
++i;
196267
}
197-
LineDataSet lineDataSet = new LineDataSet(values, mContext.getString(R.string
198-
.latest_7_days));
199-
lineDataSet.setDrawIcons(false);
200-
lineDataSet.enableDashedLine(10f, 5f, 0f);
201-
lineDataSet.enableDashedHighlightLine(10f, 5f, 0f);
202-
lineDataSet.setColor(Color.BLACK);
203-
lineDataSet.setCircleColor(Color.BLACK);
204-
lineDataSet.setLineWidth(1f);
205-
lineDataSet.setCircleRadius(3f);
206-
lineDataSet.setDrawCircleHole(false);
207-
lineDataSet.setValueTextSize(9f);
208-
lineDataSet.setDrawFilled(true);
209-
lineDataSet.setFormLineWidth(1f);
210-
lineDataSet.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
211-
lineDataSet.setFormSize(15.f);
212-
lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
213-
lineDataSet.setFillDrawable(ContextCompat.getDrawable(mContext, R.drawable.fade_red));
214-
lineDataSet.setDrawCircles(false);
215-
ArrayList<ILineDataSet> dataSets = new ArrayList<>(1);
216-
dataSets.add(lineDataSet);
217-
LineData data = new LineData(dataSets);
218-
lineChart.setData(data);
219-
lineChart.getAxisLeft().setValueFormatter(new LargeValueFormatter());
220-
return setLayoutParams(lineChart);
268+
return Data.newData(normalizedValues);
221269
}
222270

223271
private Map<Date, Float> getValuesByDatedURL(@NonNull String url) {
@@ -232,40 +280,22 @@ private Map<Date, Float> getValuesByDatedURL(@NonNull String url) {
232280
}
233281
}
234282

235-
private Bitmap setLayoutParams(@NonNull final LineChart lineChart) {
236-
float dpHeight = mContext.getResources().getDisplayMetrics().heightPixels;
237-
float dpWidth = mContext.getResources().getDisplayMetrics().widthPixels;
238-
239-
int[] attrs = new int[]{R.attr.actionBarSize};
240-
TypedArray array = mContext.obtainStyledAttributes(attrs);
241-
int size = array.getDimensionPixelSize(0, 0);
242-
array.recycle();
243-
244-
int finalHeightDp = (int) ((dpHeight - size) * 0.5);
245-
int finalWidthDp = (int) ((dpWidth - size) * 0.9);
246-
247-
System.out.println("Height: " + finalHeightDp);
248-
System.out.println("Width: " + finalWidthDp);
249-
250-
Bitmap bitmap = Bitmap.createBitmap(finalWidthDp, finalHeightDp, Bitmap.Config.ARGB_8888);
251-
Canvas canvas = new Canvas(bitmap);
252-
253-
ConstraintLayout.LayoutParams layoutParams =
254-
new ConstraintLayout.LayoutParams(finalWidthDp, finalHeightDp);
255-
layoutParams.matchConstraintMaxHeight = (int) dpHeight;
256-
layoutParams.matchConstraintMaxWidth = (int) dpWidth;
257-
layoutParams.orientation = ConstraintLayout.LayoutParams.HORIZONTAL;
258-
layoutParams.validate();
283+
private static class ImageDownloader extends AsyncTask<String, Void, Bitmap> {
284+
@Override
285+
protected Bitmap doInBackground(String... urls) {
286+
try {
287+
URL imageUrl = new URL(urls[0]);
288+
return BitmapFactory.decodeStream(imageUrl.openConnection().getInputStream());
289+
} catch (IOException ignored) {
290+
return null;
291+
}
292+
}
259293

260-
lineChart.setLayoutParams(layoutParams);
261-
lineChart.invalidate();
262-
lineChart.draw(canvas);
263-
return bitmap;
264294
}
265295

266296
@NonNull
267-
static NotificationHandler newInstance(@NonNull Context context) {
268-
return new NotificationHandler(context);
297+
static NotificationHandler newInstance() {
298+
return new NotificationHandler();
269299
}
270300

271301
private static float initMPU() {

0 commit comments

Comments
 (0)