How to listen to android googlemaps geofence transitions - android-geofence

How can i make something happen when my location on a map enters and exits one of my application google map's fence. I cant seem to understand the tutorial of google regarding geofencing. And i cant find any other tutorial of this thing.
this are my code..
#Override
protected void onCreate(Bundle savedInstanceState) {
...
buildGeofence(14.728801, 120.961209, "Id_test", 500);
}
private void buildGeofence(double latitude ,double longitude, String requestId, int radius){
int GEOFENCE_TRANSITION_ENTER = 1;
LatLng geofencePoint = new LatLng(latitude, longitude);
//int radius = 500;
Geofence.Builder geofence = new Geofence.Builder();
geofence.setCircularRegion(geofencePoint.latitude,geofencePoint.longitude, radius);
geofence.setRequestId(requestId);
geofence.setExpirationDuration(Geofence.NEVER_EXPIRE);
geofence.setTransitionTypes(GEOFENCE_TRANSITION_ENTER);
geofence.setNotificationResponsiveness(0);
geofence.build();
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(geofencePoint);
circleOptions.radius(radius);
circleOptions.strokeColor(Color.BLACK);
circleOptions.strokeWidth(2);
circleOptions.fillColor(0x30ff0000);
mMap.addCircle(circleOptions);
}

Dens,
To make something happen when you transition the Geofence you need to
Create an intent for Geofence transitions.
Create a GeofencingRequest.
Add the intent, GeofenceingRequest, and GoogleApiClient to the LocationServices.GeofencingApi API.
Handle the intent.
The code you have written so far will create a geofence and a circle on the map, but it will not yet do anything when the fence is transitioned.
In the tutorial you linked, you successfully created a geofence, but now you need to follow some of the other steps. Make sure you follow the steps in "Specify geofences and initial triggers", "Define an Intent for geofence transitions", and "Add geofences". This should complete steps 1, 2, and 3 that I listed above. One you have those steps working, try the section "Handle Geofence Transitions", which will complete step 4 that I listed above.
I hope this helps you!
P.S.: Since I see you are adding circles to the map, you may quickly discover you need a way to keep track of these circles in order to correctly add and remove them for each geofence. There is a short blog post here that discusses how to do this.

Related

Is it possible to recolor a lottie animation programmatically?

