From 3da44593ddff284f98857327832025e272c6ab8b Mon Sep 17 00:00:00 2001 From: CiufudeanDani Date: Tue, 15 Mar 2022 14:45:18 +0200 Subject: [PATCH 1/7] display Markers --- .../java/com/safemobile/lib/SuperVehicle.java | 24 ++--- .../com/safemobile/dispatch/LiveActivity.java | 91 ++++++++++++++++++- 2 files changed, 98 insertions(+), 17 deletions(-) diff --git a/libSafeMobile/src/main/java/com/safemobile/lib/SuperVehicle.java b/libSafeMobile/src/main/java/com/safemobile/lib/SuperVehicle.java index 2c9dfb1..2388814 100644 --- a/libSafeMobile/src/main/java/com/safemobile/lib/SuperVehicle.java +++ b/libSafeMobile/src/main/java/com/safemobile/lib/SuperVehicle.java @@ -21,36 +21,28 @@ public class SuperVehicle extends Vehicle{ // TODO Auto-generated constructor stub } - public void SetDataFromLastPos(Double _lat,Double _lng,long _time,int _speed,String _Address,Boolean _isON) - { - try - { + public void SetDataFromLastPos(Double _lat,Double _lng,long _time,int _speed,String _Address,Boolean _isON) { + try { lat = _lat; lng = _lng; timeGMT = _time; speed = _speed; Address = _Address; isON = _isON; - } - catch (Exception ex) - { - Log.d("Erorr", "Contert Error:"+ex.toString()); + } catch (Exception ex) { + Log.d("Erorr", "Contert Error: "+ ex); } } - public void SetNewPosition(Double _lat,Double _lng,long _time,int _speed) - { - try - { + public void SetNewPosition(Double _lat,Double _lng,long _time,int _speed) { + try { lat = _lat; lng = _lng; timeGMT = _time; speed = _speed; isON = true; - } - catch (Exception ex) - { - Log.d("Erorr", "Contert Error:"+ex.toString()); + } catch (Exception ex) { + Log.d("Erorr", "Contert Error: " + ex); } } diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java index ebbfdc1..a2a2789 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java @@ -9,6 +9,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.Typeface; import android.os.Bundle; import android.os.Handler; @@ -30,7 +37,10 @@ import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; +import com.google.android.gms.maps.model.BitmapDescriptor; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.safemobile.activities.AbstractLiveActivity; import com.safemobile.activities.AbstractSDParentActivity; @@ -456,13 +466,92 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall }); public void displayVehicle(boolean withZoom, double latZoom, double lngZoom) { - //TODO: add makers for vehicles + if (googleMap != null) { + googleMap.clear(); + + for (int i = 0; i < displayedVehicles.size(); i++) { + if (displayedVehicles.get(i)) { + SuperVehicle tmpSuper = Objects.requireNonNull(tableHashOverlay.get((int) liveVehicle.get(i).driver_id)).get(0); + + if (tmpSuper != null) { + LatLng newLocation = new LatLng(tmpSuper.lat, tmpSuper.lng); + MarkerOptions markerOptions = new MarkerOptions().position(newLocation).title(tmpSuper.name); + + BitmapDescriptor markerIcon = getProperBitmap(tmpSuper.getLargeIcon(), tmpSuper.name); + markerOptions.icon(markerIcon); + + Marker marker = this.googleMap.addMarker(markerOptions); + this.googleMap.moveCamera(CameraUpdateFactory.newLatLng(newLocation)); + } + } + } + } } public void showOpenedBalloon(boolean demo) { + int i =0; //TODO: add show balloon } + private BitmapDescriptor getProperBitmap(int largeIcon, String text) { + Bitmap bitmap = BitmapFactory.decodeResource(getResources(), largeIcon); + Bitmap textBitmap = getTextAsDrawable(this, text); + Bitmap b3 = overlay(bitmap, textBitmap); + return BitmapDescriptorFactory.fromBitmap(b3); + } + + public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2) { + int maxWidth = Math.max(bmp1.getWidth(), bmp2.getWidth()); + + Bitmap bmOverlay = Bitmap.createBitmap(maxWidth, bmp1.getHeight() + bmp2.getHeight(), bmp1.getConfig()); + Canvas canvas = new Canvas(bmOverlay); + canvas.drawBitmap(bmp1, new Matrix(), null); + canvas.drawBitmap(bmp2, 0, bmp1.getHeight(), null); + bmp1.recycle(); + bmp2.recycle(); + return bmOverlay; + } + + public Bitmap getTextAsDrawable(Context context, String text) { + Typeface tf = Typeface.create("Helvetica", Typeface.BOLD); + + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(Color.WHITE); + paint.setTypeface(tf); + paint.setTextSize(convertToPixels(context, 16)); + + Rect textRect = new Rect(); + paint.getTextBounds(text, 0, text.length(), textRect); + + Bitmap bitmap = Bitmap.createBitmap(textRect.width(), textRect.height() + 5, + Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + paint.setColor(getResources().getColor(R.color.cardview_dark_background)); + canvas.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), paint); + + + float scale = context.getResources().getDisplayMetrics().density; + // text color - #3D3D3D + paint.setColor(Color.rgb(255, 255, 255)); + // text size in pixels + + // draw text to the Canvas center + Rect bounds = new Rect(); + paint.getTextBounds(text, 0, text.length(), bounds); + int x = (bitmap.getWidth() - bounds.width()) / 2; + int y = (bitmap.getHeight() + bounds.height()) / 2; + + canvas.drawText(text, x, y, paint); + + return bitmap; + } + + public int convertToPixels(Context context, int nDP) { + final float conversionScale = context.getResources().getDisplayMetrics().density; + return (int) ((nDP * conversionScale) + 0.5f); + } + public void showLoadingDialog(String message) { loadingDialog = new Dialog(context); loadingDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); From 2334dc2e3c51895c81f93d60fdfac87dd11a5291 Mon Sep 17 00:00:00 2001 From: CiufudeanDani Date: Tue, 15 Mar 2022 17:42:58 +0200 Subject: [PATCH 2/7] make marker move --- .../activities/AbstractLiveActivity.java | 1 - .../com/safemobile/dispatch/LiveActivity.java | 4 +- .../dispatch/TabLayoutActivity.java | 58 +++++++------------ 3 files changed, 22 insertions(+), 41 deletions(-) diff --git a/libSafeMobile/src/main/java/com/safemobile/activities/AbstractLiveActivity.java b/libSafeMobile/src/main/java/com/safemobile/activities/AbstractLiveActivity.java index 11a7695..2f2e654 100644 --- a/libSafeMobile/src/main/java/com/safemobile/activities/AbstractLiveActivity.java +++ b/libSafeMobile/src/main/java/com/safemobile/activities/AbstractLiveActivity.java @@ -24,7 +24,6 @@ public abstract class AbstractLiveActivity extends AppCompatActivity { public abstract void vehicleStatusReceived(long imei, int opCode, int status); // --> UpdateOptions public abstract void emergencyAlarmReceived(int position, double lat, double lng); // --> UpdateEmergencyAlarm - /** Misc */ public AbstractSDParentActivity getParentTab() { return parentTab; diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java index a2a2789..081e942 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java @@ -471,7 +471,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall for (int i = 0; i < displayedVehicles.size(); i++) { if (displayedVehicles.get(i)) { - SuperVehicle tmpSuper = Objects.requireNonNull(tableHashOverlay.get((int) liveVehicle.get(i).driver_id)).get(0); + SuperVehicle tmpSuper = getParentTab().SuperVehHash.get(Long.valueOf(liveVehicle.get(i).imei)); if (tmpSuper != null) { LatLng newLocation = new LatLng(tmpSuper.lat, tmpSuper.lng); @@ -481,7 +481,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall markerOptions.icon(markerIcon); Marker marker = this.googleMap.addMarker(markerOptions); - this.googleMap.moveCamera(CameraUpdateFactory.newLatLng(newLocation)); } } } @@ -665,7 +664,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall pollReceived(position,lat,lng); } - public void updatePosition(int pos) { contextMenuPosition = pos; } diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java index fe01c66..423b978 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java @@ -1237,35 +1237,24 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ GPSmsg GPSPos= new GPSmsg(msg); //SM.Debug("Got new GPS pos data:" + GPSPos.data); - if(SuperVehHash.get(GPSPos.gpsValue.imei) != null) - { - ((SuperVehicle)SuperVehHash.get(GPSPos.gpsValue.imei)).SetNewPosition(GPSPos.gpsValue.lat, GPSPos.gpsValue.lng, GPSPos.gpsValue.timeGMT, GPSPos.gpsValue.speed); - - if(SuperVehHash.get(GPSPos.gpsValue.imei).needUpdate) - { - - //list for live - if(AppParams.crtTab == AppParams.Tabs.live) - { - //SM.Debug("+++++ duda +++++"); - SM.Debug("currentActivity instanceof LiveActivity"); - try - { - if(liveActivity != null) - liveActivity.refreshMap(); - } - catch (Exception ex) - { - SM.Debug("Error load hash:"+ex.toString()); - } - } - } + if (SuperVehHash.get(GPSPos.gpsValue.imei) != null) { + ((SuperVehicle)SuperVehHash.get(GPSPos.gpsValue.imei)).SetNewPosition(GPSPos.gpsValue.lat, GPSPos.gpsValue.lng, GPSPos.gpsValue.timeGMT, GPSPos.gpsValue.speed); +// if (SuperVehHash.get(GPSPos.gpsValue.imei).needUpdate) { + if (AppParams.crtTab == AppParams.Tabs.live) { + SM.Debug("currentActivity instanceof LiveActivity"); + try { + if (liveActivity != null) + liveActivity.refreshMap(); + } catch (Exception ex) { + SM.Debug("Error load hash: "+ ex); + } + } +// } } } @Override - public void onPollReceived(TCPEvent event) - { + public void onPollReceived(TCPEvent event) { SM.Debug("Got POLL GPS message"); TCPmsg msg= event.msg(); GPSmsg GPSPos= new GPSmsg(msg); @@ -1273,13 +1262,11 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ mess = "LAT:"+Double.toString(GPSPos.gpsValue.lat)+" LNG:"+Double.toString(GPSPos.gpsValue.lng); SM.Debug("Got new Poll pos data:" + GPSPos.data); - if(SuperVehHash.get(GPSPos.gpsValue.imei) != null) - { + if (SuperVehHash.get(GPSPos.gpsValue.imei) != null) { ((SuperVehicle)SuperVehHash.get(GPSPos.gpsValue.imei)).SetNewPosition(GPSPos.gpsValue.lat, GPSPos.gpsValue.lng, GPSPos.gpsValue.timeGMT, GPSPos.gpsValue.speed); //if is not check i need to force check to put on the map Boolean forceChecked =false; - if (!SuperVehHash.get(GPSPos.gpsValue.imei).needUpdate) - { + if (!SuperVehHash.get(GPSPos.gpsValue.imei).needUpdate) { SuperVehHash.get(GPSPos.gpsValue.imei).needUpdate =true; forceChecked =true; } @@ -1525,15 +1512,12 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ @Override public void onLastPositionsReceived(TCPEvent event) { TCPmsg msg= event.msg(); - SM.Debug("Got lastpos"); - //SM.Debug("Got lastpos :" + msg.allData); - + SM.Debug("Got last pos"); + LastPosmsg lastPos= new LastPosmsg(msg); - //SM.Debug("Got LastPost msg.data:" + msg.data); - for(LastPos posMsg: lastPos.PosList) - { - if(SuperVehHash.get(posMsg.imei) != null) - ((SuperVehicle)SuperVehHash.get(posMsg.imei)).SetDataFromLastPos(posMsg.lat, posMsg.lng, posMsg.timeGMT, posMsg.speed, posMsg.Address, posMsg.isON); + for (LastPos posMsg: lastPos.PosList) { + if (SuperVehHash.get(posMsg.imei) != null) + ((SuperVehicle) SuperVehHash.get(posMsg.imei)).SetDataFromLastPos(posMsg.lat, posMsg.lng, posMsg.timeGMT, posMsg.speed, posMsg.Address, posMsg.isON); } } From 201845da3a4c6a97c87f3eaa249665543be8c8d0 Mon Sep 17 00:00:00 2001 From: CiufudeanDani Date: Wed, 16 Mar 2022 10:54:41 +0200 Subject: [PATCH 3/7] display info bubble --- .../drawable-xhdpi/custom_info_bubble.9.png | Bin 0 -> 2030 bytes .../src/main/res/drawable-xhdpi/l_bg_gps.jpg | Bin 0 -> 16927 bytes .../src/main/res/drawable-xhdpi/l_speed.png | Bin 0 -> 5242 bytes .../src/main/res/drawable-xhdpi/l_street.png | Bin 0 -> 22489 bytes .../src/main/res/drawable-xhdpi/l_time.png | Bin 0 -> 19357 bytes .../res/layout/map_marker_info_bubble.xml | 140 ++++++++++++++++++ libSafeMobile/src/main/res/values/color.xml | 5 + .../dispatch/GoogleMapsInfoBubble.java | 93 ++++++++++++ .../com/safemobile/dispatch/LiveActivity.java | 9 +- .../src/main/res/values-de/strings.xml | 3 + .../src/main/res/values-es/strings.xml | 3 + .../src/main/res/values-ro/strings.xml | 3 + .../src/main/res/values-tr/strings.xml | 3 + safeDispatch/src/main/res/values/strings.xml | 4 + 14 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 libSafeMobile/src/main/res/drawable-xhdpi/custom_info_bubble.9.png create mode 100644 libSafeMobile/src/main/res/drawable-xhdpi/l_bg_gps.jpg create mode 100644 libSafeMobile/src/main/res/drawable-xhdpi/l_speed.png create mode 100644 libSafeMobile/src/main/res/drawable-xhdpi/l_street.png create mode 100644 libSafeMobile/src/main/res/drawable-xhdpi/l_time.png create mode 100644 libSafeMobile/src/main/res/layout/map_marker_info_bubble.xml create mode 100644 libSafeMobile/src/main/res/values/color.xml create mode 100644 safeDispatch/src/main/java/com/safemobile/dispatch/GoogleMapsInfoBubble.java diff --git a/libSafeMobile/src/main/res/drawable-xhdpi/custom_info_bubble.9.png b/libSafeMobile/src/main/res/drawable-xhdpi/custom_info_bubble.9.png new file mode 100644 index 0000000000000000000000000000000000000000..21dc176f2d13da96f7494c5545cf0050aeac811e GIT binary patch literal 2030 zcmd6odoY{%8ppBGrf39Jl&&HaaXqfZ9;HDQ5tk{t6{SMSL7i?ErLMK2#71dQQEjbD z);&Gcr7l4!ClqBh(ljnXN{N;Pq3qi+)7hDwIe(wu%{|t3Ek736yeja7 z=K((K;n}li-*h68xVyXitpuRHzMjkF0+61buArbWJv|MuwY9aZtSp1Uh>MH!_xCq4 zGBPnS0rZ}p9y*;K5fM>aTU%II2m*m7CMK9nrkk4^fj}rKDgr!gHk-rYn46meoSU0l zQBl#{+-zfGheyMga8m^n^ko5{aZzsRIK8?(XhUQBg}vOPiaUD=RA>K73eTUte2W`~3Oy z$B!RpW@hH*<^%%4#>NIPD_|@@Z$Q@K;v%2V=ka)3TU(z#eOg^zJsbk?$pMMm+uL8h zeA(IA+27v>#s$Ph)Z{w>*{wf$BE3X@)%{LXUeeZ7^yoDp{3mjCUT=h?lW?9GEXxDLw>0UL_cnkpL)<*mQz%K zqo0m>Ykd7j={JxAvOlwEx<9P#)>9_$b=%f0bg2)Oc9Ry;L=s44V*Kp#sjP6LDW1hL zkzK0n&0^fwCRWRdX$aLb`W+u*HLmkWLWEXiL-z2yQE3Uj#R+DiBJI`7^lo}eStV|j zo1&1?6I7&jHxnzKqhehfKae9*OU{InW^_Lavo5ta=-yBRS>TIUKjB#>iX8APBP${a z6|O9}4bJ^BEA2n{w5nmvyR7v2P;H!wfwkIYvCt~<8W;kyZqbyiVh`fVirNQ@9iSv% zkqL51o^ZS0Mm0TU`*;)M_)aq@z#GIfaMyRRS81g44;YuPT@6Lb+&kJ|;Qt zA@m8`_phA#1aC5(!vd~Q!1bC^euth^MsiHB*C*gTT{Ms$!2WuEeX9JVn$(dCTK?*J zP|=yA;i97UoR)??X?Y1x?vP=}RZrt z#(GKW`EN`(KyVdPRTA#t#%vd?-qo(AYhwdZu3B~I&GWQB`00eOt3?;VcBB@(?K>*w zX@`}q?GKbEbsvWLmI=KHv(s2q*PS-3_6{O35x3h%A~o3dI8)Dq9f|svoP)c4!&D<& z-3+eEaVcxv{)5)Mwz{(@IrPlM`Kpd_OQ?>A9<>{qiUH*ooOm|nWmWfknDc@-LB6)W zEN0(l@wTfV`&3%o;8}0ni-~zNxU8Xsl(L3z|1vZ#i{qWI8<|2!PbS__U9$<`Iu49T zOk&Yo#Dk}nnv#ZAHGmUO3o%OVg$+@M`_C504_&^c70upZj~1`f8^R$N{hQq(d6+Q{ zv{1@ijjnUo&$9Z=73!_1)$WKTiRZm$fu;qSseG}4pegKDfF4PvyqTQ%F4`bk{Aa0n zd-aX3C_nNmXzYk3zMXe&H|l5JmEROFp~sYj&|oQs(x3|MOK9fNQN~j%Of^zWsW;Hr z){;QUK+Ezcs|@!YOaF2i!;aAgx~X zU?0~>(U(>sWz#C{u6eg|tZ|8P%KJg(j_P%JO^lXfRBCqM#sl-s*)(Yn=EDji!HkPE(sGF& zOH9}_Zf3f`Brfy?bP<`I$Es8XmT_unM`(qyr55#=Us<)m9!l!X&$ZB=^u^zyh6Z7H ehNi_qf0AhDuB5JDi}UqwBI4|TMAX?|OZ^j=jaME3 literal 0 HcmV?d00001 diff --git a/libSafeMobile/src/main/res/drawable-xhdpi/l_bg_gps.jpg b/libSafeMobile/src/main/res/drawable-xhdpi/l_bg_gps.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e940b102c0542b3b72191a13111ddc4d882ef96b GIT binary patch literal 16927 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­)os_E(yqT7%erT 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 literal 0 HcmV?d00001 diff --git a/libSafeMobile/src/main/res/drawable-xhdpi/l_speed.png b/libSafeMobile/src/main/res/drawable-xhdpi/l_speed.png new file mode 100644 index 0000000000000000000000000000000000000000..9451fc29a4097b2b3f3ea85a9ac3a6c4c127e0ba GIT binary patch literal 5242 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 literal 0 HcmV?d00001 diff --git a/libSafeMobile/src/main/res/drawable-xhdpi/l_time.png b/libSafeMobile/src/main/res/drawable-xhdpi/l_time.png new file mode 100644 index 0000000000000000000000000000000000000000..72e4ebf3ea1634747e8b1161f4b99651b58bd05c GIT binary patch literal 19357 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 a0fXT4%3+C(R*U~~U}a{DDK+uh`~Ltn@n)p} literal 0 HcmV?d00001 diff --git a/libSafeMobile/src/main/res/layout/map_marker_info_bubble.xml b/libSafeMobile/src/main/res/layout/map_marker_info_bubble.xml new file mode 100644 index 0000000..08ce499 --- /dev/null +++ b/libSafeMobile/src/main/res/layout/map_marker_info_bubble.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libSafeMobile/src/main/res/values/color.xml b/libSafeMobile/src/main/res/values/color.xml new file mode 100644 index 0000000..503e1f0 --- /dev/null +++ b/libSafeMobile/src/main/res/values/color.xml @@ -0,0 +1,5 @@ + + + #FFFFFF + #000000 + \ No newline at end of file diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/GoogleMapsInfoBubble.java b/safeDispatch/src/main/java/com/safemobile/dispatch/GoogleMapsInfoBubble.java new file mode 100644 index 0000000..4aea17d --- /dev/null +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/GoogleMapsInfoBubble.java @@ -0,0 +1,93 @@ +package com.safemobile.dispatch; + +import android.content.Context; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.Marker; +import com.safemobile.lib.SuperVehicle; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Hashtable; +import java.util.Locale; + + +public class GoogleMapsInfoBubble implements GoogleMap.InfoWindowAdapter { + private final String TAG = GoogleMapsInfoBubble.class.getName(); + + private final View mWindow; + private final Hashtable superVehHash; + private final Context context; + + + public GoogleMapsInfoBubble(LayoutInflater layoutInflater, Context context, Hashtable vehicles) { + this.context = context; + this.superVehHash = vehicles; + mWindow = layoutInflater.inflate(R.layout.map_marker_info_bubble, null); + } + + @Override + public View getInfoWindow(@NonNull Marker marker) { + render(marker, mWindow); + return mWindow; + } + + @Override + public View getInfoContents(@NonNull Marker marker) { + render(marker, mWindow); + return mWindow; + } + + private void render(Marker marker, View view) { + long key = 0; + + try { + key = Long.parseLong(marker.getTitle()); + } catch (Exception ex) { + Log.v(TAG, "Unable to parse Google Maps Info Bubble title"); + } + SuperVehicle vehicle = superVehHash.get(key); + + RelativeLayout rlMapInfoBubbleInfo = view.findViewById(R.id.rlMapInfoBubbleInfo); + TextView tvUnitName = view.findViewById(R.id.tvUnitName); + TextView tvGPSLocation = view.findViewById(R.id.tvGPSLocation); + TextView tvTimeAgo = view.findViewById(R.id.tvTimeAgo); + TextView tvSpeed = view.findViewById(R.id.tvSpeed); + TextView tvStreetView = view.findViewById(R.id.tvStreetView); + ImageView streetView = view.findViewById(R.id.streetView); + rlMapInfoBubbleInfo.setVisibility(View.VISIBLE); + + boolean isMilitaryTime = false; + Date positionTime = new Date(vehicle.timeGMT); + + + String timeFormat = isMilitaryTime + ? "HH:mm:ss dd.MMM.yyyy" + : "hh:mm:ss a dd.MMM.yyy"; + + DateFormat format = new SimpleDateFormat(timeFormat, Locale.ENGLISH); + + tvTimeAgo.setText(format.format(positionTime)); + + tvSpeed.setText(String.format(context.getResources().getString(R.string.speedMph), vehicle.speed)); + + String address = vehicle.Address != null ? vehicle.Address : ""; + + tvStreetView.setText(address); + streetView.setVisibility(address.length() > 0 ? View.VISIBLE : View.GONE); + tvStreetView.setVisibility(address.length() > 0 ? View.VISIBLE : View.GONE); + tvUnitName.setText(vehicle.name); + tvGPSLocation.setText("[" + String.format("%.4f", vehicle.lat) + + "," + String.format("%.4f",vehicle.lng) + "]"); + } +} + diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java index 081e942..3cf2168 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java @@ -32,6 +32,8 @@ import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; @@ -307,7 +309,8 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall @Override public void onMapReady(@NonNull GoogleMap googleMap) { this.googleMap = googleMap; - + GoogleMapsInfoBubble infoBubble = new GoogleMapsInfoBubble(getLayoutInflater(), this, getParentTab().SuperVehHash); + this.googleMap.setInfoWindowAdapter(infoBubble); // Add a marker in Sydney and move the camera LatLng sydney = new LatLng(-34, 151); this.googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney")); @@ -475,12 +478,12 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall if (tmpSuper != null) { LatLng newLocation = new LatLng(tmpSuper.lat, tmpSuper.lng); - MarkerOptions markerOptions = new MarkerOptions().position(newLocation).title(tmpSuper.name); + MarkerOptions markerOptions = new MarkerOptions().position(newLocation).title(liveVehicle.get(i).imei); BitmapDescriptor markerIcon = getProperBitmap(tmpSuper.getLargeIcon(), tmpSuper.name); markerOptions.icon(markerIcon); - Marker marker = this.googleMap.addMarker(markerOptions); + Marker marker = this.googleMap.addMarker(markerOptions); } } } diff --git a/safeDispatch/src/main/res/values-de/strings.xml b/safeDispatch/src/main/res/values-de/strings.xml index caf053d..c0fd0fc 100644 --- a/safeDispatch/src/main/res/values-de/strings.xml +++ b/safeDispatch/src/main/res/values-de/strings.xml @@ -232,4 +232,7 @@ German Romanian + + %1$d mph + \ No newline at end of file diff --git a/safeDispatch/src/main/res/values-es/strings.xml b/safeDispatch/src/main/res/values-es/strings.xml index 6f0fd3c..c8269bb 100644 --- a/safeDispatch/src/main/res/values-es/strings.xml +++ b/safeDispatch/src/main/res/values-es/strings.xml @@ -236,4 +236,7 @@ Spanish Russian + + %1$d mph + \ No newline at end of file diff --git a/safeDispatch/src/main/res/values-ro/strings.xml b/safeDispatch/src/main/res/values-ro/strings.xml index d1a0dff..168d4fb 100644 --- a/safeDispatch/src/main/res/values-ro/strings.xml +++ b/safeDispatch/src/main/res/values-ro/strings.xml @@ -233,4 +233,7 @@ Turca Romana + + %1$d mph + \ No newline at end of file diff --git a/safeDispatch/src/main/res/values-tr/strings.xml b/safeDispatch/src/main/res/values-tr/strings.xml index 21068cd..b7fd8ac 100644 --- a/safeDispatch/src/main/res/values-tr/strings.xml +++ b/safeDispatch/src/main/res/values-tr/strings.xml @@ -232,4 +232,7 @@ German Romanian + + %1$d mph + \ No newline at end of file diff --git a/safeDispatch/src/main/res/values/strings.xml b/safeDispatch/src/main/res/values/strings.xml index 6630330..f415089 100644 --- a/safeDispatch/src/main/res/values/strings.xml +++ b/safeDispatch/src/main/res/values/strings.xml @@ -254,4 +254,8 @@ NewLiveActivity GoogleMapsActivity + + + %1$d mph + \ No newline at end of file From b91931e8330f092df1517ad583d10284039bead3 Mon Sep 17 00:00:00 2001 From: CiufudeanDani Date: Wed, 16 Mar 2022 14:32:28 +0200 Subject: [PATCH 4/7] small changes --- .../safemobile/dispatch/IconContextMenu.java | 29 +++----- .../com/safemobile/dispatch/LiveActivity.java | 72 ++++++------------- 2 files changed, 31 insertions(+), 70 deletions(-) diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/IconContextMenu.java b/safeDispatch/src/main/java/com/safemobile/dispatch/IconContextMenu.java index 22fb898..bcd2fae 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/IconContextMenu.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/IconContextMenu.java @@ -42,10 +42,9 @@ public class IconContextMenu implements DialogInterface.OnCancelListener, private static final int LIST_PREFERED_HEIGHT = 65; - private IconMenuAdapter menuAdapter = null; - private Activity parentActivity = null; - private int dialogId = 0; - + private IconMenuAdapter menuAdapter; + private Activity parentActivity; + private IconContextMenuOnClickListener clickHandler = null; /** @@ -55,8 +54,7 @@ public class IconContextMenu implements DialogInterface.OnCancelListener, */ public IconContextMenu(Activity parent, int id) { this.parentActivity = parent; - this.dialogId = id; - + menuAdapter = new IconMenuAdapter(parentActivity); } @@ -89,19 +87,13 @@ public class IconContextMenu implements DialogInterface.OnCancelListener, public Dialog createMenu(String menuItitle) { final AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); builder.setTitle(menuItitle); - builder.setAdapter(menuAdapter, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialoginterface, int i) { - IconContextMenuItem item = (IconContextMenuItem) menuAdapter.getItem(i); - - if (clickHandler != null) { - clickHandler.onClick(item.actionTag); - } - } + builder.setAdapter(menuAdapter, (dialoginterface, i) -> { + IconContextMenuItem item = (IconContextMenuItem) menuAdapter.getItem(i); + if (clickHandler != null) + clickHandler.onClick(item.actionTag); }); builder.setInverseBackgroundForced(true); - AlertDialog dialog = builder.create(); dialog.setOnCancelListener(this); dialog.setOnDismissListener(this); @@ -117,7 +109,7 @@ public class IconContextMenu implements DialogInterface.OnCancelListener, } private void cleanup() { - parentActivity.dismissDialog(dialogId); +// parentActivity.dismissDialog(dialogId); } /** @@ -131,7 +123,7 @@ public class IconContextMenu implements DialogInterface.OnCancelListener, * Menu-like list adapter with icon */ protected class IconMenuAdapter extends BaseAdapter { - private Context context = null; + private Context context; private ArrayList mItems = new ArrayList(); @@ -193,6 +185,7 @@ public class IconContextMenu implements DialogInterface.OnCancelListener, textView.setTag(item); textView.setText(item.text); textView.setCompoundDrawablesWithIntrinsicBounds(item.image, null, null, null); + textView.setTextColor(R.color.black); return textView; } diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java index 3cf2168..9731c77 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java @@ -22,7 +22,6 @@ import android.os.Handler; import android.os.Looper; import android.view.View; import android.view.Window; -import android.widget.AdapterView; import android.widget.Button; import android.widget.GridView; import android.widget.ImageButton; @@ -32,8 +31,6 @@ import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.constraintlayout.widget.ConstraintLayout; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; @@ -42,7 +39,6 @@ import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.safemobile.activities.AbstractLiveActivity; import com.safemobile.activities.AbstractSDParentActivity; @@ -142,12 +138,11 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall mapFragment.getMapAsync(this); } - // create on vehicle long click menu createIconContextMenu(); // image View for changing map type satellite or map - ImageView changeMapTypeImageView = (ImageView) findViewById(R.id.changeMapType); + ImageView changeMapTypeImageView = findViewById(R.id.changeMapType); changeMapTypeImageView.setOnClickListener(v -> { if (googleMap.getMapType() == GoogleMap.MAP_TYPE_SATELLITE) { changeMapTypeImageView.setImageResource(R.drawable.satellite); @@ -158,7 +153,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall } }); - ImageView changeTrafficImageView = (ImageView) findViewById(R.id.changeTraffic); + ImageView changeTrafficImageView = findViewById(R.id.changeTraffic); changeTrafficImageView.setOnClickListener(v -> { if (googleMap.isTrafficEnabled()) { changeTrafficImageView.setImageResource(R.drawable.traffic_off); @@ -170,12 +165,12 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall }); // change tab header font - TextView textView1 = (TextView) findViewById(R.id.textView1); + TextView textView1 = findViewById(R.id.textView1); textView1.setTypeface(Typeface.createFromAsset(getAssets(), "Sketch_Block.ttf")); textView1.setTextSize(24); // get grid view and set empty data adapter - gridVehicle = (GridView) findViewById(R.id.gridVehicle); + gridVehicle = findViewById(R.id.gridVehicle); if (AppParams.DEMO) { disabledVehicles = new ArrayList<>(); @@ -197,14 +192,16 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall threadUI.start(); }); - // get vehicle menu creation - gridVehicle.setOnItemLongClickListener(itemLongClickHandler); + gridVehicle.setOnItemLongClickListener((adapterView, view, i, l) -> { + contextMenuPosition = position; + iconContextMenu.createMenu(getString(R.string.options)).show(); + return true; + }); - - LinearLayout slideLayout = (LinearLayout) findViewById(R.id.slidelayout); - ImageView slideLayoutImageView = (ImageView) findViewById(R.id.slideLayoutImage); - LinearLayout linearLayoutVehicles = (LinearLayout) findViewById(R.id.layoutBig); + LinearLayout slideLayout = findViewById(R.id.slidelayout); + ImageView slideLayoutImageView = findViewById(R.id.slideLayoutImage); + LinearLayout linearLayoutVehicles = findViewById(R.id.layoutBig); slideLayout.setOnClickListener(v -> { if (showVehicle) { linearLayoutVehicles.setVisibility(View.GONE); @@ -217,7 +214,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall } }); - imageViewCheckAll = (ImageButton) findViewById(R.id.imageCheckAll); + imageViewCheckAll = findViewById(R.id.imageCheckAll); imageViewCheckAll.setSelected(false); imageViewCheckAll.setOnClickListener(arg0 -> { for (int i = 0; i < displayedVehicles.size(); i++) @@ -235,7 +232,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall Enumeration keyList = getParentTab().SuperVehHash.keys(); while (keyList.hasMoreElements()) { - (Objects.requireNonNull(getParentTab().SuperVehHash.get((long) keyList.nextElement()))).needUpdate = true; + (Objects.requireNonNull(getParentTab().SuperVehHash.get(keyList.nextElement()))).needUpdate = true; } // change button title @@ -259,7 +256,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall displayVehicle(true, LAT_OUTLIMIT, LNG_OUTLIMIT); }); - displayButton = (Button) findViewById(R.id.buttonDisplay); + displayButton = findViewById(R.id.buttonDisplay); displayButton.setText(getString(R.string.displayAll)); @@ -271,7 +268,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall Enumeration keyList = getParentTab().SuperVehHash.keys(); while (keyList.hasMoreElements()) - (Objects.requireNonNull(getParentTab().SuperVehHash.get((long) keyList.nextElement()))).needUpdate = true; + (Objects.requireNonNull(getParentTab().SuperVehHash.get(keyList.nextElement()))).needUpdate = true; // change button title if (displayButton.getText().toString().equals(getString(R.string.displayAll))) { @@ -446,28 +443,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall }); } - /** - * create context menu - */ - @Override - public Dialog onCreateDialog(int id) { - if (id == 1) { - return iconContextMenu.createMenu(getString(R.string.options)); - } - return super.onCreateDialog(id); - } - - - /* list item long click handler - * used to show the context menu - */ - private final AdapterView.OnItemLongClickListener itemLongClickHandler = ((parent, view, position, id) -> { - // save position - contextMenuPosition = position; - showDialog(1); - return true; - }); - public void displayVehicle(boolean withZoom, double latZoom, double lngZoom) { if (googleMap != null) { googleMap.clear(); @@ -483,7 +458,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall BitmapDescriptor markerIcon = getProperBitmap(tmpSuper.getLargeIcon(), tmpSuper.name); markerOptions.icon(markerIcon); - Marker marker = this.googleMap.addMarker(markerOptions); + this.googleMap.addMarker(markerOptions); } } } @@ -491,7 +466,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall } public void showOpenedBalloon(boolean demo) { - int i =0; //TODO: add show balloon } @@ -561,9 +535,9 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall loadingDialog.setCancelable(true); loadingDialog.setCanceledOnTouchOutside(false); - Button cancel = (Button) loadingDialog.findViewById(R.id.buttonCancel); + Button cancel = loadingDialog.findViewById(R.id.buttonCancel); cancel.setVisibility(View.GONE); - TextView textView1 = (TextView) loadingDialog.findViewById(R.id.textView1); + TextView textView1 = loadingDialog.findViewById(R.id.textView1); textView1.setText(message); loadingDialog.show(); @@ -592,8 +566,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall disabledVehicles.add(!veh.status); // add vehicle to hash Table according to driver_id - if (tableHashOverlay.get((int) veh.driver_id) == null) // if doesn't exist - { + if (tableHashOverlay.get((int) veh.driver_id) == null) { ArrayList array = new ArrayList<>(); SuperVehicle superVehicle = new SuperVehicle(veh.sc_id, veh.imei, veh.lp, veh.name, veh.driver_id, veh.time_route, veh.GPS_reporting_interval, veh.is_stolen); array.add(superVehicle); @@ -610,7 +583,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall } // set adapter - adapter = new VehiclesGridViewAdapter(activity, context, list, disabledVehicles); adapter.notifyDataSetChanged(); @@ -629,7 +601,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall // show vehicles in gridView private void updateResultsUI() { gridVehicle.setAdapter(adapter); - try { // hide loading dialog loadingDialog.cancel(); @@ -688,11 +659,9 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall final Runnable updateOptionsRUN = this::updateOptionsUI; private void updateOptionsUI() { - SM.Debug("REFRESHDisableEnable" + (Boolean.TRUE.equals(disabledVehicles.get(contextMenuPosition)) ? "true" : "false")); // change Enable/Disable in adapter adapter.changeDisabled(contextMenuPosition, disabledVehicles.get(contextMenuPosition)); - } /** @@ -782,7 +751,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall // zone and channel change intent IntentFilter intentFilter = new IntentFilter(OperationCodes.UNIT_STATUS_UPDATE + ""); this.registerReceiver(mReceiver, intentFilter); - } //The BroadcastReceiver that listens for Notification broadcasts From 5349558aceb35ad911b066b37db8b8ac159d41a1 Mon Sep 17 00:00:00 2001 From: CiufudeanDani Date: Wed, 16 Mar 2022 14:41:05 +0200 Subject: [PATCH 5/7] display info when on move --- .../com/safemobile/dispatch/LiveActivity.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java index 9731c77..b444a3f 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/LiveActivity.java @@ -32,13 +32,13 @@ import android.widget.Toast; import androidx.annotation.NonNull; -import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.safemobile.activities.AbstractLiveActivity; import com.safemobile.activities.AbstractSDParentActivity; @@ -102,6 +102,7 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall //value poll private double latPoll = 0; private double lngPoll = 0; + private ArrayList markers = new ArrayList<>(); @Override @@ -308,10 +309,6 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall this.googleMap = googleMap; GoogleMapsInfoBubble infoBubble = new GoogleMapsInfoBubble(getLayoutInflater(), this, getParentTab().SuperVehHash); this.googleMap.setInfoWindowAdapter(infoBubble); - // Add a marker in Sydney and move the camera - LatLng sydney = new LatLng(-34, 151); - this.googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney")); - this.googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); } @@ -445,6 +442,12 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall public void displayVehicle(boolean withZoom, double latZoom, double lngZoom) { if (googleMap != null) { + String openWindow = ""; + for (Marker marker : markers) { + if (marker.isInfoWindowShown()) { + openWindow = marker.getTitle(); + } + } googleMap.clear(); for (int i = 0; i < displayedVehicles.size(); i++) { @@ -458,7 +461,11 @@ public class LiveActivity extends AbstractLiveActivity implements OnMapReadyCall BitmapDescriptor markerIcon = getProperBitmap(tmpSuper.getLargeIcon(), tmpSuper.name); markerOptions.icon(markerIcon); - this.googleMap.addMarker(markerOptions); + Marker marker = this.googleMap.addMarker(markerOptions); + if (openWindow.equals(marker.getTitle())) + marker.showInfoWindow(); + + markers.add(marker); } } } From 4439687405f0d4a573b63719bae4e3c8282bd5b0 Mon Sep 17 00:00:00 2001 From: CiufudeanDani Date: Wed, 16 Mar 2022 16:40:34 +0200 Subject: [PATCH 6/7] display history --- .../safemobile/dispatch/HistoryActivity.java | 6 + .../dispatch/TabLayoutActivity.java | 203 +++--- .../src/main/res/layout/tabhistory.xml | 625 +++++++++--------- safeDispatch/src/main/res/layout/tabpanel.xml | 181 +++-- 4 files changed, 482 insertions(+), 533 deletions(-) diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/HistoryActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/HistoryActivity.java index 87de241..5397cfa 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/HistoryActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/HistoryActivity.java @@ -9,12 +9,18 @@ import com.safemobile.lib.SM; public class HistoryActivity extends AppCompatActivity { public Bundle savedInstanceState; + private TabLayoutActivity parentTab; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.savedInstanceState = savedInstanceState; setContentView(R.layout.tabhistory); + + parentTab = (TabLayoutActivity) getParent(); + parentTab.historyActivity = this; + } public void UpdateMap() { diff --git a/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java b/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java index 423b978..7f1968c 100644 --- a/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java +++ b/safeDispatch/src/main/java/com/safemobile/dispatch/TabLayoutActivity.java @@ -12,7 +12,6 @@ import java.util.Locale; import java.util.Timer; import java.util.TimerTask; -/** fix import */ import com.safemobile.activities.AbstractEmptyActivity; import com.safemobile.activities.AbstractLiveActivity; import com.safemobile.activities.AbstractMessagesActivity; @@ -267,11 +266,11 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ tabHost = getTabHost(); // The activity TabHost tabHost.setTag("Tab Panel"); - tabWidget = (TabWidget) findViewById(android.R.id.tabs); + tabWidget = findViewById(android.R.id.tabs); tabWidget.setVisibility(View.GONE); - intent = new Intent[7]; - tabspecs = new TabSpec[7]; + intent = new Intent[8]; + tabspecs = new TabSpec[8]; // add live tab try @@ -290,23 +289,6 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ .setContent(intent[0]); } - // add history tab - try - { - //intent[1] = new Intent(context, HistoryActivity.class); - //tabspecs[1] = tabHost.newTabSpec("History") - // .setIndicator("History", res.getDrawable(R.drawable.ic_tab_history_selected)) - // .setContent(intent[1]); - } - catch(NoClassDefFoundError e) - { - // exception when GoogleApi not exists - //intent[1] = new Intent(context, AbstractEmptyActivity.class); - //tabspecs[1] = tabHost.newTabSpec("History") - // .setIndicator("History", res.getDrawable(R.drawable.ic_tab_history_selected)) - // .setContent(intent[1]); - } - // add text tab intent[1] = new Intent(context, MessagesActivity.class); tabspecs[1] = tabHost.newTabSpec("Text") @@ -342,6 +324,21 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ tabspecs[6] = tabHost.newTabSpec("SafeMobile") .setIndicator("SafeMobile", res.getDrawable(AppParams.DEMO ? R.drawable.icon_demo : R.drawable.ic_launcher)) .setContent(intent[6]); + + // add history tab + try + { + intent[7] = new Intent(context, HistoryActivity.class); + tabspecs[7] = tabHost.newTabSpec("History") + .setIndicator("History", res.getDrawable(R.drawable.ic_tab_history_selected)) + .setContent(intent[7]); + } catch(NoClassDefFoundError e) { +// exception when GoogleApi not exists + intent[7] = new Intent(context, AbstractEmptyActivity.class); + tabspecs[7] = tabHost.newTabSpec("History") + .setIndicator("History", res.getDrawable(R.drawable.ic_tab_history_selected)) + .setContent(intent[1]); + } // add tab in tabHost // for(int i=0;i<7;i++ @@ -355,76 +352,64 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ imageViewSlideMenu = (ImageView) findViewById(R.id.imageViewSlideMenu); // get Live Button - buttonLive = (ImageButton) findViewById(R.id.buttonLive); - buttonLive.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if(!buttonLive.isSelected()) - { - // select button - buttonLive.setSelected(true); - // deselect other buttons - buttonAlarms.setSelected(false); - buttonHistory.setSelected(false); - buttonRadio.setSelected(false); - buttonRecordings.setSelected(false); - buttonSetup.setSelected(false); - buttonText.setSelected(false); - // select tab - tabHost.setCurrentTabByTag("Live"); - AppParams.crtTab = AppParams.Tabs.live; - } + buttonLive = findViewById(R.id.buttonLive); + buttonLive.setOnClickListener(v -> { + if (!buttonLive.isSelected()) { + // select button + buttonLive.setSelected(true); + // deselect other buttons + buttonAlarms.setSelected(false); + buttonHistory.setSelected(false); + buttonRadio.setSelected(false); + buttonRecordings.setSelected(false); + buttonSetup.setSelected(false); + buttonText.setSelected(false); + // select tab + tabHost.setCurrentTabByTag("Live"); + AppParams.crtTab = AppParams.Tabs.live; } }); // get History Button - buttonHistory = (ImageButton) findViewById(R.id.buttonHistory); - buttonHistory.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if(!buttonHistory.isSelected()) - { - // select button - buttonHistory.setSelected(true); - // deselect other buttons - buttonAlarms.setSelected(false); - buttonLive.setSelected(false); - buttonRadio.setSelected(false); - buttonRecordings.setSelected(false); - buttonSetup.setSelected(false); - buttonText.setSelected(false); - // select tab - tabHost.setCurrentTabByTag("History"); - AppParams.crtTab = AppParams.Tabs.history; - } + buttonHistory = findViewById(R.id.buttonHistory); + buttonHistory.setOnClickListener(v -> { + if (!buttonHistory.isSelected()) { + // select button + buttonHistory.setSelected(true); + // deselect other buttons + buttonAlarms.setSelected(false); + buttonLive.setSelected(false); + buttonRadio.setSelected(false); + buttonRecordings.setSelected(false); + buttonSetup.setSelected(false); + buttonText.setSelected(false); + // select tab + tabHost.setCurrentTabByTag("History"); + AppParams.crtTab = AppParams.Tabs.history; } }); // get Text Button - buttonText= (ImageButton) findViewById(R.id.buttonText); - buttonText.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if(!buttonText.isSelected()) + buttonText= findViewById(R.id.buttonText); + buttonText.setOnClickListener(v -> { + if (!buttonText.isSelected()) { + // select button + buttonText.setSelected(true); + // deselect other buttons + buttonAlarms.setSelected(false); + buttonLive.setSelected(false); + buttonRadio.setSelected(false); + buttonRecordings.setSelected(false); + buttonSetup.setSelected(false); + buttonHistory.setSelected(false); + // select tab + tabHost.setCurrentTabByTag("Text"); + AppParams.crtTab = AppParams.Tabs.message; + + if(AppParams.DEMO && messageActivity.allVehicle.size()== 0) { - // select button - buttonText.setSelected(true); - // deselect other buttons - buttonAlarms.setSelected(false); - buttonLive.setSelected(false); - buttonRadio.setSelected(false); - buttonRecordings.setSelected(false); - buttonSetup.setSelected(false); - buttonHistory.setSelected(false); - // select tab - tabHost.setCurrentTabByTag("Text"); - AppParams.crtTab = AppParams.Tabs.message; - - if(AppParams.DEMO && messageActivity.allVehicle.size()== 0) - { - messageActivity.UpdateVehs(allVehicle); - messageActivity.UpdateSMS(listSMS); - } + messageActivity.UpdateVehs(allVehicle); + messageActivity.UpdateSMS(listSMS); } } }); @@ -611,24 +596,21 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ }); // get About Button - buttonLogo = (ImageButton) findViewById(R.id.buttonLogo); - buttonLogo.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - // create dialog - final Dialog dialog = new Dialog(context); - dialog.setTitle(AppParams.DEMO ? getString(R.string.app_name_demo) : getString(R.string.app_name)); - dialog.setContentView(R.layout.dialog); - ImageView image = (ImageView) dialog.findViewById(R.id.image); - image.setImageResource(AppParams.DEMO ? R.drawable.icon_demo : R.drawable.ic_launcher); - TextView text = (TextView) dialog.findViewById(R.id.text); - TextView text2 = (TextView) dialog.findViewById(R.id.text2); - text.setText(getString(R.string.version) + "1.0.8"); - text2.setText(getString(R.string.email) + ": support@safemobile.com"); - dialog.setCancelable(true); - dialog.setCanceledOnTouchOutside(true); - dialog.show(); - } + buttonLogo = findViewById(R.id.buttonLogo); + buttonLogo.setOnClickListener(v -> { + // create dialog + final Dialog dialog = new Dialog(context); + dialog.setTitle(AppParams.DEMO ? getString(R.string.app_name_demo) : getString(R.string.app_name)); + dialog.setContentView(R.layout.dialog); + ImageView image = dialog.findViewById(R.id.image); + image.setImageResource(AppParams.DEMO ? R.drawable.icon_demo : R.drawable.ic_launcher); + TextView text = dialog.findViewById(R.id.text); + TextView text2 = dialog.findViewById(R.id.text2); + text.setText(getString(R.string.version) + "1.0.8"); + text2.setText(getString(R.string.email) + ": support@safemobile.com"); + dialog.setCancelable(true); + dialog.setCanceledOnTouchOutside(true); + dialog.show(); }); imageViewClose.setOnTouchListener(new OnTouchListener() { @@ -1457,28 +1439,19 @@ public class TabLayoutActivity extends AbstractSDParentActivity{ } // if tab is not TextTab - if(tabHost.getCurrentTab() != 2) - { + if(tabHost.getCurrentTab() != 2) { myHandler.post(UpdateResults); //mHandler.dispatchMessage(new Message()); - } - else - myHandler.post(new Runnable() { - - @Override - public void run() { - // create Notification - createNotification(AppParams.messageNotif); - } + } else + myHandler.post(() -> { + // create Notification + createNotification(AppParams.messageNotif); }); //list for SMS - if(AppParams.crtTab == AppParams.Tabs.message && messageActivity!= null) - { + if(AppParams.crtTab == AppParams.Tabs.message && messageActivity!= null) { SM.Debug("currentActivity instanceof MessagesActivity - NewSMS | " + tempArr[0] + " | " + tempArr[1]); messageActivity.NewSMS(tempArr[0], tempArr[1], time); } - - } @Override diff --git a/safeDispatch/src/main/res/layout/tabhistory.xml b/safeDispatch/src/main/res/layout/tabhistory.xml index 10a0b62..f952944 100644 --- a/safeDispatch/src/main/res/layout/tabhistory.xml +++ b/safeDispatch/src/main/res/layout/tabhistory.xml @@ -5,337 +5,328 @@ android:id="@+id/tab1Layout" android:orientation="horizontal" style="?bg"> - + - + - - + + - + - + - + - + - + - - - - - + + + - + - - - - - - + + + + - + android:id="@+id/LayoutSpinner" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:paddingTop="10dp" + android:gravity="top" + android:layout_weight="1"> + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + -