Google Street view + device tilting - java

I'm trying to add an activity as a feature to an app I'm building where, the API will return a lat long, and with this lat long I will load google street view. Which with the movement of the device, will rotate the 360 degree angle of the position. I'm struggling on the movement part of the device. Using your fingers on the screen you can rotate. I wonder if anyone can point me in the right direction in getting the device movement to affect the position of the street view?
The code I have so far is:
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback;
import com.google.android.gms.maps.StreetViewPanorama;
import com.google.android.gms.maps.StreetViewPanoramaFragment;
import com.google.android.gms.maps.StreetViewPanoramaOptions;
import com.google.android.gms.maps.StreetViewPanoramaView;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.StreetViewPanoramaCamera;
import com.google.android.gms.maps.model.StreetViewPanoramaLocation;
public class MainActivity extends FragmentActivity
implements OnStreetViewPanoramaReadyCallback {
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StreetViewPanoramaFragment streetViewPanoramaFragment =
(StreetViewPanoramaFragment) getFragmentManager()
.findFragmentById(R.id.streetviewpanorama);
streetViewPanoramaFragment.getStreetViewPanoramaAsync(this);
}
#Override
public void onStreetViewPanoramaReady(final StreetViewPanorama panorama) {
final long duration = 1000;
float tilt = 30;
float bearing = 90;
final StreetViewPanoramaCamera camera = new StreetViewPanoramaCamera.Builder()
.zoom(panorama.getPanoramaCamera().zoom)
.bearing(bearing)
.tilt(tilt)
.build();
panorama.setPosition(new LatLng(52.208818, 0.090587));
panorama.setStreetNamesEnabled(false);
panorama.setZoomGesturesEnabled(false);
panorama.setOnStreetViewPanoramaChangeListener(new StreetViewPanorama.OnStreetViewPanoramaChangeListener() {
#Override
public void onStreetViewPanoramaChange(StreetViewPanoramaLocation streetViewPanoramaLocation) {
if (streetViewPanoramaLocation != null) {
panorama.animateTo(camera, duration);
}
Log.d(TAG, "TESTINGGGGGGGGGG");
}
});
}
}

I'm not sure given your question, so comment if i'm wrong but it seems you're able to rotate through this instruction
panorama.animateTo(camera, duration);
and you're moving to a specific location using the "camera" variable you built before.
So, if i understand correctly what you are trying to do, you have to check for mobilephone sensors (accelerometer & position) to get the motion then apply the correct motion to the panorama. Take a look at android sensor documentation in order to get the proper listeners (or how to register a sensor usage) then build the correct camera object according to the acceleration registered by the phone (left acceleration -> rotating left, right acceleration --> rotating right).
If you need a code example i'd suggest you to look this question which has some other links to help you using sensors and getting more doc.
If this does not help, comment and/or clarify the question.

Related

Detect when android user zooms an app screen in Android

I want to log an event for telemetry when user zooms in the screen of an app in android.
Based on my research I could not find a system event that I can subscribe to determine if user zoomed the screen.
Any pointers to detect that?
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.accessibilityservice.AccessibilityService;
import android.graphics.Region;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity implements AccessibilityService.MagnificationController.OnMagnificationChangedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onMagnificationChanged(#NonNull AccessibilityService.MagnificationController magnificationController, #NonNull Region region, float v, float v1, float v2) {
float Scale = v;
// Scale will be changed as magnification is done on app
}
}
You are looking for Android Gestures
Here is a documentation about it:
https://developer.android.com/training/gestures
Here is a zoom/scale gesture:
https://developer.android.com/training/gestures/scale
and
Can we use scale gesture detector for pinch zoom in Android?

simulating touch event on system android java