If I have a lottie animation in the form of a json file, is there a way to recolor it in code or even within the json itself?
(To be clear, I hope there's a way to do it without involving After Effects. For instance if I decide to change my app's primary color, the whole app will change except the animation unless there's a way to do that.)
I figured it out. For this example, let's say I want to recolor a specific layer to Color.RED.
You'll need your LottieAnimationView, a KeyPath, and a LottieValueCallback
private LottieAnimationView lottieAnimationVIew;
private KeyPath mKeyPath;
private LottieValueCallback<Integer> mCallback;
Then in your onCreate (or onViewCreated for a fragment) you'll get the animation with findViewById, as well as "addLottieOnCompositionLoadedListener" to the lottieAnimationView, in which you will setup the "mKeyPath" and "mCallback":
lottieAnimationVIew = findViewById(R.id.animationView);
lottieAnimationView.addLottieOnCompositionLoadedListener(new LottieOnCompositionLoadedListener() {
#Override
public void onCompositionLoaded(LottieComposition composition) {
mKeyPath = getKeyPath(); // This is your own method for getting the KeyPath you desire. More on that below.
mCallback = new LottieValueCallback<>();
mCallback.setValue(Color.RED);
checkBox.addValueCallback(mKeyPath, LottieProperty.COLOR, mCallback);
}
});
The argument "LottieProperty.COLOR" specifies which property I am changing.
There's probably a better way to do this, but here's my "getKeyPath" method for finding the specific thing I want to change. It will log every KeyPath so you can see which one you want. Then it returns it once you've supplied the correct index. I saw that the one I want is the 5th in the list, hence the hard-coded index of 4.
private KeyPath getKeyPath() {
List<KeyPath> keyPaths = lottieAnimationView.resolveKeyPath(new KeyPath("Fill", "Ellipse 1", "Fill 1"));
for (int i = 0; i < keyPaths.size(); i++) {
Log.i("KeyPath", keyPaths.get(i).toString());
}
if (keyPaths.size() == 5) {
return keyPaths.get(4);
}
else {
return null;
}
}
Note that the "Fill", "Ellipse 1", "Fill 1" are strings I supplied to narrow the list down to just the ones that have those keys, because I know that the layer I want will be among those. There's likely a better way to do this as well.
There is another thread on this topic with the same approach but a bit simplified:
How to add a color overlay to an animation in Lottie?
Here's directly an example (Kotlin):
yourLottieAnimation.addValueCallback(
KeyPath("whatever_keypath", "**"),
LottieProperty.COLOR_FILTER
) {
PorterDuffColorFilter(
Color.CYAN,
PorterDuff.Mode.SRC_ATOP
)
}
You can find the names of the keypaths also in the Lottie editor.

HoloLens spatial mapping.SpatialSurfaceMesh update problem. C++/winrt

im working on the spatial mapping processing for my HoloLens project.
Somehow calling "SpatialSurfaceMesh::TryComputeLatestMeshAsync" keeps returning the same mesh data overtime.
Is there another process involved updating the observer?
void SpatialMapping::AddOrUpdateSurface(winrt::Windows::Perception::Spatial::SpatialCoordinateSystem const& coordinateSystem)
{
using namespace winrt::Windows::Perception::Spatial::Surfaces;
SpatialBoundingBox axisAlignedBoundingBox =
{
{ 0.f, 0.f, 0.f },
{ 50.f, 50.f, 50.f },
};
SpatialBoundingVolume bounds = SpatialBoundingVolume::FromBox(coordinateSystem, axisAlignedBoundingBox);
m_surfaceObserver.SetBoundingVolume(bounds);
m_surfaceObserver.ObservedSurfacesChanged(
winrt::Windows::Foundation::TypedEventHandler
<SpatialSurfaceObserver, winrt::Windows::Foundation::IInspectable>
({ this, &SpatialMapping::Observer_ObservedSurfacesChanged })
);
}
void SpatialMapping::Observer_ObservedSurfacesChanged(winrt::Windows::Perception::Spatial::Surfaces::SpatialSurfaceObserver const& sender
, winrt::Windows::Foundation::IInspectable const& object)
{
{
using namespace winrt::Windows::Perception::Spatial::Surfaces;
const auto mapContainingSurfaceCollection = sender.GetObservedSurfaces();
// Process surface adds and updates?.
for (const auto& pair : mapContainingSurfaceCollection)
{
auto id = pair.Key();
auto info = pair.Value();
InsertAsync(id, info);
}
}
}
Concurrency::task<void> SpatialMapping::InsertAsync(winrt::guid /*const&*/ id, winrt::Windows::Perception::Spatial::Surfaces::SpatialSurfaceInfo /*const&*/ newSurfaceInfo)
{
using namespace winrt::Windows::Perception::Spatial::Surfaces;
return concurrency::create_task([this, id, newSurfaceInfo]
{
const auto surfaceMesh = newSurfaceInfo.TryComputeLatestMeshAsync(m_maxTrianglesPerCubicMeter, m_surfaceMeshOptions).get();
std::lock_guard<std::mutex> guard(m_meshCollectionLock);
m_updatedSurfaces.emplace(id, surfaceMesh);
});
}
Generation works, Update does not
Manuel attempt same problem:
winrt::Windows::Foundation::IAsyncAction SpatialMapping::CollectSurfacesManuel()
{
const auto mapContainingSurfaceCollection = m_surfaceObserver.GetObservedSurfaces();
for (const auto& pair : mapContainingSurfaceCollection)
{
auto id = pair.Key();
auto info = pair.Value();
auto mesh{ co_await info.TryComputeLatestMeshAsync(m_maxTrianglesPerCubicMeter, m_surfaceMeshOptions) };
{
std::lock_guard<std::mutex> guard(m_meshCollectionLock);
m_updatedSurfaces.emplace(id, mesh);
}
}
}
MVCE:
Create a New Project with the template
"Holographic DirectX 11 App (UWP) C++/WinRT)"
Add the files:
https://github.com/lpnxDX/HL_MVCE_SpatialSurfaceMeshUpdateProblem.git
Replace m_main in AppView.h
We did some research and have some thoughts about your question right now, let me explain the findings
Has your Observer_ObservedSurfacesChanged method triggered exactly? Adding output statements or breakpoints can help you check it. Since SurfaceObserver should be always available, usually we need to check the availability of surfaceObserver in each frame and recreate a new one when necessary, sample code snippt please see here.
Have you set m_surfaceMeshOptions? It is not visible in the code you posted. If it is missing, you can configure it with the following statement:
surfaceMeshOptions-> IncludeVertexNormals = true;
Microsoft provided the Holographic spatial mapping sample, shows how to acquire spatial mapping data from Windows Perception in real-time. it is similar to your needs, to narrow down issue if it's an issue with your code, please try to check and run this example on your device
If after the above steps, you still can't solve the problem, could you provide an
MVCE, so that we can locate the issue or find a solution? Be careful to remove any privacy-related or other business function codes.
Your code has the following problems:
TryComputeLatestMeshAsync should be called from Observer_ObservedSurfacesChanged not from concurrency::create_task
TryComputeLatestMeshAsync return mesh with matrix, vertices and indices. Indices should be stored to a safe location at the first run, they don't change later. Vertices and matrix should copied as they returns. You shouldn't save the mesh itself, because its data updates from various threads.
ObservedSurfacesChanged shouldn't be called every frame. This is long running function.
Maybe it has something more. I would recommend to start from the sample mentioned earlier.

Make Two Views Share Click Feedback in Constraint Layout

I have this situation where I have a constraint layout. Within it lies two views. An ImageView and a TextView. When either of these Views is clicked, I want both to produce a feedback (text color change for textview and drawable tint in imageview) but I can't seem to think of a way to do these unless I put them inside another viewgroup.
Can someone show me how this could be done in constraint Layout? thank you.
Take a look at performClick().
performClick
boolean performClick ()
Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc.
The idea is that when one view is clicked, your code will call performClick() on the other view. You will have to make sure that you inhibit any duplication of actions if the two views do the same function.
Other than doing this in code, I don't know of a way using just XML. There is the concept of a Group in ConstraintLayout but that just a way to control the visibility of the members of the group and does not extend to other properties.
I would use another enclosing view group unless you have a requirement not to. I just seems easier.
Use Group concept in ConstraintLayout refer: https://developer.android.com/reference/android/support/constraint/Group ,https://riggaroo.co.za/constraintlayout-guidelines-barriers-chains-groups/ ,
in java
Group group = findViewById(R.id.group);
int refIds[] = group.getReferencedIds();
for (int id : refIds) {
findViewById(id).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// your code here.
}
});
}
Kotlin:
fun Group.setAllOnClickListener(listener: View.OnClickListener?) {
referencedIds.forEach { id ->
rootView.findViewById<View>(id).setOnClickListener(listener)
}
}
Then call the function on the group:
group.setAllOnClickListener(View.OnClickListener {
// your code here.
})

