77import  android .content .Context ;
88import  android .content .Intent ;
99import  android .content .SharedPreferences ;
10- import  android .content .res .TypedArray ;
1110import  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 ;
1513import  android .os .Build ;
1614import  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
2530import  org .json .JSONException ;
2631
32+ import  java .io .IOException ;
33+ import  java .net .URL ;
2734import  java .text .SimpleDateFormat ;
2835import  java .util .ArrayList ;
2936import  java .util .Calendar ;
37+ import  java .util .Collection ;
38+ import  java .util .Collections ;
3039import  java .util .Date ;
40+ import  java .util .List ;
3141import  java .util .Locale ;
3242import  java .util .Map ;
3343import  java .util .concurrent .ExecutionException ;
3444
3545import  androidx .annotation .NonNull ;
36- import  androidx .constraintlayout .widget .ConstraintLayout ;
37- import  androidx .core .content .ContextCompat ;
3846import  javinator9889 .bitcoinpools .BitCoinApp ;
3947import  javinator9889 .bitcoinpools .Constants ;
4048import  javinator9889 .bitcoinpools .DataLoaderScreen ;
41- import  javinator9889 .bitcoinpools .FragmentViews .CustomMarkerView ;
4249import  javinator9889 .bitcoinpools .JSONTools .JSONTools ;
4350import  javinator9889 .bitcoinpools .MainActivity ;
4451import  javinator9889 .bitcoinpools .NetTools .net ;
4754import  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
5460class  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