package net.xxxxxxxxxxxxxxxxx.muxic;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import static android.app.Service.START_STICKY;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//System.out.println(isConnected(this));
setContentView(R.layout.activity_main);
if(isConnected(this)) {
//startActivity(new Intent("com.google.music"));
/*Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
startActivity(i);*/
View view = (View) findViewById(R.id.layoutView);
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE);
KeyguardManager.KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.disableKeyguard();
view.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
Toast toast = Toast.makeText(
getApplicationContext(),
"View touched",
Toast.LENGTH_LONG
);
toast.show();
return true;
}
});
// Obtain MotionEvent object
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis() + 100;
float x = 0.0f;
float y = 0.0f;
// List of meta states found here: developer.android.com/reference/android/view/KeyEvent.html#getMetaState()
int metaState = 0;
MotionEvent motionEvent = MotionEvent.obtain(
downTime,
eventTime,
MotionEvent.ACTION_UP,
x,
y,
metaState
);
// Dispatch touch event to view
view.dispatchTouchEvent(motionEvent);
}
}
#Override
public boolean onTouchEvent(MotionEvent e) {
// MotionEvent reports input details from the touch screen
// and other input controls. In this case, you are only
// interested in events where the touch position changed.
float x = e.getX();
float y = e.getY();
Log.d("[DEBUG]", "X: " + x + "Y: " + y);
return true;
}
public void fox(View v){
Log.d("[DEBUG]", "X: " + v.getPivotX() + ", Y: " + v.getPivotY());
}
public static boolean isConnected(Context context) {
Intent intent = context.registerReceiver(null, new IntentFilter("android.hardware.usb.action.USB_STATE"));
return intent.getExtras().getBoolean("connected");
}
}
What I want to Achieve
Main goal is to be able to check if the user is connected to a device, if TRUE then redirect the user to HOME in which there is a widget waiting to be a pressed. Afterwards fire an event that will automatically touch the widget to start playing the music.
NOTE: The music part is done by a separate app. That's why I have the app redirect to HOME (Triggered/Redirected through intent.) and then execute the button press at X: (coordinate X here) and Y: (coordinate Y here).
I don't care if I have to root, sign with platform key, and all that since I will be the only one that will be using it.
What have I done?
Searched google for over an hour. Found a bunch of tutorials, but most of them are outdated and is not noob proof. However, the code below is in fact from other stackoverflow questions. (Since what I did was simply google what I needed to do, and started mashing them together in hopes that it would work.)
Looked at StackOverflow for answers about Simulating Touch Events, Touch Events android, MotionEvent for android java, Signing app with system permission for touch event, etc.
NOTE: As mentioned most of the stuff I've seen are old (2010-2014). Since when I tried to find the system_signature, it was not in the directory mentioned in another stackoverflow question. If you guys could just give me a small pointer, that'd be really helpful!
EXTRA: I'm also having issue with making it check every X second if the 'connected' status has changed. If it has don't do anything until it's connected again. (I believe this is done through background service thing. As per said just give me a proper name to google and I'll do my own research, or if you give me a definite answer that'd be helpful too.) [NOT NEEDED, but would be cool.]
IMAGE UI
Widget UI - Hopefully this will help you get an idea of what I'm trying to press.

Android Wear Wellness Sensor Moto360

As far as I know , moto360 doesn't have a sensor of type : TYPE_HEART_RATE, it's called passive wellness sensor.
The problem is that this wellness sensor is not giving me any data, as opposed to every other sensor that I've tried (like gravity, accelerometer...)
I've been waiting for more than 5 min but this sensor gives me data only when I start the app.
I've tried sdk20,sdk21,sdk22,sdk23 ... still no result
I also have the android.permission.BODY_SENSORS in my manifest
Question : How to get the sensor working, what can I do?
package com.x.firstapp;
import android.app.Activity;
import android.os.Bundle;
import android.support.wearable.view.WatchViewStub;
import android.util.Log;
import android.widget.Toast;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.WindowManager;
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mHeartSensor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override
public void onLayoutInflated(WatchViewStub stub) {
}
});
// keep watch screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Toast.makeText(getApplicationContext(), "Hi Oleg", Toast.LENGTH_LONG).show();
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mHeartSensor = mSensorManager.getDefaultSensor(65538); //wellness sensor
mSensorManager.registerListener(this, mHeartSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == 65538) {
String msg = "" + (int) event.values[0];
Log.d("Main Activity", msg);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
Log.d("Main Activity", "accuracy : " + accuracy + " sensor : " + sensor.getName());
}
#Override
protected void onStop() {
super.onStop();
mSensorManager.unregisterListener(this);
}
}
only output out of this "wellness" sensor (only when app starts) :
D/Main Activity: accuracy : 3 sensor : Wellness Passive Sensor
D/Main Activity: 0
As you know ,the value of TYPE_HEART_RATE is not equal to the Wellness Passive Sensor, but when I set as below:
Sensor mHeartRateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
I find, I get the heart beat values.
By the way, don't forget to add permission.
I remember having huge problems specifically on the Moto 360 (first gen) when trying to read heart rate data. You're doing the correct thing using the passive wellness sensor as there isn't a heart rate monitor reported in the list of sensors.
Have a look at the Github repo here for inspiration (that's what I did to figure it out): https://github.com/pocmo/SensorDashboard
It's worth noting that even if you get it working, it's incredibly flaky. It's even flaky through the built in apps - have a play around with the Google Fit and Moto Body to take your heart rate, you'll see what I mean.
Google have API for fitness sensors, look at the following links
https://developers.google.com/fit/android/sensors
And project for example
https://github.com/googlesamples/android-fit/tree/master/BasicSensorsApi

Android: addProximityAlert LocationManager Method doesn't send Broadcast

I'm working on an Android Project where i'm using AddProximityAlert method, as you already know this method let you set a proximity alert for the location given by the position (latitude, longitude) and the given radius, and notify you if you are so close to it.
so i was working on that for three days ago and i was getting the same probleme again and again..
in bref: this is my simple code.
#MainActivity.java
package com.example.proximityalert;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity implements LocationListener {
LocationManager lm;
//Defining Latitude & Longitude
double lat=37.422006 ,long1=-122.084095;
//Defining Radius
float radius=1000;
//Intent Action
String ACTION_FILTER = "com.example.proximityalert";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//i'm registering my Receiver First
registerReceiver(new ProximityReciever(), new IntentFilter(ACTION_FILTER));
//i'm calling ther service Location Manager
lm=(LocationManager) getSystemService(LOCATION_SERVICE);
//for debugging...
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10, this);
//Setting up My Broadcast Intent
Intent i= new Intent(ACTION_FILTER);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), -1, i, 0);
//setting up proximituMethod
lm.addProximityAlert(lat, long1, radius, -1, pi);
}
#Override
//just For debugging to See the distance between my actual position and the aproximit point
public void onLocationChanged(Location newLocation) {
Location old = new Location("OLD");
old.setLatitude(lat);
old.setLongitude(long1);
double distance = newLocation.distanceTo(old);
Log.i("MyTag", "Distance: " + distance);
}
#Override
public void onProviderDisabled(String arg0) {}
#Override
public void onProviderEnabled(String arg0) {}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}
}
#ProximityReceiver.java
package com.example.proximityalert;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.util.Log;
import android.widget.Toast;
public class ProximityReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Key for determining whether user is leaving or entering
String key = LocationManager.KEY_PROXIMITY_ENTERING;
//Gives whether the user is entering or leaving in boolean form
boolean state = intent.getBooleanExtra(key, false);
if(state){
// Call the Notification Service or anything else that you would like to do here
Log.i("MyTag", "Welcome to my Area");
Toast.makeText(context, "Welcome to my Area", Toast.LENGTH_SHORT).show();
}else{
//Other custom Notification
Log.i("MyTag", "Thank you for visiting my Area,come back again !!");
Toast.makeText(context, "Thank you for visiting my Area,come back again !!", Toast.LENGTH_SHORT).show();
}
}
}
*#the probleme is when i run the program , the BroadcastReceiver(ProximityReciever) never never called by the system even if i'm veryyy close to the proximit point, and even if the debugger shows me that distance between the two locations is < 1000m :/
I just figured out somthing about this topic and why the addProximityAlert sames to be not working, I'm sharing this with you because I noticed that some people asked the same question before and they don't get any answer!
The answer was just in front of me but i didn't pay attention to it, so when i was reading the Android officiel documentation (here) i saw this sentence "Due to the approximate nature of position estimation, if the device passes through the given area briefly, it is possible that no Intent will be fired"
what is that mean? it means when you are testing your app on the AVD and u send a gps coordinates(latitude, longitude) from the DDMS to AVD its really hard to
simulate the real aspect of a gps, (because in the first place u pick some point to be your proximPoint and just after that you choose anthor point very far from the proximPoint to see if its work) and thats not what it's happing with a real device.
so the solution is to test your app on a real device or with the DDMS try to change the coordiantes very slowly until you are in the zone wanted.