andengine removing collectable objects like Sprites

im developing a game using andangine and the tmx and body2d extensions.
i create Objects(sprites) like coins an specific positions while creating my map.
i use a contactlistener to check if the player collides with a coin.
how can i delete this sprite?
and how can i organize my sprites best?
thanks =)
I assume you create a PhysicsConnector to connect between your sprites and bodies. Create a list of these physics connectors, and when you decide you should remove a body (And its sprite), do the following:
Body bodyToRemove = //Get it from your contact listener
for(PhysicsConnector connector : mPhysicsConnectors) //mPhysicsConnectors is the list of your coins physics connectors.
if(connector.getBody() == bodyToRemove)
removeSpriteAndBody(connector); //This method should also delete the physics connector itself from the connectors list.
About sprites organization: Coins are re-useable sprite, you shouldn't recreate them every time. You can use an object pool, here's a question about this topic.
I advice you to set user data of a body. And in your collision handler you would be able to work with it. Small example:
body.setUserData(...);
..
public void postSolve(Contact contact, ContactImpulse impulse) {
... bodyAType = (...) bodyA.getUserData();
... bodyBType = (...) bodyB.getUserData();
if (bodyAType != null && bodyBType != null) {
if (bodyAType.getUserData.equals(...)) {
//.......do what you need
}
}
}

Why the command button is not being displayed in my emulator?

I have already added 5 cammands in a form and I want to add a sixth but It does not display the sixth?
I am posting my codes below.
public Command getOk_Lastjourney() {
if (Ok_Lastjourney == null) {
// write pre-init user code here
Ok_Lastjourney = new Command("Last Journey", Command.OK, 0);
// write post-init user code here
}
return Ok_Lastjourney;
}
public Form getFrm_planjourney() {
if (frm_planjourney == null) {
// write pre-init user code here
frm_planjourney = new Form("Plan journey", new Item[] { getTxt_From(), getTxt_To(), getCg_usertype(), getCg_userpref(), getCg_searchalgo() });
frm_planjourney.addCommand(getExt_planjourney());
frm_planjourney.addCommand(getOk_planjourney());
frm_planjourney.addCommand(getOk_planFare());
frm_planjourney.addCommand(getOk_planDistance());
frm_planjourney.addCommand(getOk_planTime());
frm_planjourney.addCommand(getOk_planRoute());
frm_planjourney.setCommandListener(this);
// write post-init user code here
System.out.println("Appending.....");
System.out.println("Append completed...");
System.out.println(frm_planjourney.size());
frm_planjourney.setItemStateListener(this);
}
return frm_planjourney;
}
Given System.out.println I assume you were debugging with emulator, right? in that case it would be really helpful to provide a screen shot showing how exactly does not display the sixth looks like.
Most likely you just got too many commands to fit to area allocated so that some of them are not shown until scrolled. There is also a chance that sixth command was reassigned to some other soft-button and you didn't notice that. Or there's something else - hard to tell with details you provided.
A general note - handling six actions with commands might be not the best choice in MIDP UI. For stuff like that, consider using lcdui List API instead. IMPLICIT kind of lists allow for more reliable and user friendly design than commands.

Resources