From ce9364fa8cadd978c85787053c888d4730940b8d Mon Sep 17 00:00:00 2001 From: graiola Date: Sat, 19 Nov 2022 14:46:57 +0100 Subject: [PATCH 01/14] gps2ros --- .idea/runConfigurations.xml | 12 ---- .../widgets/gps2ros/Gps2RosData.java | 59 +++++++++++++++++++ .../widgets/gps2ros/Gps2RosDetailVH.java | 45 ++++++++++++++ .../widgets/gps2ros/Gps2RosEntity.java | 33 +++++++++++ .../widgets/gps2ros/Gps2RosView.java | 56 ++++++++++++++++++ .../main/res/layout/widget_detail_gps2ros.xml | 15 +++++ app/src/main/res/values/widgets.xml | 6 ++ 7 files changed, 214 insertions(+), 12 deletions(-) delete mode 100644 .idea/runConfigurations.xml create mode 100644 app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java create mode 100644 app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java create mode 100644 app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java create mode 100644 app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java create mode 100644 app/src/main/res/layout/widget_detail_gps2ros.xml diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460d..00000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java new file mode 100644 index 00000000..100fe2e4 --- /dev/null +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java @@ -0,0 +1,59 @@ +package com.schneewittchen.rosandroid.widgets.gps2ros; + +import com.schneewittchen.rosandroid.model.repositories.rosRepo.node.BaseData; +import com.schneewittchen.rosandroid.model.entities.widgets.BaseEntity; + +import org.ros.internal.message.Message; +import org.ros.node.topic.Publisher; + +import sensor_msgs.NavSatFix; + + +/** + * TODO: Description + * + * @author Gennaro Raiola + * @version 0.0.1 + * @created on 19.11.22 + */ +public class Gps2RosData extends BaseData { + + @Override + public Message toRosMessage(Publisher publisher, BaseEntity widget) { + + sensor_msgs.NavSatFix message = (NavSatFix) publisher.newMessage(); + + /*JoystickEntity joyWidget = (JoystickEntity) widget; + + float xAxisValue = joyWidget.xScaleLeft + (joyWidget.xScaleRight - joyWidget.xScaleLeft) * ((x+1) /2f); + float yAxisValue = joyWidget.yScaleLeft + (joyWidget.yScaleRight - joyWidget.yScaleLeft) * ((y+1) /2f); + + geometry_msgs.Twist message = (Twist) publisher.newMessage(); + + for (int i = 0; i < 2; i++) { + String[] splitMapping = (i == 0? joyWidget.xAxisMapping : joyWidget.yAxisMapping).split("/"); + float value = i == 0? xAxisValue : yAxisValue; + + Vector3 dirVector; + if (splitMapping[0].equals("Linear")) { + dirVector = message.getLinear(); + } else { + dirVector = message.getAngular(); + } + + switch (splitMapping[1]) { + case "X": + dirVector.setX(value); + break; + case "Y": + dirVector.setY(value); + break; + case "Z": + dirVector.setZ(value); + break; + } + }*/ + + return message; + } +} diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java new file mode 100644 index 00000000..b4b323a0 --- /dev/null +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java @@ -0,0 +1,45 @@ +package com.schneewittchen.rosandroid.widgets.gps2ros; + +import android.view.View; + +import com.schneewittchen.rosandroid.model.entities.widgets.BaseEntity; +import com.schneewittchen.rosandroid.ui.views.details.PublisherWidgetViewHolder; + +import java.util.Collections; +import java.util.List; + +import sensor_msgs.NavSatFix; + + +/** + * TODO: Description + * + * @author Gennaro Raiola + * @version 0.0.1 + * @created on 19.11.22 + */ +public class Gps2RosDetailVH extends PublisherWidgetViewHolder { + + + + @Override + public void initView(View view) { + + } + + @Override + public void bindEntity(BaseEntity entity) { + + } + + + @Override + public void updateEntity(BaseEntity entity) { + + } + + @Override + public List getTopicTypes() { + return Collections.singletonList(NavSatFix._TYPE); + } +} diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java new file mode 100644 index 00000000..58430580 --- /dev/null +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java @@ -0,0 +1,33 @@ +package com.schneewittchen.rosandroid.widgets.gps2ros; + +import com.schneewittchen.rosandroid.model.entities.widgets.PublisherWidgetEntity; +import com.schneewittchen.rosandroid.model.repositories.rosRepo.message.Topic; + +import sensor_msgs.NavSatFix; + + +/** + * TODO: Description + * + * @author Gennaro Raiola + * @version 0.0.1 + * @created on 19.11.22 + */ +public class Gps2RosEntity extends PublisherWidgetEntity { + + public double longitude; + public double latitude; + + + public Gps2RosEntity() { + this.width = 4; + this.height = 4; + this.topic = new Topic("gps_android", NavSatFix._TYPE); + this.immediatePublish = false; + this.publishRate = 20f; + this.longitude = 0.0; + this.latitude = 0.0; + + } + +} diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java new file mode 100644 index 00000000..9ef69b91 --- /dev/null +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java @@ -0,0 +1,56 @@ +package com.schneewittchen.rosandroid.widgets.gps2ros; + +import android.content.Context; +import android.graphics.Canvas; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.annotation.Nullable; + +import com.schneewittchen.rosandroid.ui.views.widgets.PublisherWidgetView; + + +/** + * TODO: Description + * + * @author Gennaro Raiola + * @version 0.0.1 + * @created on 19.11.22 + */ +public class Gps2RosView extends PublisherWidgetView { + + public static final String TAG = Gps2RosView.class.getSimpleName(); + + public Gps2RosView(Context context) { + super(context); + init(); + } + + public Gps2RosView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + + private void init(){ + + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (this.editMode) { + return super.onTouchEvent(event); + } + return true; + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + + + } + + + +} diff --git a/app/src/main/res/layout/widget_detail_gps2ros.xml b/app/src/main/res/layout/widget_detail_gps2ros.xml new file mode 100644 index 00000000..e98f3352 --- /dev/null +++ b/app/src/main/res/layout/widget_detail_gps2ros.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/widgets.xml b/app/src/main/res/values/widgets.xml index 93278309..9fd5568e 100644 --- a/app/src/main/res/values/widgets.xml +++ b/app/src/main/res/values/widgets.xml @@ -12,6 +12,7 @@ Logger RqtPlot Viz2D + Gps2Ros @@ -112,6 +113,11 @@ automatically go back to center. + + + TODO + + Linear Angular From 5a1e2af0912317d5021ffd49587463ec907ebb80 Mon Sep 17 00:00:00 2001 From: graiola Date: Sun, 20 Nov 2022 21:37:19 +0100 Subject: [PATCH 02/14] Add background location permission --- app/src/main/AndroidManifest.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1c3392df..65351d53 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,8 @@ + + - + + + \ No newline at end of file From 94b3cbb9d661a8fe80a30017b8b9d0af7fdb85f3 Mon Sep 17 00:00:00 2001 From: graiola Date: Sun, 20 Nov 2022 21:37:35 +0100 Subject: [PATCH 03/14] Move gps2ros description --- app/src/main/res/values/widgets.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values/widgets.xml b/app/src/main/res/values/widgets.xml index 9fd5568e..73534cdb 100644 --- a/app/src/main/res/values/widgets.xml +++ b/app/src/main/res/values/widgets.xml @@ -100,6 +100,10 @@ You can zoom in and out by pinching 2 or more fingers together or apart. + + + TODO + @@ -113,11 +117,6 @@ automatically go back to center. - - - TODO - - Linear Angular From f06ce79c9d561c227100ae4e0cc8c0590ed38cfb Mon Sep 17 00:00:00 2001 From: graiola Date: Sun, 20 Nov 2022 21:37:45 +0100 Subject: [PATCH 04/14] More permissions --- jcraft/src/main/AndroidManifest.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/jcraft/src/main/AndroidManifest.xml b/jcraft/src/main/AndroidManifest.xml index 1438840c..29a0cd81 100644 --- a/jcraft/src/main/AndroidManifest.xml +++ b/jcraft/src/main/AndroidManifest.xml @@ -1,2 +1,8 @@ + package="com.jcraft" > + + + + + + From 45e4eec4c8003abd168af22f80eca78e3412a3df Mon Sep 17 00:00:00 2001 From: graiola Date: Sun, 20 Nov 2022 21:38:08 +0100 Subject: [PATCH 05/14] Hacking around --- .../widgets/gps2ros/Gps2RosData.java | 43 ++----- .../widgets/gps2ros/Gps2RosDetailVH.java | 11 +- .../widgets/gps2ros/Gps2RosEntity.java | 10 +- .../widgets/gps2ros/Gps2RosView.java | 111 +++++++++++++++++- 4 files changed, 127 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java index 100fe2e4..3663bc82 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java @@ -2,6 +2,7 @@ import com.schneewittchen.rosandroid.model.repositories.rosRepo.node.BaseData; import com.schneewittchen.rosandroid.model.entities.widgets.BaseEntity; +import com.schneewittchen.rosandroid.widgets.joystick.JoystickEntity; import org.ros.internal.message.Message; import org.ros.node.topic.Publisher; @@ -18,41 +19,23 @@ */ public class Gps2RosData extends BaseData { + double latitude; + double longitude; + + public Gps2RosData(double lat, double lon) { + latitude = lat; + longitude = lon; + } + @Override public Message toRosMessage(Publisher publisher, BaseEntity widget) { + Gps2RosEntity gps2rosWidget = (Gps2RosEntity) widget; + sensor_msgs.NavSatFix message = (NavSatFix) publisher.newMessage(); - /*JoystickEntity joyWidget = (JoystickEntity) widget; - - float xAxisValue = joyWidget.xScaleLeft + (joyWidget.xScaleRight - joyWidget.xScaleLeft) * ((x+1) /2f); - float yAxisValue = joyWidget.yScaleLeft + (joyWidget.yScaleRight - joyWidget.yScaleLeft) * ((y+1) /2f); - - geometry_msgs.Twist message = (Twist) publisher.newMessage(); - - for (int i = 0; i < 2; i++) { - String[] splitMapping = (i == 0? joyWidget.xAxisMapping : joyWidget.yAxisMapping).split("/"); - float value = i == 0? xAxisValue : yAxisValue; - - Vector3 dirVector; - if (splitMapping[0].equals("Linear")) { - dirVector = message.getLinear(); - } else { - dirVector = message.getAngular(); - } - - switch (splitMapping[1]) { - case "X": - dirVector.setX(value); - break; - case "Y": - dirVector.setY(value); - break; - case "Z": - dirVector.setZ(value); - break; - } - }*/ + message.setLatitude(latitude); + message.setLongitude(longitude); return message; } diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java index b4b323a0..86f8c6f8 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java @@ -4,13 +4,13 @@ import com.schneewittchen.rosandroid.model.entities.widgets.BaseEntity; import com.schneewittchen.rosandroid.ui.views.details.PublisherWidgetViewHolder; +import com.schneewittchen.rosandroid.widgets.joystick.JoystickEntity; import java.util.Collections; import java.util.List; import sensor_msgs.NavSatFix; - /** * TODO: Description * @@ -20,26 +20,23 @@ */ public class Gps2RosDetailVH extends PublisherWidgetViewHolder { - - @Override public void initView(View view) { - } @Override public void bindEntity(BaseEntity entity) { - + Gps2RosEntity widget = (Gps2RosEntity) entity; } - @Override public void updateEntity(BaseEntity entity) { - + Gps2RosEntity widget = (Gps2RosEntity) entity; } @Override public List getTopicTypes() { return Collections.singletonList(NavSatFix._TYPE); } + } diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java index 58430580..34febdfc 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java @@ -5,6 +5,7 @@ import sensor_msgs.NavSatFix; +import androidx.core.app.ActivityCompat; /** * TODO: Description @@ -13,11 +14,8 @@ * @version 0.0.1 * @created on 19.11.22 */ -public class Gps2RosEntity extends PublisherWidgetEntity { - - public double longitude; - public double latitude; +public class Gps2RosEntity extends PublisherWidgetEntity { public Gps2RosEntity() { this.width = 4; @@ -25,9 +23,5 @@ public Gps2RosEntity() { this.topic = new Topic("gps_android", NavSatFix._TYPE); this.immediatePublish = false; this.publishRate = 20f; - this.longitude = 0.0; - this.latitude = 0.0; - } - } diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java index 9ef69b91..4a363fd2 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java @@ -2,13 +2,26 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; +import android.location.LocationListener; +import android.location.LocationManager; import android.util.AttributeSet; +import android.util.TypedValue; import android.view.MotionEvent; import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import com.schneewittchen.rosandroid.R; import com.schneewittchen.rosandroid.ui.views.widgets.PublisherWidgetView; +import android.Manifest; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.location.Location; +import android.util.Log; +import android.location.LocationProvider; + /** * TODO: Description @@ -17,40 +30,132 @@ * @version 0.0.1 * @created on 19.11.22 */ -public class Gps2RosView extends PublisherWidgetView { +public class Gps2RosView extends PublisherWidgetView implements LocationListener { public static final String TAG = Gps2RosView.class.getSimpleName(); + Paint textPaint; + float textSize; + float borderWidth; + String displayedText; + + protected LocationManager locationManager; + protected LocationListener locationListener; + protected boolean gps_enabled, network_enabled; + double latitude; + double longitude; + Context context; + + public Gps2RosView(Context context) { super(context); + this.context = context; init(); } public Gps2RosView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); + this.context = context; init(); } + + private void init() { + + float textDip = 18f; + float borderDip = 10f; + + textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, textDip, + getResources().getDisplayMetrics()); + borderWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, borderDip, + getResources().getDisplayMetrics()); + + borderWidth = 10; + + textPaint = new Paint(); + textPaint.setColor(getResources().getColor(R.color.whiteHigh)); + textPaint.setTextAlign(Paint.Align.CENTER); + textPaint.setTextSize(textSize); + + + locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + Log.e("Gps2RosView","checkSelfPermission!"); + return; + } + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); + locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); - private void init(){ + final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + if (!gpsEnabled) { + Log.e("Gps2RosView","gpsEnabled"); + return; + } } - @Override + + @Override public boolean onTouchEvent(MotionEvent event) { if (this.editMode) { return super.onTouchEvent(event); } + Log.i("Gps2RosView","Longitude: "+longitude+" Latitude: " + latitude); + return true; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); + float width = getWidth(); + float height = getHeight(); + float middleX = width/2; + + float left = borderWidth/2; + float right = width - borderWidth/2; + float top = borderWidth * 2; + float bottom = height - borderWidth - textSize; + + // Draw status text + displayedText = ("GPS 2 ROS"); + canvas.drawText(displayedText, middleX, height, textPaint); + } + + @Override + public void onLocationChanged(Location location) { + latitude = location.getLatitude(); + longitude = location.getLongitude(); + + Log.i("Gps2RosView","Longitude: "+longitude+" Latitude: " + latitude); + + Gps2RosData data = new Gps2RosData(latitude,longitude); + this.publishViewData(data); + } + @Override + public void onProviderDisabled(String provider) { + Log.d("Gps2RosView","disable"); } + @Override + public void onProviderEnabled(String provider) { + Log.d("Gps2RosView","enable"); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + + Log.d("Gps2RosView","status"); + } } From 353be366a4d7b1b54f6fa27aa2c84a09ee09fcc5 Mon Sep 17 00:00:00 2001 From: graiola Date: Sun, 20 Nov 2022 23:09:56 +0100 Subject: [PATCH 06/14] To Test with real hw --- .../widgets/gps2ros/Gps2RosData.java | 9 +- .../widgets/gps2ros/Gps2RosDetailVH.java | 30 ++++- .../widgets/gps2ros/Gps2RosEntity.java | 12 +- .../widgets/gps2ros/Gps2RosView.java | 121 ++++++++++-------- .../main/res/layout/widget_detail_gps2ros.xml | 73 ++++++++++- app/src/main/res/values/widgets.xml | 10 +- 6 files changed, 184 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java index 3663bc82..035a7387 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java @@ -2,7 +2,6 @@ import com.schneewittchen.rosandroid.model.repositories.rosRepo.node.BaseData; import com.schneewittchen.rosandroid.model.entities.widgets.BaseEntity; -import com.schneewittchen.rosandroid.widgets.joystick.JoystickEntity; import org.ros.internal.message.Message; import org.ros.node.topic.Publisher; @@ -22,16 +21,14 @@ public class Gps2RosData extends BaseData { double latitude; double longitude; - public Gps2RosData(double lat, double lon) { - latitude = lat; - longitude = lon; + public Gps2RosData(double latitude, double longitude) { + this.latitude = latitude; + this.longitude = longitude; } @Override public Message toRosMessage(Publisher publisher, BaseEntity widget) { - Gps2RosEntity gps2rosWidget = (Gps2RosEntity) widget; - sensor_msgs.NavSatFix message = (NavSatFix) publisher.newMessage(); message.setLatitude(latitude); diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java index 86f8c6f8..d4fdbb1f 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java @@ -1,10 +1,14 @@ package com.schneewittchen.rosandroid.widgets.gps2ros; import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.Spinner; +import com.schneewittchen.rosandroid.R; import com.schneewittchen.rosandroid.model.entities.widgets.BaseEntity; import com.schneewittchen.rosandroid.ui.views.details.PublisherWidgetViewHolder; -import com.schneewittchen.rosandroid.widgets.joystick.JoystickEntity; +import com.schneewittchen.rosandroid.utility.Utils; import java.util.Collections; import java.util.List; @@ -20,18 +24,38 @@ */ public class Gps2RosDetailVH extends PublisherWidgetViewHolder { + private EditText textText; + private Spinner rotationSpinner; + private ArrayAdapter rotationAdapter; + @Override public void initView(View view) { + textText = view.findViewById(R.id.btnTextTypeText); + rotationSpinner = view.findViewById(R.id.btnTextRotation); + + // Init spinner + rotationAdapter = ArrayAdapter.createFromResource(view.getContext(), + R.array.button_rotation, android.R.layout.simple_spinner_dropdown_item); + + rotationSpinner.setAdapter(rotationAdapter); } @Override public void bindEntity(BaseEntity entity) { - Gps2RosEntity widget = (Gps2RosEntity) entity; + Gps2RosEntity gps2rosEntity = (Gps2RosEntity) entity; + + textText.setText(gps2rosEntity.text); + String degrees = Utils.numberToDegrees(gps2rosEntity.rotation); + rotationSpinner.setSelection(rotationAdapter.getPosition(degrees)); } @Override public void updateEntity(BaseEntity entity) { - Gps2RosEntity widget = (Gps2RosEntity) entity; + Gps2RosEntity gps2rosEntity = (Gps2RosEntity) entity; + + gps2rosEntity.text = textText.getText().toString(); + String degrees = rotationSpinner.getSelectedItem().toString(); + gps2rosEntity.rotation = Utils.degreesToNumber(degrees); } @Override diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java index 34febdfc..1dfde737 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java @@ -4,8 +4,7 @@ import com.schneewittchen.rosandroid.model.repositories.rosRepo.message.Topic; import sensor_msgs.NavSatFix; - -import androidx.core.app.ActivityCompat; +import std_msgs.Bool; /** * TODO: Description @@ -17,11 +16,16 @@ public class Gps2RosEntity extends PublisherWidgetEntity { + public String text; + public int rotation; + public Gps2RosEntity() { this.width = 4; this.height = 4; this.topic = new Topic("gps_android", NavSatFix._TYPE); - this.immediatePublish = false; - this.publishRate = 20f; + this.immediatePublish = true; + //this.publishRate = 20f; + this.text = "Publish GPS 2 ROS"; + this.rotation = 0; } } diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java index 4a363fd2..08884633 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java @@ -2,11 +2,15 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Rect; import android.location.LocationListener; import android.location.LocationManager; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; import android.util.AttributeSet; -import android.util.TypedValue; import android.view.MotionEvent; import androidx.annotation.Nullable; @@ -20,7 +24,6 @@ import android.os.Bundle; import android.location.Location; import android.util.Log; -import android.location.LocationProvider; /** @@ -34,19 +37,16 @@ public class Gps2RosView extends PublisherWidgetView implements LocationListener public static final String TAG = Gps2RosView.class.getSimpleName(); - Paint textPaint; - float textSize; - float borderWidth; - String displayedText; + Paint buttonPaint; + TextPaint textPaint; + StaticLayout staticLayout; + boolean buttonPressed; protected LocationManager locationManager; - protected LocationListener locationListener; - protected boolean gps_enabled, network_enabled; double latitude; double longitude; Context context; - public Gps2RosView(Context context) { super(context); this.context = context; @@ -58,24 +58,20 @@ public Gps2RosView(Context context, @Nullable AttributeSet attrs) { this.context = context; init(); } - - private void init() { - - float textDip = 18f; - float borderDip = 10f; - textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, textDip, - getResources().getDisplayMetrics()); - borderWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, borderDip, - getResources().getDisplayMetrics()); + private void init() { - borderWidth = 10; + // By default it is ... + buttonPressed = false; - textPaint = new Paint(); - textPaint.setColor(getResources().getColor(R.color.whiteHigh)); - textPaint.setTextAlign(Paint.Align.CENTER); - textPaint.setTextSize(textSize); + buttonPaint = new Paint(); + buttonPaint.setColor(getResources().getColor(R.color.colorPrimary)); + buttonPaint.setStyle(Paint.Style.FILL_AND_STROKE); + textPaint = new TextPaint(); + textPaint.setColor(Color.BLACK); + textPaint.setStyle(Paint.Style.FILL_AND_STROKE); + textPaint.setTextSize(26 * getResources().getDisplayMetrics().density); locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { @@ -86,76 +82,99 @@ private void init() { // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. - Log.e("Gps2RosView","checkSelfPermission!"); + Log.e("Gps2RosView","check permissions failed!"); return; } locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); - locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); + //locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - if (!gpsEnabled) { - Log.e("Gps2RosView","gpsEnabled"); + Log.e("Gps2RosView","gps is not enabled!"); return; } } + private void changeState(boolean pressed) { + this.buttonPressed = pressed; + invalidate(); + } - @Override + @Override public boolean onTouchEvent(MotionEvent event) { if (this.editMode) { return super.onTouchEvent(event); } - Log.i("Gps2RosView","Longitude: "+longitude+" Latitude: " + latitude); + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + if(buttonPressed) { + buttonPaint.setColor(getResources().getColor(R.color.colorPrimary)); + changeState(false); + } + else + { + buttonPaint.setColor(getResources().getColor(R.color.color_attention)); + changeState(true); + } + break; + default: + return false; + } return true; } @Override public void onDraw(Canvas canvas) { - super.onDraw(canvas); float width = getWidth(); float height = getHeight(); - float middleX = width/2; + float textLayoutWidth = width; - float left = borderWidth/2; - float right = width - borderWidth/2; - float top = borderWidth * 2; - float bottom = height - borderWidth - textSize; + Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; - // Draw status text - displayedText = ("GPS 2 ROS"); - canvas.drawText(displayedText, middleX, height, textPaint); + if (entity.rotation == 90 || entity.rotation == 270) { + textLayoutWidth = height; + } + + canvas.drawRect(new Rect(0, 0, (int) width, (int) height), buttonPaint); + + staticLayout = new StaticLayout(entity.text, + textPaint, + (int) textLayoutWidth, + Layout.Alignment.ALIGN_CENTER, + 1.0f, + 0, + false); + canvas.save(); + canvas.rotate(entity.rotation, width / 2, height / 2); + canvas.translate(((width / 2) - staticLayout.getWidth() / 2), height / 2 - staticLayout.getHeight() / 2); + staticLayout.draw(canvas); + canvas.restore(); } @Override public void onLocationChanged(Location location) { - latitude = location.getLatitude(); - longitude = location.getLongitude(); - - Log.i("Gps2RosView","Longitude: "+longitude+" Latitude: " + latitude); - - Gps2RosData data = new Gps2RosData(latitude,longitude); - this.publishViewData(data); + if(buttonPressed) { + latitude = location.getLatitude(); + longitude = location.getLongitude(); + Log.i("Gps2RosView","Longitude: "+longitude+" Latitude: " + latitude); + Gps2RosData data = new Gps2RosData(latitude,longitude); + this.publishViewData(data); + } } @Override public void onProviderDisabled(String provider) { - - Log.d("Gps2RosView","disable"); } @Override public void onProviderEnabled(String provider) { - - Log.d("Gps2RosView","enable"); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { - - Log.d("Gps2RosView","status"); } } diff --git a/app/src/main/res/layout/widget_detail_gps2ros.xml b/app/src/main/res/layout/widget_detail_gps2ros.xml index e98f3352..20e7f17b 100644 --- a/app/src/main/res/layout/widget_detail_gps2ros.xml +++ b/app/src/main/res/layout/widget_detail_gps2ros.xml @@ -1,15 +1,76 @@ - + android:layout_height="wrap_content" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> - \ No newline at end of file + + + + + + + + + + + + + diff --git a/app/src/main/res/values/widgets.xml b/app/src/main/res/values/widgets.xml index 73534cdb..a03a8e74 100644 --- a/app/src/main/res/values/widgets.xml +++ b/app/src/main/res/values/widgets.xml @@ -102,9 +102,17 @@ - TODO + The ROS GPS Node 2 is designed to publish the phone GPS coordinates to the ROS as a sensor_msgs/NavSatFix message. + The publisher can be started or stopped by pressing its button in the Viz tab. + + + 90° + 180° + 270° + + The Joystick node is designed for teleoperational control of robotic systems. From 5c9f7171396d9670d67aa03033665a14322813eb Mon Sep 17 00:00:00 2001 From: Gennaro Raiola Date: Mon, 21 Nov 2022 15:58:41 +0100 Subject: [PATCH 07/14] Fix widget details for gps2ros --- app/src/main/res/layout/widget_detail_gps2ros.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/widget_detail_gps2ros.xml b/app/src/main/res/layout/widget_detail_gps2ros.xml index 20e7f17b..332e00b4 100644 --- a/app/src/main/res/layout/widget_detail_gps2ros.xml +++ b/app/src/main/res/layout/widget_detail_gps2ros.xml @@ -32,7 +32,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:hint="Button text" + android:hint="Gps2Ros text" app:boxBackgroundMode="outline" app:endIconCheckable="false" app:endIconMode="none" @@ -47,7 +47,7 @@ android:imeOptions="actionDone" android:inputType="text" android:singleLine="true" - android:text="A button" /> + android:text="Gps2Ros" /> @@ -67,7 +67,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="24dp" - android:entries="@array/button_rotation" + android:entries="@array/Gps2Ros_rotation" android:foregroundTintMode="add" app:layout_constraintBottom_toBottomOf="@+id/textView11" app:layout_constraintEnd_toEndOf="parent" From d0788e626180791540a0f136bacba9fcbec69b11 Mon Sep 17 00:00:00 2001 From: Gennaro Raiola Date: Mon, 21 Nov 2022 17:29:50 +0100 Subject: [PATCH 08/14] Check both Network and Gps locations --- .../widgets/gps2ros/Gps2RosData.java | 13 +- .../widgets/gps2ros/Gps2RosEntity.java | 2 + .../widgets/gps2ros/Gps2RosView.java | 137 ++++++++++++------ 3 files changed, 106 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java index 035a7387..796797e2 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java @@ -16,14 +16,19 @@ * @version 0.0.1 * @created on 19.11.22 */ + public class Gps2RosData extends BaseData { - double latitude; - double longitude; + public double latitude; + public double longitude; + public double altitude; + public String type; - public Gps2RosData(double latitude, double longitude) { + public Gps2RosData(double latitude, double longitude, double altitude, String type) { this.latitude = latitude; this.longitude = longitude; + this.altitude = altitude; + this.type = type; } @Override @@ -31,8 +36,10 @@ public Message toRosMessage(Publisher publisher, BaseEntity widget) { sensor_msgs.NavSatFix message = (NavSatFix) publisher.newMessage(); + message.getHeader().setFrameId(type); message.setLatitude(latitude); message.setLongitude(longitude); + message.setAltitude(altitude); return message; } diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java index 1dfde737..dc94ec7b 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java @@ -18,6 +18,7 @@ public class Gps2RosEntity extends PublisherWidgetEntity { public String text; public int rotation; + public boolean buttonPressed; public Gps2RosEntity() { this.width = 4; @@ -27,5 +28,6 @@ public Gps2RosEntity() { //this.publishRate = 20f; this.text = "Publish GPS 2 ROS"; this.rotation = 0; + this.buttonPressed = false; } } diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java index 08884633..52879ef7 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java @@ -15,6 +15,7 @@ import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import com.schneewittchen.rosandroid.R; import com.schneewittchen.rosandroid.ui.views.widgets.PublisherWidgetView; @@ -25,6 +26,8 @@ import android.location.Location; import android.util.Log; +import java.util.ArrayList; + /** * TODO: Description @@ -33,19 +36,47 @@ * @version 0.0.1 * @created on 19.11.22 */ -public class Gps2RosView extends PublisherWidgetView implements LocationListener { +public class Gps2RosView extends PublisherWidgetView { public static final String TAG = Gps2RosView.class.getSimpleName(); + Context context; + Paint buttonPaint; TextPaint textPaint; StaticLayout staticLayout; - boolean buttonPressed; protected LocationManager locationManager; - double latitude; - double longitude; - Context context; + double gpsLatitude; + double gpsLongitude; + double gpsAltitude; + double networkLatitude; + double networkLongitude; + double networkAltitude; + long gpsTime = 0; + long networkTime = 0; + + LocationListener locationListenerGps = new LocationListener() { + public void onLocationChanged(Location location) { + gpsTime = location.getTime(); + gpsLatitude = location.getLatitude(); + gpsLongitude = location.getLongitude(); + gpsAltitude = location.getAltitude(); + Log.d("Gps2RosView","GPS - Longitude: "+ gpsLongitude +" Latitude: " + gpsLatitude +" Altitude: " + gpsAltitude); + publishCoordinates(); + } + }; + + LocationListener locationListenerNetwork = new LocationListener() { + public void onLocationChanged(Location location) { + networkTime = location.getTime(); + networkLatitude = location.getLatitude(); + networkLongitude = location.getLongitude(); + networkAltitude = location.getAltitude(); + Log.d("Gps2RosView","NETWORK - Longitude: "+networkLongitude+" Latitude: " + networkLatitude +" Altitude: " + networkAltitude); + publishCoordinates(); + } + }; public Gps2RosView(Context context) { super(context); @@ -61,9 +92,6 @@ public Gps2RosView(Context context, @Nullable AttributeSet attrs) { private void init() { - // By default it is ... - buttonPressed = false; - buttonPaint = new Paint(); buttonPaint.setColor(getResources().getColor(R.color.colorPrimary)); buttonPaint.setStyle(Paint.Style.FILL_AND_STROKE); @@ -75,29 +103,40 @@ private void init() { locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - // TODO: Consider calling - // ActivityCompat#requestPermissions - // here to request the missing permissions, and then overriding - // public void onRequestPermissionsResult(int requestCode, String[] permissions, - // int[] grantResults) - // to handle the case where the user grants the permission. See the documentation - // for ActivityCompat#requestPermissions for more details. - Log.e("Gps2RosView","check permissions failed!"); - return; + requestPermissionsIfNecessary(new String[]{ + Manifest.permission.ACCESS_FINE_LOCATION + }); } - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); - //locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); - final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - if (!gpsEnabled) { - Log.e("Gps2RosView","gps is not enabled!"); + final boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + + if(gpsEnabled) + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps); + if (networkEnabled) + locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork); + + if(!gpsEnabled && !networkEnabled) + { + Log.e("Gps2RosView","gps and network locations are not enabled!"); return; } } + private void requestPermissionsIfNecessary(String[] permissions) { + ArrayList permissionsToRequest = new ArrayList<>(); + for (String permission : permissions) { + if (ContextCompat.checkSelfPermission(this.getContext(), permission) + != PackageManager.PERMISSION_GRANTED) { + // Permission is not granted + permissionsToRequest.add(permission); + } + } + } + private void changeState(boolean pressed) { - this.buttonPressed = pressed; + Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; + entity.buttonPressed = pressed; invalidate(); } @@ -107,9 +146,11 @@ public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } + Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; + switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - if(buttonPressed) { + if(entity.buttonPressed) { buttonPaint.setColor(getResources().getColor(R.color.colorPrimary)); changeState(false); } @@ -138,6 +179,11 @@ public void onDraw(Canvas canvas) { textLayoutWidth = height; } + if(!entity.buttonPressed) + buttonPaint.setColor(getResources().getColor(R.color.colorPrimary)); + else + buttonPaint.setColor(getResources().getColor(R.color.color_attention)); + canvas.drawRect(new Rect(0, 0, (int) width, (int) height), buttonPaint); staticLayout = new StaticLayout(entity.text, @@ -154,27 +200,32 @@ public void onDraw(Canvas canvas) { canvas.restore(); } - @Override - public void onLocationChanged(Location location) { - if(buttonPressed) { - latitude = location.getLatitude(); - longitude = location.getLongitude(); - Log.i("Gps2RosView","Longitude: "+longitude+" Latitude: " + latitude); - Gps2RosData data = new Gps2RosData(latitude,longitude); - this.publishViewData(data); - } - } - - @Override - public void onProviderDisabled(String provider) { - } + public void publishCoordinates() { - @Override - public void onProviderEnabled(String provider) { - } + Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; - @Override - public void onStatusChanged(String provider, int status, Bundle extras) { + if(entity.buttonPressed) { + double latitude; + double longitude; + double altitude; + String type; + Log.d("Gps2RosView", "time network " + networkTime + " time GPS "+ gpsTime); + if(gpsTime > (networkTime + 1000)) { // 1sec + latitude = gpsLatitude; + longitude = gpsLongitude; + altitude = gpsAltitude; + type = "GPS"; + } + else + { + latitude = networkLatitude; + longitude = networkLongitude; + altitude = networkAltitude; + type = "NETWORK"; + } + Log.d("Gps2RosView", type + " Longitude: " + longitude + " Latitude: " + latitude + " Altitude " + altitude); + this.publishViewData(new Gps2RosData(latitude, longitude, altitude, type)); + } } } From 5fa446cefa4f8232a522951dd7d2bc7c6607ccd8 Mon Sep 17 00:00:00 2001 From: Gennaro Raiola Date: Mon, 21 Nov 2022 17:56:22 +0100 Subject: [PATCH 09/14] Rename gps2ros -> location --- .../LocationData.java} | 6 +++--- .../LocationDetailVH.java} | 16 +++++++------- .../LocationEntity.java} | 11 +++++----- .../LocationView.java} | 21 +++++++++---------- ...gps2ros.xml => widget_detail_location.xml} | 6 +++--- app/src/main/res/values/widgets.xml | 10 ++++----- 6 files changed, 34 insertions(+), 36 deletions(-) rename app/src/main/java/com/schneewittchen/rosandroid/widgets/{gps2ros/Gps2RosData.java => location/LocationData.java} (83%) rename app/src/main/java/com/schneewittchen/rosandroid/widgets/{gps2ros/Gps2RosDetailVH.java => location/LocationDetailVH.java} (75%) rename app/src/main/java/com/schneewittchen/rosandroid/widgets/{gps2ros/Gps2RosEntity.java => location/LocationEntity.java} (67%) rename app/src/main/java/com/schneewittchen/rosandroid/widgets/{gps2ros/Gps2RosView.java => location/LocationView.java} (91%) rename app/src/main/res/layout/{widget_detail_gps2ros.xml => widget_detail_location.xml} (95%) diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationData.java similarity index 83% rename from app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java rename to app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationData.java index 796797e2..6faf4e85 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosData.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationData.java @@ -1,4 +1,4 @@ -package com.schneewittchen.rosandroid.widgets.gps2ros; +package com.schneewittchen.rosandroid.widgets.location; import com.schneewittchen.rosandroid.model.repositories.rosRepo.node.BaseData; import com.schneewittchen.rosandroid.model.entities.widgets.BaseEntity; @@ -17,14 +17,14 @@ * @created on 19.11.22 */ -public class Gps2RosData extends BaseData { +public class LocationData extends BaseData { public double latitude; public double longitude; public double altitude; public String type; - public Gps2RosData(double latitude, double longitude, double altitude, String type) { + public LocationData(double latitude, double longitude, double altitude, String type) { this.latitude = latitude; this.longitude = longitude; this.altitude = altitude; diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationDetailVH.java similarity index 75% rename from app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java rename to app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationDetailVH.java index d4fdbb1f..5d1a020a 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosDetailVH.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationDetailVH.java @@ -1,4 +1,4 @@ -package com.schneewittchen.rosandroid.widgets.gps2ros; +package com.schneewittchen.rosandroid.widgets.location; import android.view.View; import android.widget.ArrayAdapter; @@ -22,7 +22,7 @@ * @version 0.0.1 * @created on 19.11.22 */ -public class Gps2RosDetailVH extends PublisherWidgetViewHolder { +public class LocationDetailVH extends PublisherWidgetViewHolder { private EditText textText; private Spinner rotationSpinner; @@ -42,20 +42,20 @@ public void initView(View view) { @Override public void bindEntity(BaseEntity entity) { - Gps2RosEntity gps2rosEntity = (Gps2RosEntity) entity; + LocationEntity locationEntity = (LocationEntity) entity; - textText.setText(gps2rosEntity.text); - String degrees = Utils.numberToDegrees(gps2rosEntity.rotation); + textText.setText(locationEntity.text); + String degrees = Utils.numberToDegrees(locationEntity.rotation); rotationSpinner.setSelection(rotationAdapter.getPosition(degrees)); } @Override public void updateEntity(BaseEntity entity) { - Gps2RosEntity gps2rosEntity = (Gps2RosEntity) entity; + LocationEntity locationEntity = (LocationEntity) entity; - gps2rosEntity.text = textText.getText().toString(); + locationEntity.text = textText.getText().toString(); String degrees = rotationSpinner.getSelectedItem().toString(); - gps2rosEntity.rotation = Utils.degreesToNumber(degrees); + locationEntity.rotation = Utils.degreesToNumber(degrees); } @Override diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationEntity.java similarity index 67% rename from app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java rename to app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationEntity.java index dc94ec7b..b1adeae3 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosEntity.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationEntity.java @@ -1,10 +1,9 @@ -package com.schneewittchen.rosandroid.widgets.gps2ros; +package com.schneewittchen.rosandroid.widgets.location; import com.schneewittchen.rosandroid.model.entities.widgets.PublisherWidgetEntity; import com.schneewittchen.rosandroid.model.repositories.rosRepo.message.Topic; import sensor_msgs.NavSatFix; -import std_msgs.Bool; /** * TODO: Description @@ -14,19 +13,19 @@ * @created on 19.11.22 */ -public class Gps2RosEntity extends PublisherWidgetEntity { +public class LocationEntity extends PublisherWidgetEntity { public String text; public int rotation; public boolean buttonPressed; - public Gps2RosEntity() { + public LocationEntity() { this.width = 4; this.height = 4; - this.topic = new Topic("gps_android", NavSatFix._TYPE); + this.topic = new Topic("location", NavSatFix._TYPE); this.immediatePublish = true; //this.publishRate = 20f; - this.text = "Publish GPS 2 ROS"; + this.text = "Publish phone's location to ROS"; this.rotation = 0; this.buttonPressed = false; } diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java similarity index 91% rename from app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java rename to app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java index 52879ef7..43a1f9eb 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/gps2ros/Gps2RosView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java @@ -1,4 +1,4 @@ -package com.schneewittchen.rosandroid.widgets.gps2ros; +package com.schneewittchen.rosandroid.widgets.location; import android.content.Context; import android.graphics.Canvas; @@ -22,7 +22,6 @@ import android.Manifest; import android.content.pm.PackageManager; -import android.os.Bundle; import android.location.Location; import android.util.Log; @@ -36,9 +35,9 @@ * @version 0.0.1 * @created on 19.11.22 */ -public class Gps2RosView extends PublisherWidgetView { +public class LocationView extends PublisherWidgetView { - public static final String TAG = Gps2RosView.class.getSimpleName(); + public static final String TAG = LocationView.class.getSimpleName(); Context context; @@ -78,13 +77,13 @@ public void onLocationChanged(Location location) { } }; - public Gps2RosView(Context context) { + public LocationView(Context context) { super(context); this.context = context; init(); } - public Gps2RosView(Context context, @Nullable AttributeSet attrs) { + public LocationView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.context = context; init(); @@ -135,7 +134,7 @@ private void requestPermissionsIfNecessary(String[] permissions) { } private void changeState(boolean pressed) { - Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; + LocationEntity entity = (LocationEntity) widgetEntity; entity.buttonPressed = pressed; invalidate(); } @@ -146,7 +145,7 @@ public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } - Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; + LocationEntity entity = (LocationEntity) widgetEntity; switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: @@ -173,7 +172,7 @@ public void onDraw(Canvas canvas) { float height = getHeight(); float textLayoutWidth = width; - Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; + LocationEntity entity = (LocationEntity) widgetEntity; if (entity.rotation == 90 || entity.rotation == 270) { textLayoutWidth = height; @@ -202,7 +201,7 @@ public void onDraw(Canvas canvas) { public void publishCoordinates() { - Gps2RosEntity entity = (Gps2RosEntity) widgetEntity; + LocationEntity entity = (LocationEntity) widgetEntity; if(entity.buttonPressed) { double latitude; @@ -224,7 +223,7 @@ public void publishCoordinates() { type = "NETWORK"; } Log.d("Gps2RosView", type + " Longitude: " + longitude + " Latitude: " + latitude + " Altitude " + altitude); - this.publishViewData(new Gps2RosData(latitude, longitude, altitude, type)); + this.publishViewData(new LocationData(latitude, longitude, altitude, type)); } } diff --git a/app/src/main/res/layout/widget_detail_gps2ros.xml b/app/src/main/res/layout/widget_detail_location.xml similarity index 95% rename from app/src/main/res/layout/widget_detail_gps2ros.xml rename to app/src/main/res/layout/widget_detail_location.xml index 332e00b4..bddc5e46 100644 --- a/app/src/main/res/layout/widget_detail_gps2ros.xml +++ b/app/src/main/res/layout/widget_detail_location.xml @@ -32,7 +32,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:hint="Gps2Ros text" + android:hint="Location text" app:boxBackgroundMode="outline" app:endIconCheckable="false" app:endIconMode="none" @@ -47,7 +47,7 @@ android:imeOptions="actionDone" android:inputType="text" android:singleLine="true" - android:text="Gps2Ros" /> + android:text="Location" /> @@ -67,7 +67,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="24dp" - android:entries="@array/Gps2Ros_rotation" + android:entries="@array/Location_rotation" android:foregroundTintMode="add" app:layout_constraintBottom_toBottomOf="@+id/textView11" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/values/widgets.xml b/app/src/main/res/values/widgets.xml index a03a8e74..67b0fd68 100644 --- a/app/src/main/res/values/widgets.xml +++ b/app/src/main/res/values/widgets.xml @@ -12,7 +12,7 @@ Logger RqtPlot Viz2D - Gps2Ros + Location @@ -101,12 +101,12 @@ - - The ROS GPS Node 2 is designed to publish the phone GPS coordinates to the ROS as a sensor_msgs/NavSatFix message. + + The Location node is designed to publish the phone GPS and or network coordinates to ROS as a sensor_msgs/NavSatFix message. The publisher can be started or stopped by pressing its button in the Viz tab. - + 90° 180° @@ -158,4 +158,4 @@ 2D View of multiple layers. - \ No newline at end of file + From 226a011100a0f23d0df138598a9d4b121e88bbb2 Mon Sep 17 00:00:00 2001 From: graiola Date: Mon, 21 Nov 2022 23:33:01 +0100 Subject: [PATCH 10/14] Give priority to GPS --- .../rosandroid/widgets/location/LocationView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java index 43a1f9eb..9793b173 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java @@ -209,7 +209,7 @@ public void publishCoordinates() { double altitude; String type; Log.d("Gps2RosView", "time network " + networkTime + " time GPS "+ gpsTime); - if(gpsTime > (networkTime + 1000)) { // 1sec + if( 0 < gpsTime - networkTime) { latitude = gpsLatitude; longitude = gpsLongitude; altitude = gpsAltitude; From 1c1f3441524ea20d5076d1bc9420ec92eab0513d Mon Sep 17 00:00:00 2001 From: graiola Date: Mon, 21 Nov 2022 23:54:57 +0100 Subject: [PATCH 11/14] Change button color in onDraw --- .idea/deploymentTargetDropDown.xml | 17 +++++++++++++++++ .../widgets/location/LocationView.java | 7 +------ 2 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 .idea/deploymentTargetDropDown.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 00000000..44943151 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java index 9793b173..b2f35152 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java @@ -149,15 +149,10 @@ public boolean onTouchEvent(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - if(entity.buttonPressed) { - buttonPaint.setColor(getResources().getColor(R.color.colorPrimary)); + if(entity.buttonPressed) changeState(false); - } else - { - buttonPaint.setColor(getResources().getColor(R.color.color_attention)); changeState(true); - } break; default: return false; From 267e4f4e22077a29e289d235c9e284393dad1304 Mon Sep 17 00:00:00 2001 From: graiola Date: Thu, 8 Dec 2022 23:00:07 +0100 Subject: [PATCH 12/14] Implementation with fusedLocationManager --- .idea/misc.xml | 3 +- app/build.gradle | 1 + .../widgets/location/LocationData.java | 8 +- .../widgets/location/LocationView.java | 103 ++++++------------ 4 files changed, 42 insertions(+), 73 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 9a237764..6ddcda74 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,6 @@ + - + diff --git a/app/build.gradle b/app/build.gradle index ae66a799..09a88463 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,6 +60,7 @@ dependencies { // Room implementation "androidx.room:room-runtime:2.3.0" + implementation 'com.google.android.gms:play-services:11.8.0' annotationProcessor "androidx.room:room-compiler:2.3.0" // Parsing diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationData.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationData.java index 6faf4e85..e6a04f30 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationData.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationData.java @@ -22,13 +22,13 @@ public class LocationData extends BaseData { public double latitude; public double longitude; public double altitude; - public String type; + public String provider; - public LocationData(double latitude, double longitude, double altitude, String type) { + public LocationData(double latitude, double longitude, double altitude, String provider) { this.latitude = latitude; this.longitude = longitude; this.altitude = altitude; - this.type = type; + this.provider = provider; } @Override @@ -36,7 +36,7 @@ public Message toRosMessage(Publisher publisher, BaseEntity widget) { sensor_msgs.NavSatFix message = (NavSatFix) publisher.newMessage(); - message.getHeader().setFrameId(type); + message.getHeader().setFrameId(provider); message.setLatitude(latitude); message.setLongitude(longitude); message.setAltitude(altitude); diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java index b2f35152..6e9b8be5 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java @@ -1,12 +1,13 @@ package com.schneewittchen.rosandroid.widgets.location; +import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; -import android.location.LocationListener; -import android.location.LocationManager; +import android.os.Looper; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; @@ -17,12 +18,14 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import com.google.android.gms.location.LocationCallback; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationResult; import com.schneewittchen.rosandroid.R; import com.schneewittchen.rosandroid.ui.views.widgets.PublisherWidgetView; import android.Manifest; import android.content.pm.PackageManager; -import android.location.Location; import android.util.Log; import java.util.ArrayList; @@ -45,37 +48,12 @@ public class LocationView extends PublisherWidgetView { TextPaint textPaint; StaticLayout staticLayout; - protected LocationManager locationManager; - double gpsLatitude; - double gpsLongitude; - double gpsAltitude; - double networkLatitude; - double networkLongitude; - double networkAltitude; - long gpsTime = 0; - long networkTime = 0; - - LocationListener locationListenerGps = new LocationListener() { - public void onLocationChanged(Location location) { - gpsTime = location.getTime(); - gpsLatitude = location.getLatitude(); - gpsLongitude = location.getLongitude(); - gpsAltitude = location.getAltitude(); - Log.d("Gps2RosView","GPS - Longitude: "+ gpsLongitude +" Latitude: " + gpsLatitude +" Altitude: " + gpsAltitude); - publishCoordinates(); - } - }; - - LocationListener locationListenerNetwork = new LocationListener() { - public void onLocationChanged(Location location) { - networkTime = location.getTime(); - networkLatitude = location.getLatitude(); - networkLongitude = location.getLongitude(); - networkAltitude = location.getAltitude(); - Log.d("Gps2RosView","NETWORK - Longitude: "+networkLongitude+" Latitude: " + networkLatitude +" Altitude: " + networkAltitude); - publishCoordinates(); - } - }; + LocationRequest locationRequest; + double altitude; + double latitude; + double longitude; + String provider; + public LocationView(Context context) { super(context); @@ -91,6 +69,8 @@ public LocationView(Context context, @Nullable AttributeSet attrs) { private void init() { + LocationEntity entity = (LocationEntity) widgetEntity; + buttonPaint = new Paint(); buttonPaint.setColor(getResources().getColor(R.color.colorPrimary)); buttonPaint.setStyle(Paint.Style.FILL_AND_STROKE); @@ -100,26 +80,31 @@ private void init() { textPaint.setStyle(Paint.Style.FILL_AND_STROKE); textPaint.setTextSize(26 * getResources().getDisplayMetrics().density); - locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + locationRequest = new LocationRequest(); + locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); + //long interval = (long)(1.0/entity.publishRate)*1000; + //Log.i(TAG,"INTERVAL - --------------------" + interval); + long interval = 500; + locationRequest.setInterval(interval); + locationRequest.setFastestInterval(interval); + locationRequest.setSmallestDisplacement(0); if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestPermissionsIfNecessary(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION }); } + getFusedLocationProviderClient(context).requestLocationUpdates(locationRequest, new LocationCallback() { + @Override + public void onLocationResult(LocationResult locationResult) { + provider = locationResult.getLastLocation().getProvider(); + altitude = locationResult.getLastLocation().getAltitude(); + latitude = locationResult.getLastLocation().getLatitude(); + longitude = locationResult.getLastLocation().getLongitude(); + publishCoordinates(); + } + }, + Looper.myLooper()); - final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - final boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); - - if(gpsEnabled) - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps); - if (networkEnabled) - locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork); - - if(!gpsEnabled && !networkEnabled) - { - Log.e("Gps2RosView","gps and network locations are not enabled!"); - return; - } } private void requestPermissionsIfNecessary(String[] permissions) { @@ -199,26 +184,8 @@ public void publishCoordinates() { LocationEntity entity = (LocationEntity) widgetEntity; if(entity.buttonPressed) { - double latitude; - double longitude; - double altitude; - String type; - Log.d("Gps2RosView", "time network " + networkTime + " time GPS "+ gpsTime); - if( 0 < gpsTime - networkTime) { - latitude = gpsLatitude; - longitude = gpsLongitude; - altitude = gpsAltitude; - type = "GPS"; - } - else - { - latitude = networkLatitude; - longitude = networkLongitude; - altitude = networkAltitude; - type = "NETWORK"; - } - Log.d("Gps2RosView", type + " Longitude: " + longitude + " Latitude: " + latitude + " Altitude " + altitude); - this.publishViewData(new LocationData(latitude, longitude, altitude, type)); + Log.d(TAG, " Provider: " + provider + " Longitude: " + longitude + " Latitude: " + latitude + " Altitude " + altitude); + this.publishViewData(new LocationData(latitude, longitude, altitude, provider)); } } From 16525761b98a8de2fbcaf7b51cd7af98e5bf4812 Mon Sep 17 00:00:00 2001 From: graiola Date: Fri, 9 Dec 2022 15:41:08 +0100 Subject: [PATCH 13/14] Keep screen on --- .../rosandroid/widgets/location/LocationView.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java index 6e9b8be5..6211783f 100644 --- a/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java +++ b/app/src/main/java/com/schneewittchen/rosandroid/widgets/location/LocationView.java @@ -2,6 +2,7 @@ import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient; +import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; @@ -27,6 +28,7 @@ import android.Manifest; import android.content.pm.PackageManager; import android.util.Log; +import android.view.WindowManager; import java.util.ArrayList; @@ -69,6 +71,8 @@ public LocationView(Context context, @Nullable AttributeSet attrs) { private void init() { + ((Activity) getContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + LocationEntity entity = (LocationEntity) widgetEntity; buttonPaint = new Paint(); @@ -88,9 +92,11 @@ private void init() { locationRequest.setInterval(interval); locationRequest.setFastestInterval(interval); locationRequest.setSmallestDisplacement(0); - if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED ) { requestPermissionsIfNecessary(new String[]{ - Manifest.permission.ACCESS_FINE_LOCATION + Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION }); } getFusedLocationProviderClient(context).requestLocationUpdates(locationRequest, new LocationCallback() { From 03c7d034792d68c6f1158e0717bb4a426d5bbf1a Mon Sep 17 00:00:00 2001 From: graiola Date: Tue, 24 Jan 2023 09:00:35 +0100 Subject: [PATCH 14/14] Access coarse --- app/src/main/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 65351d53..40325a72 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,10 +5,11 @@ - + +