Android sensor callback behavior

I'm working with a friend trying to develop an android application to track movement by numerically integrating acceleration. We are mechanical engineering students and having trouble understanding how the order of events is occurs within the threads used in an android application. For example it appears that the UI thread runs before the code that called it can finish executing. See the following code that just attempts to get the current acceleration and store the previous acceleration for later use in trapezoidal integration:
import java.util.Arrays;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity implements SensorEventListener {
float[] current;
float[] last;
SensorManager sm;
Sensor accelerometer;
TextView Display;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
current = new float[] {0, 0, 0};
last = new float[] {0, 0, 0};
sm = (SensorManager)getSystemService(SENSOR_SERVICE);
accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sm.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
Display = (TextView)findViewById(R.id.text_box);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onSensorChanged(SensorEvent event) {
last = current;
current = event.values;
if (last != current) {
Display.setText(Arrays.toString(current)+"\n"+Arrays.toString(last)+"\nThe numbers are not the same!!!");
} else {
Display.setText(Arrays.toString(current)+"\n"+Arrays.toString(last)+"\nThe numbers are the same!!!");
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
The result is that the TextView always displays "the numbers are the same" text.The acceleration values change but the printed current and last values are always the same (ie "[.4423,.12234,9.8234]\n[.4423,.12234,9.8234]\nThe values are the same"). We put a counter in the code to see how often the if statement detects that the values are different and it only increments to one, which I assumes happens on the first iteration. I can't come up with any good theory why the values would change with time but the current and last values are never different. Can the UI thread somehow get the value of last before it is updated by the sensor manager thread? Should I have to deal with handling the order of thread execution if I didn't explicitly create one?
OK so the problem was a fundamental misunderstanding of how Java works. We were passing around the pointers to the array. I have worked with c++ before and thought that since java doesn't use pointers that setting arrays equal to one another was equivalent to passing by value. Doing this actually just set the reference to the current and last variables equal to the reference to the events.value array, which means that the setText function was told to print the values from the same reference. This was a painful way to learn, the Professor who gave us this project is the third person who said to me "if you understand C++, you'll understand java", when he should have said go read a book on the specifics...
To run the above code running we changed:
last = current;
current = event.values;
to this:
System.arraycopy(current,0,last,0,3);
System.arraycopy(event.values, 0, current, 0, 3);

Categories