I'm creating a cordova plugin that should return the device's position using mapbox. The issue is that LocationEngineResult.getLastLocation() is always returning null.
I use locationEngine to retrieve the location with locationCallback.
Permissions are also checked.
***
LocationEngine locationEngine;
AltGeolocationLocationCallback callback = new AltGeolocationLocationCallback(this);
***
#SuppressLint("MissingPermission")
private void initLocationEngine() {
locationEngine = LocationEngineProvider.getBestLocationEngine(this.cordova.getActivity().getApplicationContext());
LocationEngineRequest request = new LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setMaxWaitTime(DEFAULT_MAX_WAIT_TIME).build();
locationEngine.requestLocationUpdates(request, callback, Looper.getMainLooper());
locationEngine.getLastLocation(callback);
}
private static class AltGeolocationLocationCallback extends Activity
implements LocationEngineCallback<LocationEngineResult> {
private final WeakReference<AltGeolocation> activityWeakReference;
private AltGeolocationLocationCallback contexto = this;
AltGeolocationLocationCallback(AltGeolocation activity) {
this.activityWeakReference = new WeakReference<>(activity);
}
#Override
public void onSuccess(LocationEngineResult result) {
AltGeolocation activity = activityWeakReference.get();
if (activity != null) {
Location location = result.getLastLocation();
Log.d(LOG_TAG, "result: " + location );
}
}
#Override
public void onFailure(#NonNull Exception exception) {
AltGeolocation activity = activityWeakReference.get();
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}
}
Related
I am trying out agora sdk sample on android using java. when I run the app on my phone and remote device the audio actually works well but the video shows black screen. How do I solve this issue.
I have tried what was stated on agora docs but non worked for me.
I have checked permissions they are working fine
My front camera is working fine
I enabled the video on my code.
My Code
public class VideoChatViewActivity extends AppCompatActivity {
private static final String TAG = VideoChatViewActivity.class.getSimpleName();
private static final int PERMISSION_REQ_ID = 22;
private static final String[] REQUESTED_PERMISSIONS = {
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private RtcEngine mRtcEngine;
private boolean mCallEnd;
private boolean mMuted;
private FrameLayout mLocalContainer;
private RelativeLayout mRemoteContainer;
private SurfaceView mLocalView;
private SurfaceView mRemoteView;
private ImageView mCallBtn;
private ImageView mMuteBtn;
private ImageView mSwitchCameraBtn;
// Customized logger view
private LoggerRecyclerView mLogView;
#Override
public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLogView.logI("Join channel success, uid: " + (uid & 0xFFFFFFFFL));
}
});
}
#Override
public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLogView.logI("First remote video decoded, uid: " + (uid & 0xFFFFFFFFL));
setupRemoteVideo(uid);
}
});
}
#Override
public void onUserOffline(final int uid, int reason) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLogView.logI("User offline, uid: " + (uid & 0xFFFFFFFFL));
onRemoteUserLeft();
}
});
}
};
private void setupRemoteVideo(int uid) {
int count = mRemoteContainer.getChildCount();
View view = null;
for (int i = 0; i < count; i++) {
View v = mRemoteContainer.getChildAt(i);
if (v.getTag() instanceof Integer && ((int) v.getTag()) == uid) {
view = v;
}
}
if (view != null) {
return;
}
mRemoteView = RtcEngine.CreateRendererView(getBaseContext());
mRemoteContainer.addView(mRemoteView);
// Initializes the video view of a remote user.
mRtcEngine.setupRemoteVideo(new VideoCanvas(mRemoteView, VideoCanvas.RENDER_MODE_HIDDEN, uid));
mRemoteView.setTag(uid);
}
private void onRemoteUserLeft() {
removeRemoteVideo();
}
private void removeRemoteVideo() {
if (mRemoteView != null) {
mRemoteContainer.removeView(mRemoteView);
}
// Destroys remote view
mRemoteView = null;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_chat_view);
initUI();
// Ask for permissions at runtime.
// This is just an example set of permissions. Other permissions
// may be needed, and please refer to our online documents.
if (checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID) &&
checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID) &&
checkSelfPermission(REQUESTED_PERMISSIONS[2], PERMISSION_REQ_ID)) {
initEngineAndJoinChannel();
}
}
private void initUI() {
mLocalContainer = findViewById(R.id.local_video_view_container);
mRemoteContainer = findViewById(R.id.remote_video_view_container);
mCallBtn = findViewById(R.id.btn_call);
mMuteBtn = findViewById(R.id.btn_mute);
mSwitchCameraBtn = findViewById(R.id.btn_switch_camera);
mLogView = findViewById(R.id.log_recycler_view);
// Sample logs are optional.
showSampleLogs();
}
private void showSampleLogs() {
mLogView.logI("Welcome to Agora 1v1 video call");
mLogView.logW("You will see custom logs here");
mLogView.logE("You can also use this to show errors");
}
private boolean checkSelfPermission(String permission, int requestCode) {
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQ_ID) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED ||
grantResults[1] != PackageManager.PERMISSION_GRANTED ||
grantResults[2] != PackageManager.PERMISSION_GRANTED) {
showLongToast("Need permissions " + Manifest.permission.RECORD_AUDIO +
"/" + Manifest.permission.CAMERA + "/" + Manifest.permission.WRITE_EXTERNAL_STORAGE);
finish();
return;
}
// Here we continue only if all permissions are granted.
// The permissions can also be granted in the system settings manually.
initEngineAndJoinChannel();
}
}
private void showLongToast(final String msg) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
});
}
private void initEngineAndJoinChannel() {
// This is our usual steps for joining
// a channel and starting a call.
initializeEngine();
setupVideoConfig();
setupLocalVideo();
joinChannel();
}
private void initializeEngine() {
try {
mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
}
private void setupVideoConfig() {
// In simple use cases, we only need to enable video capturing
// and rendering once at the initialization step.
// Note: audio recording and playing is enabled by default.
mRtcEngine.enableVideo();
// Please go to this page for detailed explanation
// https://docs.agora.io/en/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html#af5f4de754e2c1f493096641c5c5c1d8f
mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
VideoEncoderConfiguration.VD_640x360,
VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
VideoEncoderConfiguration.STANDARD_BITRATE,
VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT));
}
private void setupLocalVideo() {
mRtcEngine.setupLocalVideo(new VideoCanvas(mLocalView, VideoCanvas.RENDER_MODE_HIDDEN, 0));
}
private void joinChannel() {
String token = getString(R.string.agora_access_token);
if (TextUtils.isEmpty(token) || TextUtils.equals(token, "#YOUR ACCESS TOKEN#")) {
token = null; // default, no token
}
mRtcEngine.joinChannel(token, "demoChannel1", "Extra Optional Data", 0);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (!mCallEnd) {
leaveChannel();
}
/*
Destroys the RtcEngine instance and releases all resources used by the Agora SDK.
This method is useful for apps that occasionally make voice or video calls,
to free up resources for other operations when not making calls.
*/
RtcEngine.destroy();
}
private void leaveChannel() {
mRtcEngine.leaveChannel();
}
public void onLocalAudioMuteClicked(View view) {
mMuted = !mMuted;
// Stops/Resumes sending the local audio stream.
mRtcEngine.muteLocalAudioStream(mMuted);
int res = mMuted ? R.drawable.btn_mute : R.drawable.btn_unmute;
mMuteBtn.setImageResource(res);
}
public void onSwitchCameraClicked(View view) {
// Switches between front and rear cameras.
mRtcEngine.switchCamera();
}
public void onCallClicked(View view) {
if (mCallEnd) {
startCall();
mCallEnd = false;
mCallBtn.setImageResource(R.drawable.btn_endcall);
} else {
endCall();
mCallEnd = true;
mCallBtn.setImageResource(R.drawable.btn_startcall);
}
showButtons(!mCallEnd);
}
private void startCall() {
setupLocalVideo();
joinChannel();
}
private void endCall() {
removeLocalVideo();
removeRemoteVideo();
leaveChannel();
}
private void removeLocalVideo() {
if (mLocalView != null) {
mLocalContainer.removeView(mLocalView);
}
mLocalView = null;
}
private void showButtons(boolean show) {
int visibility = show ? View.VISIBLE : View.GONE;
mMuteBtn.setVisibility(visibility);
mSwitchCameraBtn.setVisibility(visibility);
}
}
I dont really know what is the issue. Anyone have idea on how I can solve this issue?
I found the solution for this
you have to add delay of 10 seconds before running below code
mRtcEngine!!.setClientRole(Constants.CLIENT_ROLE_BROADCASTER)
mRtcEngine!!.joinChannel(
stringToken,
channelName,
"Extra Optional Data",
currentUid
)
so the surface view of current user is loaded properly first and then it tries to join the call.
Simply put, dont join channel before surface view and camera is ready.
I have a location tracking app. I have a Foreground service that when the app goes into the background, it continues to get the location. That part works fine. If I output the location I can see the different points and correct timestamps.
While in the background I need to POST that data to an API endpoint. My GPSHeartbeat class is a singleton and it exposes a function to let me update the Singletons location property.
While in the foreground, everything works fine. When in the background, the location IS updated, but the singleton has the last location from BEFORE it went into the background.
My APICommunicator is firing in the background on its interval like it should, it just doesn't have the correct Location.
Here is the broadcast receiver that is responsible for listening to the Foreground services location change.
This works fine in the background and in the foreground. It is successfully getting the updated location.
private void onNewLocation(Location location)
{
Log.i(TAG, "onNewLocationRec'd: " + location);
mLocation = location;
// Notify anyone listening for broadcasts about the new location.
Intent intent = new Intent(ACTION_BROADCAST);
intent.putExtra(EXTRA_LOCATION, location);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
// Update notification content if running as a foreground service.
if (serviceIsRunningInForeground(this)) {
mNotificationManager.notify(NOTIFICATION_ID, getNotification());
}
}
The BroadcastReceiver is an inner class of an Activity called HomeActivity. This gets the CORRECT location from the service. If I output the log, it is the same as what the Service broadcast.
public class HomeActivity extends AppCompatActivity
{
private GPSHeartbeat mGPSHeartbeat;
private GPSReceiver myReceiver;
private LocationUpdatesService mService = null;
private boolean mBound = false;
private final ServiceConnection mServiceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName name, IBinder service)
{
LocationUpdatesService.LocalBinder binder = (LocationUpdatesService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name)
{
mService = null;
mBound = false;
}
};
private void GPSBeginRequestingUpdates()
{
//Wait 5 seconds to spin up
(new Handler()).postDelayed(this::StartGPSUpdates, 5000);
}
private void StartGPSUpdates()
{
mService.requestLocationUpdates();
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
myReceiver = new GPSReceiver();
setContentView(R.layout.activity_home);
mGPSHeartbeat = GPSHeartbeat.instance(getApplicationContext()).setInterval(6);
}
#Override
protected void onStart()
{
super.onStart();
bindService(new Intent(getApplicationContext(), LocationUpdatesService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop()
{
if (mBound) {
unbindService(mServiceConnection);
mBound = false;
}
super.onStop();
}
#Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(myReceiver, new IntentFilter(LocationUpdatesService.ACTION_BROADCAST));
GPSBeginRequestingUpdates();
}
#Override
protected void onPause()
{
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(myReceiver);
super.onPause();
}
private class GPSReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Location location = intent.getParcelableExtra(LocationUpdatesService.EXTRA_LOCATION);
if (location != null) {
Log.i(TAG, "\nonReceived New Location: " + GPSUtils.getLocationText(location));
GPSHeartbeat.instance(context.getApplicationContext()).SetLocation(location);
}
}
}
}
The Singleton. The SetLocation() does receive the correct location. It is only during my POST request that the APICommunicator is using the GPSHeartbeat's old location. Even though it was just updated.
How do I make sure I update to the correct location?
public class GPSHeartbeat extends Service {
private static String TAG = "GPSHeartbeat";
private static volatile GPSHeartbeat _instance;
private final WeakReference<Context> mContextRef;
private Boolean isRunning = false;
private int mInterval;
private Location mLocation;
private Handler mHandler;
private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
private Future mLongRunningTaskFuture;
private Runnable mStatusChecker = new Runnable()
{
#Override
public void run()
{
try {
tick(); //this function can change value of mInterval.
}
finally {
if (isRunning()) {
// 100% guarantee that this always happens, even if your update method throws an exception
mHandler.postDelayed(mStatusChecker, mInterval);
}
}
}
};
private GPSHeartbeat(Context context)
{
mContextRef = new WeakReference<>(context.getApplicationContext());
}
public static GPSHeartbeat instance(Context context)
{
if (_instance == null) {
_instance = new GPSHeartbeat(context);
} else {
if (!context.equals(_instance.mContextRef.get())) {
_instance = null;
_instance = new GPSHeartbeat(context);
}
}
return _instance;
}
public void SetLocation(Location loc)
{
Log.i(TAG, "setLocation(): " + loc);
this.mLocation = loc;
}
public GPSHeartbeat setInterval(int interval)
{
this.mInterval = interval * 1000;
return this;
}
public void start()
{
if (isRunning()) return;
mHandler = new Handler();
mLongRunningTaskFuture = mExecutorService.submit(mStatusChecker);
mStatusChecker.run();
isRunning = true;
}
public void stop()
{
if (mHandler != null) {
mHandler.removeCallbacks(mStatusChecker);
}
if (mLongRunningTaskFuture != null) {
//kill the task:
try {
mLongRunningTaskFuture.cancel(true);
mLongRunningTaskFuture = null;
mHandler = null;
}
catch (Exception e) {
Log.e(TAG, "Unable to cancel task: " + e.getLocalizedMessage());
}
}
isRunning = false;
}
public Location currentLocation()
{
return mLocation;
}
public boolean isRunning()
{
return isRunning;
}
private void tick()
{
// Fire off the APICommuncator.Post() method
}
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
The APICommuncator
public class APICommuncator
{
private static String TAG = "APICommuncator";
private static volatile APICommuncator _instance;
private final WeakReference<Context> mContextRef;
private GPSHeartbeat _gpsHeartbeat;
private APICommuncator(Context context)
{
mContextRef = new WeakReference<>(context.getApplicationContext());
_gpsHeartbeat = GPSHeartbeat.instance(context.getApplicationContext());
}
public static APICommuncator i(Context context)
{
if (_instance == null) {
_instance = new APICommuncator(context);
} else {
if (!context.equals(_instance.mContextRef.get())) {
_instance = null;
_instance = new APICommuncator(context);
}
}
return _instance;
}
public void Post(){
// Do the background thing and grab
// getLocationNode() which gets the OLD location before it went to the background.
}
private JSONObject getLocationNode()
{
Location location = _gpsHeartbeat.currentLocation();
if (location == null) {
return null;
}
JSONObject node = null;
try {
node = new JSONObject();
node.put("Latitude", String.valueOf(location.getLatitude()));
node.put("Longitude", String.valueOf(location.getLongitude()));
node.put("HAccuracy", String.valueOf(location.getAccuracy()));
node.put("VAccuracy", String.valueOf(location.getAccuracy()));
node.put("Altitude", String.valueOf(location.getAltitude()));
node.put("Speed", String.valueOf(location.getSpeed() * 2.237));
node.put("Heading", String.valueOf(location.getBearing()));
node.put("Timestamp", String.valueOf((location.getTime() / 1000)));
}
catch (JSONException | NullPointerException e) {
e.printStackTrace();
}
return node;
}
}
In the Manifest:
<service
android:name=".gpsheartbeat.GPSHeartbeat"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:name=".gpsheartbeat.LocationUpdatesService"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="location" />
Actually I don't see that you are using foreground service. Not foreground service would be killed very soon after the application goes background. Plus communication with API should be in the scope of foreground service because activity could be killed by the system.
This question already has answers here:
NullPointerException addToRequestQueue(com.android.volley.Request, java.lang.String)' on a null object reference
(8 answers)
Closed 4 years ago.
This is a barcode scanning app. It crashes when I scanned the code. If anyone knows how to fix help me out.
It crashes after I scanned the code from the ScanActivity.java and pass the object to the TicketResultActivity.javato display the result.
error
java.lang.RuntimeException: Unable to start activity ComponentInfo{info.androidhive.movietickets/info.androidhive.movietickets.TicketResultActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void info.androidhive.movietickets.MyApplication.addToRequestQueue(com.android.volley.Request)' on a null object reference
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
// making toolbar transparent
transparentToolbar();
setContentView(R.layout.activity_main);
findViewById(R.id.btn_scan).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this, ScanActivity.class));
}
});
}
private void transparentToolbar() {
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true);
}
if (Build.VERSION.SDK_INT >= 19) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
}
private void setWindowFlag(Activity activity, final int bits, boolean on) {
Window win = activity.getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
if (on) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
win.setAttributes(winParams);
}
}
ScanActivity.java
public class ScanActivity extends AppCompatActivity implements BarcodeReader.BarcodeReaderListener{
BarcodeReader barcodeReader;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
// get the barcode reader instance
barcodeReader = (BarcodeReader) getSupportFragmentManager().findFragmentById(R.id.barcode_scanner);
}
#Override
public void onScanned(Barcode barcode) {
// playing barcode reader beep sound
barcodeReader.playBeep();
// ticket details activity by passing barcode
Intent intent = new Intent(ScanActivity.this, TicketResultActivity.class);
intent.putExtra("code", barcode.displayValue);
startActivity(intent);
}
#Override
public void onScannedMultiple(List<Barcode> list) {
}
#Override
public void onBitmapScanned(SparseArray<Barcode> sparseArray) {
}
/*#Override
public void onCameraPermissionDenied() {
finish();
}*/
#Override
public void onScanError(String s) {
Toast.makeText(getApplicationContext(), "Error occurred while scanning " + s, Toast.LENGTH_SHORT).show();
}
}
TicketResultActivity.java
public class TicketResultActivity extends AppCompatActivity {
private static final String TAG = TicketResultActivity.class.getSimpleName();
// url to search barcode
private static final String URL = "https://api.androidhive.info/barcodes/search.php?code=";
private TextView txtName, txtDuration, txtDirector, txtGenre, txtRating, txtPrice, txtError;
private ImageView imgPoster;
private Button btnBuy;
private ProgressBar progressBar;
private TicketView ticketView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ticket_result);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
txtName = findViewById(R.id.name);
txtDirector = findViewById(R.id.director);
txtDuration = findViewById(R.id.duration);
txtPrice = findViewById(R.id.price);
txtRating = findViewById(R.id.rating);
imgPoster = findViewById(R.id.poster);
txtGenre = findViewById(R.id.genre);
btnBuy = findViewById(R.id.btn_buy);
imgPoster = findViewById(R.id.poster);
txtError = findViewById(R.id.txt_error);
ticketView = findViewById(R.id.layout_ticket);
progressBar = findViewById(R.id.progressBar);
String barcode = getIntent().getStringExtra("code");
// close the activity in case of empty barcode
if (TextUtils.isEmpty(barcode)) {
Toast.makeText(getApplicationContext(), "Barcode is empty!", Toast.LENGTH_LONG).show();
finish();
}
// search the barcode
searchBarcode(barcode);
}
/**
* Searches the barcode by making HTTP call
* Request was made using Volley network library but the library is
* not suggested in production, consider using Retrofit
*/
private void searchBarcode(String barcode) {
// making volley's json request
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
URL + barcode, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e(TAG, "Ticket response: " + response.toString());
// check for success status
if (!response.has("error")) {
// received movie response
renderMovie(response);
} else {
// no movie found
showNoTicket();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
showNoTicket();
}
});
MyApplication.getInstance().addToRequestQueue(jsonObjReq);
}
private void showNoTicket() {
txtError.setVisibility(View.VISIBLE);
ticketView.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
}
/**
* Rendering movie details on the ticket
*/
private void renderMovie(JSONObject response) {
try {
// converting json to movie object
Movie movie = new Gson().fromJson(response.toString(), Movie.class);
if (movie != null) {
txtName.setText(movie.getName());
txtDirector.setText(movie.getDirector());
txtDuration.setText(movie.getDuration());
txtGenre.setText(movie.getGenre());
txtRating.setText("" + movie.getRating());
txtPrice.setText(movie.getPrice());
Glide.with(this).load(movie.getPoster()).into(imgPoster);
if (movie.isReleased()) {
btnBuy.setText(getString(R.string.btn_buy_now));
btnBuy.setTextColor(ContextCompat.getColor(this, R.color.colorPrimary));
} else {
btnBuy.setText(getString(R.string.btn_coming_soon));
btnBuy.setTextColor(ContextCompat.getColor(this, R.color.btn_disabled));
}
ticketView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
} else {
// movie not found
showNoTicket();
}
} catch (JsonSyntaxException e) {
Log.e(TAG, "JSON Exception: " + e.getMessage());
showNoTicket();
Toast.makeText(getApplicationContext(), "Error occurred. Check your LogCat for full report", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
// exception
showNoTicket();
Toast.makeText(getApplicationContext(), "Error occurred. Check your LogCat for full report", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
private class Movie {
String name;
String director;
String poster;
String duration;
String genre;
String price;
float rating;
#SerializedName("released")
boolean isReleased;
public String getName() {
return name;
}
public String getDirector() {
return director;
}
public String getPoster() {
return poster;
}
public String getDuration() {
return duration;
}
public String getGenre() {
return genre;
}
public String getPrice() {
return price;
}
public float getRating() {
return rating;
}
public boolean isReleased() {
return isReleased;
}
}
}
MyApplication.java
public class MyApplication extends Application {
public static final String TAG = MyApplication.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
To initialize MyApplication properly you have to add the following in the AndroidManifest.xml
<application android:name="com.package.subpackage.MyApplication">
...
</application>
I'm trying to use the mapbox SDK to get my current location and set the navigation, but it's not working. I was trying to implement this code following the tutorial from the mapbox website.
public class pos extends AppCompatActivity implements LocationEngineListener, PermissionsListener {
private MapView mapView;
// variables for adding location layer
private MapboxMap map;
private PermissionsManager permissionsManager;
private LocationLayerPlugin locationPlugin;
private LocationEngine locationEngine;
private Location originLocation;
// variables for adding a marker
private Marker destinationMarker;
private LatLng originCoord;
private LatLng destinationCoord;
// variables for calculating and drawing a route
private Point originPosition;
private Point destinationPosition;
private DirectionsRoute currentRoute;
private static final String TAG = "DirectionsActivity";
private NavigationMapRoute navigationMapRoute;
//private Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this,"pk.eyJ1IjoiaWhkaW5hIiwiYSI6ImNqaDRveHdhcjB1ZTIyd253M2R2MGhwY28ifQ.If9oJq_rILeuaK1sjp9-nw");
setContentView(R.layout.activity_pos);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(final MapboxMap mapboxMap) {
map = mapboxMap;
enableLocationPlugin();
originCoord = new LatLng(originLocation.getLatitude(), originLocation.getLongitude());
mapboxMap.addOnMapClickListener(new MapboxMap.OnMapClickListener() {
#Override
public void onMapClick(#NonNull LatLng point) {
if (destinationMarker != null) {
mapboxMap.removeMarker(destinationMarker);
}
destinationCoord = point;
destinationMarker = mapboxMap.addMarker(new MarkerOptions()
.position(destinationCoord)
);
destinationPosition = Point.fromLngLat(destinationCoord.getLongitude(), destinationCoord.getLatitude());
originPosition = Point.fromLngLat(originCoord.getLongitude(), originCoord.getLatitude());
getRoute(originPosition, destinationPosition);
/* button.setEnabled(true);
button.setBackgroundResource(R.color.mapboxBlue);*/
}
;
});
/*button = findViewById(R.id.startButton);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Point origin = originPosition;
Point destination = destinationPosition;
// Pass in your Amazon Polly pool id for speech synthesis using Amazon Polly
// Set to null to use the default Android speech synthesizer
String awsPoolId = null;
boolean simulateRoute = true;
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.origin(origin)
.destination(destination)
.awsPoolId(awsPoolId)
.shouldSimulateRoute(simulateRoute)
.build();
// Call this method with Context from within an Activity
NavigationLauncher.startNavigation(NavigationActivity.this, options);
}
});*/
}
;
});
}
private void getRoute(Point origin, Point destination) {
NavigationRoute.builder()
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination)
.build()
.getRoute(new Callback<DirectionsResponse>() {
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// You can get the generic HTTP info about the response
Log.d(TAG, "Response code: " + response.code());
if (response.body() == null) {
Log.e(TAG, "No routes found, make sure you set the right user and access token.");
return;
} else if (response.body().routes().size() < 1) {
Log.e(TAG, "No routes found");
return;
}
currentRoute = response.body().routes().get(0);
// Draw the route on the map
if (navigationMapRoute != null) {
navigationMapRoute.removeRoute();
} else {
navigationMapRoute = new NavigationMapRoute(null, mapView, map, R.style.NavigationMapRoute);
}
navigationMapRoute.addRoute(currentRoute);
}
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
Log.e(TAG, "Error: " + throwable.getMessage());
}
});
}
#SuppressWarnings( {"MissingPermission"})
private void enableLocationPlugin() {
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
// Create an instance of LOST location engine
initializeLocationEngine();
locationPlugin = new LocationLayerPlugin(mapView, map, locationEngine);
locationPlugin.setLocationLayerEnabled(true);
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
#SuppressWarnings( {"MissingPermission"})
private void initializeLocationEngine() {
locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable();
locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
locationEngine.activate();
Location lastLocation = locationEngine.getLastLocation();
if (lastLocation != null) {
originLocation = lastLocation;
setCameraPosition(lastLocation);
} else {
locationEngine.addLocationEngineListener(this);
}
}
private void setCameraPosition(Location location) {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(location.getLatitude(), location.getLongitude()), 13));
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
#Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
}
#Override
public void onPermissionResult(boolean granted) {
if (granted) {
enableLocationPlugin();
} else {
finish();
}
}
#Override
#SuppressWarnings( {"MissingPermission"})
public void onConnected() {
locationEngine.requestLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
originLocation = location;
setCameraPosition(location);
locationEngine.removeLocationEngineListener(this);
}
}
#Override
#SuppressWarnings( {"MissingPermission"})
protected void onStart() {
super.onStart();
if (locationEngine != null) {
locationEngine.requestLocationUpdates();
}
if (locationPlugin != null) {
locationPlugin.onStart();
}
mapView.onStart();
}
#Override
protected void onStop() {
super.onStop();
if (locationEngine != null) {
locationEngine.removeLocationUpdates();
}
if (locationPlugin != null) {
locationPlugin.onStop();
}
mapView.onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
if (locationEngine != null) {
locationEngine.deactivate();
}
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
#Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
Try modifying your methods with this:
private void enableLocationPlugin() {
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
initializeLocationEngine();
locationPlugin = new LocationLayerPlugin(mapView, map, locationEngine);
locationPlugin.setLocationLayerEnabled(true);
locationPlugin.setCameraMode(CameraMode.TRACKING);
locationPlugin.setRenderMode(RenderMode.COMPASS);
getLifecycle().addObserver(locationPlugin);
Log.e(TAG, "enableLocationPlugin:Permission Granted" );
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
Log.e(TAG, "enableLocationPlugin:Permission Not Granted" );
}
}
private void initializeLocationEngine() {
locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable();
locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
locationEngine.addLocationEngineListener(this);
locationEngine.activate();
Location lastLocation = locationEngine.getLastLocation();
if (lastLocation != null) {
setCameraPosition(lastLocation);
} else {
locationEngine.addLocationEngineListener(this);
}
}
and your onStart with this:
#Override
#SuppressWarnings({"MissingPermission"})
protected void onStart() {
super.onStart();
if (locationEngine != null) {
locationEngine.requestLocationUpdates();
locationEngine.addLocationEngineListener(this);
}
if (locationPlugin != null) {
locationPlugin.onStart();
}
mapView.onStart();
}
I have an application which uses the accelerometer, but only occasionally under rare circumstances. I'd like to preserve battery by having it disabled by default and only turn it on when needed.
Only thing I've found is setting configurations when initializing the app from this site
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useCompass = false;
config.useAccelerometer = false;
MyGame myGame = new MyGame(new AndroidPlatform(this, config));
initialize(myGame , config);
}
But I can't find a way to enable/disable it while the app is running. Anyone have an idea?
EDIT:
In the above example AndroidPlatform is implementing a Platform interface in the core project. I tried out Zoe's idea of passing the config to platform implementation and changing it follows:
#Override
public void enableAccelerometer(boolean enable) {
config.useCompass = enable;
config.useAccelerometer = enable;
}
and then in the core project when the accelerometer should be enabled:
private void startInclineMonitoring() {
System.out.println("Before:");
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer));
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Compass));
platform.enableAccelerometer(true);
System.out.println("After:");
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer));
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Compass));
}
Unfortunately this outputs:
I/System.out: Before:
I/System.out: false
I/System.out: false
I/System.out: After:
I/System.out: false
I/System.out: false
So, no luck there.
It seems like there's no easy way to do this as of today, but I ended up doing my own (Android) motion sensor implementation. I thought I'd share it for future visitors:
This assumes you have your platform interface and platform specific implementation as explained in this wiki.
First these methods are added to the interface:
public interface Platform {
public void startMotionSensors(PlatformCallback<float[]> callback);
public void stopMotionSensors();
}
And in the android implementation:
public class AndroidPlatform implements Platform {
private Activity activity;
private MotionSensor motionSensor;
private Handler handler;
public AndroidPlatform(Activity activity) {
this.activity = activity;
this.motionSensor = new MotionSensor(activity);
this.handler = new Handler();
}
#Override
public void startMotionSensors(final PlatformCallback<float[]> callback) {
handler.post(new Runnable() {
#Override
public void run() {
motionSensor.start(callback);
}
});
}
#Override
public void stopMotionSensors() {
handler.post(new Runnable() {
#Override
public void run() {
motionSensor.stop();
}
});
}
}
The MotionSensor class:
public class MotionSensor implements SensorEventListener {
private Activity activity;
private SensorManager sensorManager;
private float[] gravity = new float[3];
private float[] geomag = new float[3];
private float[] rotationMatrix = new float[16];
private float[] inclinationMatrix = new float[16];
private PlatformCallback<float[]> callback;
public MotionSensor(Activity activity) {
this.activity = activity;
}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
gravity = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
geomag = event.values.clone();
break;
}
if (gravity != null && geomag != null) {
boolean success = SensorManager.getRotationMatrix(rotationMatrix,
inclinationMatrix, gravity, geomag);
if (success) {
notifyCallback(new Result(), rotationMatrix);
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private void notifyCallback(Result result, float[] rotationMatrix) {
callback.callback(result, rotationMatrix);
}
public void start(PlatformCallback<float[]> callback) {
this.callback = callback;
sensorManager = (SensorManager) activity.getSystemService(Activity.SENSOR_SERVICE);
if (sensorManager != null) {
boolean accelerometerSupport = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
boolean magneticFieldSupport = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_UI);
if (!accelerometerSupport || !magneticFieldSupport) {
sensorManager.unregisterListener(this);
notifyCallback(new Result(Result.STATE.FAILED, "Not supported"), null);
}
} else {
notifyCallback(new Result(Result.STATE.FAILED, "Not supported"), null);
}
}
public void stop() {
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
}
}
And the PlaformCallback class:
public abstract class PlatformCallback<T> {
public void callback(final Result result, final T t) {
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
doCallback(result, t);
}
});
}
protected abstract void doCallback(Result result, T t);
}
In the core project you can now simply turn on and off your motion sensors:
private void startMotionSensor() {
platform.startMotionSensors(new PlatformCallback<float[]>() {
#Override
protected void doCallback(Result result, float[] rotationMatrix) {
if (result.ok()) {
// Do what you want with the rotation matrix
}
}
});
}
public void stopMotionSensor() {
platform.stopMotionSensors();
}