Camera not initialization issue with rpi3 camera v2 on Android Things - raspberry-pi3

I am trying to run a simple Android Thing project that simply captures and renders the captured image in the display. I took the sample code from (https://github.com/googlecodelabs/androidthings-imageclassifier/tree/master/imageclassifier-add-camera) without the image recognition part. But I'm getting the following error-
I/InstantRun: starting instant run server: is main process
I/CameraManagerGlobal: Connecting to camera service
D/CameraHandler: Using camera id 0
W/CameraHandler: Cannot capture image. Camera not initialized.
D/CameraHandler: Opened camera.
So it seems it detects the camera but it can't capture images from the camera. Anyone faced similar issues on AndroidThings platform?
Main Camera Handler code provided below-
public class CameraHandler {
private static final String TAG = CameraHandler.class.getSimpleName();
public static final int IMAGE_WIDTH = 320;
public static final int IMAGE_HEIGHT = 240;
private static final int MAX_IMAGES = 1;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
/**
* An {#link android.media.ImageReader} that handles still image capture.
*/
private ImageReader mImageReader;
// Lazy-loaded singleton, so only one instance of the camera is created.
private CameraHandler() {
}
private static class InstanceHolder {
private static CameraHandler mCamera = new CameraHandler();
}
public static CameraHandler getInstance() {
return InstanceHolder.mCamera;
}
/**
* Initialize the camera device
*/
public void initializeCamera(Context context,
Handler backgroundHandler,
ImageReader.OnImageAvailableListener imageAvailableListener) {
// Discover the camera instance
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
String[] camIds = {};
try {
camIds = manager.getCameraIdList();
} catch (CameraAccessException e) {
Log.d(TAG, "Cam access exception getting IDs", e);
}
if (camIds.length < 1) {
Log.d(TAG, "No cameras found");
return;
}
String id = camIds[0];
Log.d(TAG, "Using camera id " + id);
// Initialize the image processor
mImageReader = ImageReader.newInstance(IMAGE_WIDTH, IMAGE_HEIGHT,
ImageFormat.JPEG, MAX_IMAGES);
mImageReader.setOnImageAvailableListener(
imageAvailableListener, backgroundHandler);
// Open the camera resource
try {
manager.openCamera(id, mStateCallback, backgroundHandler);
} catch (CameraAccessException cae) {
Log.d(TAG, "Camera access exception", cae);
}
}
/**
* Callback handling device state changes
*/
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice cameraDevice) {
Log.d(TAG, "Opened camera.");
mCameraDevice = cameraDevice;
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
Log.d(TAG, "Camera disconnected, closing.");
closeCaptureSession();
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
Log.d(TAG, "Camera device error, closing.");
closeCaptureSession();
cameraDevice.close();
}
#Override
public void onClosed(#NonNull CameraDevice cameraDevice) {
Log.d(TAG, "Closed camera, releasing");
mCameraDevice = null;
}
};
/**
* Begin a still image capture
*/
public void takePicture() {
if (mCameraDevice == null) {
Log.w(TAG, "Cannot capture image. Camera not initialized.");
return;
}
// Here, we create a CameraCaptureSession for capturing still images.
try {
mCameraDevice.createCaptureSession(
Collections.singletonList(mImageReader.getSurface()),
mSessionCallback,
null);
} catch (CameraAccessException cae) {
Log.d(TAG, "access exception while preparing pic", cae);
}
}
/**
* Callback handling session state changes
*/
private CameraCaptureSession.StateCallback mSessionCallback =
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
// The camera is already closed
if (mCameraDevice == null) {
return;
}
// When the session is ready, we start capture.
mCaptureSession = cameraCaptureSession;
triggerImageCapture();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Log.w(TAG, "Failed to configure camera");
}
};
/**
* Execute a new capture request within the active session
*/
private void triggerImageCapture() {
try {
final CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mImageReader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
//captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO);
Log.d(TAG, "Capture request created.");
mCaptureSession.capture(captureBuilder.build(), mCaptureCallback, null);
} catch (CameraAccessException cae) {
Log.d(TAG, "camera capture exception");
}
}
/**
* Callback handling capture session events
*/
private final CameraCaptureSession.CaptureCallback mCaptureCallback =
new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureProgressed(#NonNull CameraCaptureSession session,
#NonNull CaptureRequest request,
#NonNull CaptureResult partialResult) {
Log.d(TAG, "Partial result");
}
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session,
#NonNull CaptureRequest request,
#NonNull TotalCaptureResult result) {
session.close();
mCaptureSession = null;
Log.d(TAG, "CaptureSession closed");
}
};
private void closeCaptureSession() {
if (mCaptureSession != null) {
try {
mCaptureSession.close();
} catch (Exception ex) {
Log.e(TAG, "Could not close capture session", ex);
}
mCaptureSession = null;
}
}
/**
* Close the camera resources
*/
public void shutDown() {
closeCaptureSession();
if (mCameraDevice != null) {
mCameraDevice.close();
}
}
}

The pitfall with camera:
Check the permissions in Manifest file, and restart the device.
The camera-permission is granted not after installing the application, but first after install and RESTART of device.
see https://developer.android.com/things/sdk/index.html

Related

Sinch Video clling APi not working when app is cleared from recents

I am using sinch Video calling API for my android application. But when the app is in the background, whenever the user is offline i.e user cleared app from the recent tab, he was unable to get the call. I used Firebase for pushing notification whenever the user is offline, but it is not getting triggered all the time, it is getting triggered sometimes only. can anyone suggest me how to push notification of incoming call when the user cleared the app from recent and will sinch actually run in the background?
public class SinchService extends Service {
private static final String APP_KEY = "key";
private static final String APP_SECRET = "secret";
private static final String ENVIRONMENT = "clientapi.sinch.com";
public static final String CALL_ID = "CALL_ID";
static final String TAG = SinchService.class.getSimpleName();
private SinchServiceInterface mSinchServiceInterface = new SinchServiceInterface();
private SinchClient mSinchClient;
private String mUserId;
static Context context;
private StartFailedListener mListener;
#Override
public void onCreate() {
super.onCreate();
}
/* #Override
public void onDestroy() {
if (mSinchClient != null && mSinchClient.isStarted()) {
mSinchClient.terminate();
}
super.onDestroy();
}*/
private void start(String userName,String fcm_token) {
if (mSinchClient == null) {
mUserId = userName;
/*LooperThread looperThread = new LooperThread();
looperThread.start();*/
/* new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
}
});*/
mSinchClient = Sinch.getSinchClientBuilder().context(getApplicationContext()).userId(mUserId)
.applicationKey(APP_KEY)
.applicationSecret(APP_SECRET)
.environmentHost(ENVIRONMENT)
.build();
//Log.d("OnMsg","coming after getSinchServiceInterface()");
mSinchClient.setSupportMessaging(true);
mSinchClient.setSupportCalling(true);
mSinchClient.setSupportManagedPush(true);
mSinchClient.setSupportPushNotifications(true);
mSinchClient.startListeningOnActiveConnection();
/* mSinchClient.startListeningOnActiveConnection();
mSinchClient.setSupportActiveConnectionInBackground(true);*/
// mSinchClient.setSupportActiveConnectionInBackground(true);
// mSinchClient.startListeningOnActiveConnection();
/* mSinchClient.setSupportManagedPush(true);
mSinchClient.setSupportPushNotifications(true);*/
// Log.d("fcm:","fcm token in bytes "+ fcm_token.getBytes());
mSinchClient.checkManifest();
mSinchClient.addSinchClientListener(new MySinchClientListener());
mSinchClient.getCallClient().addCallClientListener(new SinchCallClientListener());
mSinchClient.start();
// mSinchClient.registerPushNotificationData(fcm_token.getBytes());
}
}
class LooperThread extends Thread {
public Handler mHandler;
#Override
public void run() {
// Initialize the current thread as a Looper
// (this thread can have a MessageQueue now)
Looper.prepare();
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// process incoming messages here
/* mSinchClient.setSupportMessaging(true);
mSinchClient.setSupportCalling(true);
mSinchClient.setSupportManagedPush(true);
mSinchClient.setSupportPushNotifications(true);
mSinchClient.startListeningOnActiveConnection();
*//* mSinchClient.startListeningOnActiveConnection();
mSinchClient.setSupportActiveConnectionInBackground(true);*//*
// mSinchClient.setSupportActiveConnectionInBackground(true);
// mSinchClient.startListeningOnActiveConnection();
*//* mSinchClient.setSupportManagedPush(true);
mSinchClient.setSupportPushNotifications(true);*//*
// Log.d("fcm:","fcm token in bytes "+ fcm_token.getBytes());
mSinchClient.checkManifest();
mSinchClient.addSinchClientListener(new MySinchClientListener());
mSinchClient.getCallClient().addCallClientListener(new SinchCallClientListener());
mSinchClient.start();*/
}
};
// Run the message queue in this thread
Looper.loop();
}
}
private void stop() {
if (mSinchClient != null) {
mSinchClient.terminate();
mSinchClient = null;
}
}
private boolean isStarted() {
return (mSinchClient != null && mSinchClient.isStarted());
}
#Override
public IBinder onBind(Intent intent) {
return mSinchServiceInterface;
}
public class SinchServiceInterface extends Binder {
public Call callUserVideo(String userId) {
return mSinchClient.getCallClient().callUserVideo(userId);
}
public String getUserName() {
return mUserId;
}
public boolean isStarted() {
return SinchService.this.isStarted();
}
public void startClient(String userName,String token) {
start(userName,token);
}
public void stopClient() {
stop();
}
public void setStartListener(StartFailedListener listener) {
mListener = listener;
}
public Call getCall(String callId) {
return mSinchClient.getCallClient().getCall(callId);
}
public VideoController getVideoController() {
if (!isStarted()) {
return null;
}
return mSinchClient.getVideoController();
}
public AudioController getAudioController() {
if (!isStarted()) {
return null;
}
return mSinchClient.getAudioController();
}
}
public interface StartFailedListener {
void onStartFailed(SinchError error);
void onStarted();
}
private class MySinchClientListener implements SinchClientListener {
#Override
public void onClientFailed(SinchClient client, SinchError error) {
if (mListener != null) {
mListener.onStartFailed(error);
}
/* mSinchClient.terminate();
mSinchClient = null;*/
}
#Override
public void onClientStarted(SinchClient client) {
Log.d(TAG, "SinchClient started");
if (mListener != null) {
mListener.onStarted();
mSinchClient.startListeningOnActiveConnection();
}
}
#Override
public void onClientStopped(SinchClient client) {
Log.d(TAG, "SinchClient stopped");
}
#Override
public void onLogMessage(int level, String area, String message) {
switch (level) {
case Log.DEBUG:
Log.d(area, message);
break;
case Log.ERROR:
Log.e(area, message);
break;
case Log.INFO:
Log.i(area, message);
break;
case Log.VERBOSE:
Log.v(area, message);
break;
case Log.WARN:
Log.w(area, message);
break;
}
}
#Override
public void onRegistrationCredentialsRequired(SinchClient client,
ClientRegistration clientRegistration) {
}
}
public class SinchCallClientListener implements CallClientListener {
#Override
public void onIncomingCall(CallClient callClient, Call call) {
Log.d("OnMsg", "Incoming call");
Intent intent = new Intent(SinchService.this, IncomingCallScreenActivity.class);
intent.putExtra(CALL_ID, call.getCallId());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SinchService.this.startActivity(intent);
}
}
}
public class PlaceCallActivity extends BaseActivity implements SinchService.StartFailedListener/*,PushTokenRegistrationCallback*/{
private Button mCallButton;
private EditText mCallName;
Button stopButton;
String token;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//initializing UI elements
mCallName = findViewById(R.id.callName);
mCallButton = findViewById(R.id.callButton);
mCallButton.setEnabled(false);
mCallButton.setOnClickListener(buttonClickListener);
stopButton = findViewById(R.id.stopButton);
stopButton.setEnabled(false);
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w("test", "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
token = task.getResult().getToken();
// Log and toast
//String msg = getString(R.string.msg_token_fmt, token);
Log.d("test", token);
Toast.makeText(PlaceCallActivity.this, token, Toast.LENGTH_SHORT).show();
}
});
stopButton.setOnClickListener(buttonClickListener);
/* try {
#SuppressLint("WrongThread") String regId = FirebaseInstanceId.getInstance().getToken("Your-Sender-ID", "FCM");
} catch (IOException e) {
e.printStackTrace();
}*/
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
getSinchServiceInterface().startClient(new PreferenceUtils(PlaceCallActivity.this).getName(),token);
}
}, 4000);
}
// invoked when the connection with SinchServer is established
#Override
protected void onServiceConnected() {
TextView userName = (TextView) findViewById(R.id.loggedInName);
getSinchServiceInterface().setStartListener(this);
userName.setText(new PreferenceUtils(PlaceCallActivity.this).getName());
mCallButton.setEnabled(true);
stopButton.setEnabled(true);
}
/* #Override
public void onDestroy() {
if (getSinchServiceInterface() != null) {
getSinchServiceInterface().stopClient();
}
super.onDestroy();
}*/
/*//to kill the current session of SinchService
private void stopButtonClicked() {
if (getSinchServiceInterface() != null) {
getSinchServiceInterface().stopClient();
}
finish();
}*/
//to place the call to the entered name
private void callButtonClicked() {
String userName = mCallName.getText().toString();
if (userName.isEmpty()) {
Toast.makeText(this, "Please enter a user to call", Toast.LENGTH_LONG).show();
return;
}
Call call = getSinchServiceInterface().callUserVideo(userName);
String callId = call.getCallId();
Log.d("test","call id is"+callId);
Intent callScreen = new Intent(this, CallScreenActivity.class);
callScreen.putExtra(SinchService.CALL_ID, callId);
callScreen.putExtra("TOKEN", token);
startActivity(callScreen);
}
private OnClickListener buttonClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.callButton:
callButtonClicked();
break;
case R.id.stopButton:
// stopButtonClicked();
break;
}
}
};
#Override
public void onStartFailed(SinchError error) {
Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onStarted() {
}
}

kryonet client, send message to server without open a new connection

I'm saying i'm not a programmer but a guy who has been learning to program with java for a while. I hope to find the solution to my problem here. I'm trying to program my home automation system and remote control and to do this, I chose to use Kryonet. My problem is that every time I send the data to the server, the client opens a new connection. It's been 3 weeks since googlo and I try to figure out how to do it but with no results.
Every help is seriously appreciated. This is my code. Thank you.
This code work in my home network.
Sorry for my english...
public class MainActivity extends AppCompatActivity {
Button button;
String IP = "";
EditText editText;
TextView textView;
EditText editText3;
public static String msg_response;
public static String msg_request;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new MyHandler();
button = (Button) findViewById(R.id.button);
editText = (EditText) findViewById(R.id.editText);
editText3 = (EditText) findViewById(R.id.editText3);
textView = (TextView) findViewById(R.id.textView);
int MY_PERMISSIONS_REQUEST_INTERNET = 1;
int MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.INTERNET},
MY_PERMISSIONS_REQUEST_INTERNET);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_NETWORK_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE);
int MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_WIFI_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE);
textView.setText(msg_response);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
msg_request = valueOf(editText3.getText().toString());
} catch (Exception e) {
e.printStackTrace();
}
MyThread myThread = new MyThread(handler);
myThread.start();
}
});
}
private class MyHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
if (bundle.containsKey("msg da server")) {
String msgin = bundle.getString("msg da server");
textView.setText(msgin);
}
}
}
class MyThread extends Thread {
private Handler handler;
public MyThread(Handler handler) {
this.handler = handler;
}
public void run() {
System.out.println("MyThread running");
Client client = new Client();
client.start();
Kryo kryoClient = client.getKryo();
kryoClient.register(SampleRequest.class);
kryoClient.register(SampleResponse.class);
try {
client.connect(5000, "192.168.0.101", 54555, 54666);
} catch (IOException e) {
e.printStackTrace();
}
client.addListener(new Listener() {
public void received(Connection connection, Object object) {
if (object instanceof SampleResponse) {
SampleResponse response = (SampleResponse) object;
System.out.println(response.text);
msg_response = response.text.toString();
invia_activity(msg_response);
}
}
});
SampleRequest request = new SampleRequest();
request.text = msg_request;
client.sendTCP(request);
}
private void invia_activity(String invia) {
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("msg da server", "" + invia);
msg.setData(b);
handler.sendMessage(msg);
}
}
}
I dont have an direct solution, but i have an tutorial for it. I used the same one. So there the connections keeps open, and you can send as many packets as you need. Its without audio, but the code works well. After that you can experiment with the code. It works fine for me. This is the tutorial
I hope i can help you with this.
EDIT:
Maybe you can make an
public static Connection conn;
and you could use that object again and again as your connection to the server.

Android - Xamarin - Fused Location

I am trying to implement a custom activity that initialises the Fused Location services in Xamarin c# so I can reuse this activity whenever the Fused Location is needed. The problem that I am having is that the map is being loaded before the location services. This way, I cannot animate the camera to zoom in at the user's location since the location is still null.
Here is the custom activity:
using System;
using Android.App;
using Android.Gms.Common;
using Android.Gms.Common.Apis;
using Android.Gms.Maps.Model;
using Android.Locations;
using Android.OS;
using Android.Gms.Location;
using Android.Widget;
namespace Maps.Droid.LocationService {
public class LocationTrackerActivity : Activity, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Location.ILocationListener {
// Static Fields
public static long MIN_DISTANCE_CHANGE_FOR_UPDATES = 5; // 5 meters
public static long MIN_TIME_BW_UPDATES = 1000 * 10; // 10 seconds
private Location currentLocation;
private Activity activity;
private bool hasGooglePlayServices;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private bool locationAvailable = false;
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
this.activity = this;
hasGooglePlayServices = checkPlayServices();
if (hasGooglePlayServices) {
initFusedLocation();
} else {
initAndroidLocation();
}
}
private void initFusedLocation() {
mLocationRequest = new LocationRequest();
mLocationRequest.SetInterval(LocationTrackerActivity.MIN_TIME_BW_UPDATES);
mLocationRequest.SetFastestInterval(LocationTrackerActivity.MIN_TIME_BW_UPDATES / 2);
mLocationRequest.SetSmallestDisplacement(LocationTrackerActivity.MIN_DISTANCE_CHANGE_FOR_UPDATES);
mLocationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
mGoogleApiClient = new GoogleApiClient.Builder(Application.Context)
.AddConnectionCallbacks(this)
.AddOnConnectionFailedListener(this)
.AddApi(LocationServices.API)
.Build();
}
protected override void OnResume() {
base.OnResume();
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
protected override void OnPause() {
base.OnPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RemoveLocationUpdates(mGoogleApiClient, this);
}
}
protected override void OnStart() {
base.OnStart();
mGoogleApiClient.Connect();
}
protected override void OnStop() {
base.OnStop();
// only stop if it's connected, otherwise we crash
if (mGoogleApiClient != null) {
mGoogleApiClient.Disconnect();
}
}
private void initAndroidLocation() {
}
private bool checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.Instance;
int resultCode = apiAvailability.IsGooglePlayServicesAvailable(activity);
if (resultCode != ConnectionResult.Success) {
// In case we want to tell the user to install or update Google Play Services
//if (apiAvailability.IsUserResolvableError(resultCode)) {
// apiAvailability.GetErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST).Show();
//} else {
// Toast.MakeText(activity, "This device is not supported", ToastLength.Long).Show();
//}
return false;
}
return true; // has google play services installed
}
public double getLatitude() {
return currentLocation == null ? 0.0 : currentLocation.Latitude;
}
public double getLongitude() {
return currentLocation == null ? 0.0 : currentLocation.Longitude;
}
public bool canGetLocation() {
return locationAvailable;
}
public LatLng getLatLng() {
return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
}
public void OnConnected(Bundle connectionHint) {
// Get last known recent location. If the user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (currentLocation == null && mGoogleApiClient.IsConnected) {
currentLocation = LocationServices.FusedLocationApi.GetLastLocation(mGoogleApiClient);
}
Console.WriteLine("location is about to be set to true");
locationAvailable = true;
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
public void OnConnectionSuspended(int cause) {
// GoogleApiClient will automatically attempt to restore the connection.
// Applications should disable UI components that require the service, and wait for a call to onConnected(Bundle) to re-enable them
if (cause == GoogleApiClient.ConnectionCallbacks.CauseServiceDisconnected) {
Toast.MakeText(activity, "Location Services disconnected. Please re-connect.", ToastLength.Long).Show();
} else if (cause == GoogleApiClient.ConnectionCallbacks.CauseNetworkLost) {
Toast.MakeText(activity, "Network lost. Please re-connect.", ToastLength.Long).Show();
}
}
public void OnConnectionFailed(ConnectionResult result) {
Console.WriteLine("Connection failed: " + result.ToString());
}
public void OnLocationChanged(Location location) {
currentLocation = location;
}
}
}
Here is the class that inherit the custom class:
using Android.App;
using Android.OS;
using Maps.Droid.LocationService;
namespace Maps.Droid {
[Activity(Label = "Map Activity")]
public class MapActivity : LocationTrackerActivity {
// Properties
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.map_activity);
var mapFrag = new MapViewFragment();
var ft = FragmentManager.BeginTransaction();
ft.Add(Resource.Id.map_container, mapFrag);
ft.Commit();
}
}
}
Here is the fragment in the inherited activity:
using System;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Gms.Maps;
namespace Maps.Droid {
public class MapViewFragment : Fragment, IOnMapReadyCallback {
// private Activity activity;
private GoogleMap map;
private MapActivity parent;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.Inflate(Resource.Layout.map_fragment, null);
parent = ((MapActivity)Activity);
MapFragment frag = this.FragmentManager.FindFragmentById<MapFragment>(Resource.Id.map);
frag.GetMapAsync(this);
return view;
}
public void OnMapReady(GoogleMap googleMap) {
if (googleMap != null) {
map = googleMap;
var zoomVariance = 0.2;
var defaultZoom = 16f;
var currentZoomLevel = map.CameraPosition.Zoom;
map.MapType = GoogleMap.MapTypeNormal;
map.MyLocationEnabled = true;
map.CameraChange += delegate (object sender, GoogleMap.CameraChangeEventArgs e) {
if (Math.Abs(e.Position.Zoom - currentZoomLevel) < zoomVariance) {
return;
}
currentZoomLevel = e.Position.Zoom;
Console.WriteLine("Zooming " + currentZoomLevel);
};
map.UiSettings.ZoomControlsEnabled = true;
map.UiSettings.CompassEnabled = true;
map.UiSettings.SetAllGesturesEnabled(true); // Zoom, Tilt, Scroll, Rotate
if (parent.canGetLocation()) {
// ***** PROBLEM HERE ******* canGetLocation is set to true just afterwards.
map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(parent.getLatLng(), defaultZoom)); // Mosaic coordinates
}
}
}
}
}
I was thinking of implementing a call back to LocationTrackerActivity. So when the location services become available the class MapActivity then would be able to load the MapViewFragment within that custom callback. This way the location services would be loaded before the map. Therefore, this part of the code would always execute :
if (parent.canGetLocation()) {
// ***** PROBLEM HERE ******* canGetLocation is set to true just afterwards.
map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(parent.getLatLng(), defaultZoom)); // Mosaic coordinates
}
However I have no idea how to customise a callback. Maybe there are better solutions to this problem?
The problem can be because of OnConnected method. That's my OnConnected method for FusedLocationProvider in Xamarin. You can take a look on it.
public async void OnConnected(Bundle bundle)
{
Location location = LocationServices.FusedLocationApi.GetLastLocation(apiClient);
if (location != null)
{
latitude = location.Latitude;
longitude = location.Longitude;
locRequest.SetPriority(100);
locRequest.SetFastestInterval(500);
locRequest.SetInterval(1000);
await LocationServices.FusedLocationApi.RequestLocationUpdates(apiClient, locRequest, this);
}
}
When it is connected, i set the latitude and longitude values. Then in my onMapReady method, i create a new LatLng variable with these latitude and longitude variables.
void IOnMapReadyCallback.OnMapReady(GoogleMap myMap)
{
this.myMap = myMap;
myMarker = new MarkerOptions();
locCoordinates = new LatLng(latitude, longitude);
myMap.MapType = GoogleMap.MapTypeNormal;
myMap.UiSettings.ZoomControlsEnabled = true;
myMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(locCoordinates, 10));
}
UPDATE:
I have managed to find a solution. If the user has google play services then use FusedLocation Services, if the user does not then we use Android Location Services. Then we only have to interact with one object of the type LocationTracker and everything is done by this interface:
namespace Maps.Droid.LocationService {
public interface LocationInterface {
void startLocationServices();
void stopLocationServices();
void pauseLocationServices();
void resumeLocationServices();
double getLatitude();
double getLongitude();
bool canGetLocation();
}
}
using System;
using Android.App;
using Android.Gms.Location;
using Android.Gms.Common.Apis;
using Android.OS;
using Android.Gms.Maps.Model;
using Android.Widget;
using Android.Locations;
using Android.Gms.Common;
using Android.Gms.Maps;
namespace Maps.Droid.LocationService {
public class FusedLocation : Java.Lang.Object, GoogleApiClient.IConnectionCallbacks, GoogleApiClient.IOnConnectionFailedListener, Android.Gms.Location.ILocationListener {
private Activity activity;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location currentLocation;
private bool locationAvailable = false;
private GoogleMap map;
public FusedLocation(Activity activity) {
this.activity = activity;
mLocationRequest = new LocationRequest();
mLocationRequest.SetInterval(LocationTracker.MIN_TIME_BW_UPDATES);
mLocationRequest.SetFastestInterval(LocationTracker.MIN_TIME_BW_UPDATES / 2);
mLocationRequest.SetSmallestDisplacement(LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES);
mLocationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
mGoogleApiClient = new GoogleApiClient.Builder(Application.Context)
.AddConnectionCallbacks(this)
.AddOnConnectionFailedListener(this)
.AddApi(LocationServices.API)
.Build();
}
public Location getCurrentLocation() {
return currentLocation;
}
public void setMap(GoogleMap map) {
this.map = map;
}
public double getLatitude() {
return currentLocation.Latitude;
}
public double getLongitude() {
return currentLocation.Longitude;
}
public void OnResume() {
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
public void OnPause() {
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.IsConnected) {
LocationServices.FusedLocationApi.RemoveLocationUpdates(mGoogleApiClient, this);
}
}
public void OnStart() {
mGoogleApiClient?.Connect();
}
public void OnStop() {
// only stop if it's connected, otherwise we crash
if (mGoogleApiClient.IsConnected) {
mGoogleApiClient?.Disconnect();
}
}
public LatLng getLatLng() {
return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
}
public bool canGetLocation() {
return locationAvailable && currentLocation != null;
}
public void OnConnected(Bundle connectionHint) {
// Get last known recent location. If the user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
currentLocation = LocationServices.FusedLocationApi.GetLastLocation(mGoogleApiClient);
if (currentLocation != null) {
locationAvailable = true;
LocationServices.FusedLocationApi.RequestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
if (map != null) {
map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(getLatLng(), LocationTracker.DEFAULT_ZOOM));
}
}
}
public void OnConnectionSuspended(int cause) {
// GoogleApiClient will automatically attempt to restore the connection.
// Applications should disable UI components that require the service, and wait for a call to onConnected(Bundle) to re-enable them
if (cause == GoogleApiClient.ConnectionCallbacks.CauseServiceDisconnected) {
Toast.MakeText(activity, "Location Services disconnected. Please re-connect.", ToastLength.Long).Show();
} else if (cause == GoogleApiClient.ConnectionCallbacks.CauseNetworkLost) {
Toast.MakeText(activity, "Network lost. Please re-connect.", ToastLength.Long).Show();
}
}
public void OnLocationChanged(Location location) {
currentLocation = location;
}
public void OnConnectionFailed(ConnectionResult result) {
Console.WriteLine("Connection failed: " + result.ToString());
}
}
}
using System;
using Android.OS;
using Android.Locations;
using Android.Runtime;
using Android.App;
using Android.Content;
using Android.Widget;
using Android.Gms.Maps.Model;
using Java.Util.Concurrent;
namespace Maps.Droid.LocationService {
public class AndroidLocation : Java.Lang.Object, ILocationListener {
// Properties
private LocationManager locMgr;
private Activity activity;
private Location locationGPS, locationNetwork/*, locationPassive*/, currentLocation;
private bool locationAvailable = false;
private Android.Gms.Maps.GoogleMap map;
// UNCOMMNET
// private bool isPassiveEnabled = false; // Gets location from other apps that uses Location Services
// Initializer method (Constructor). Call this method onCreate
public AndroidLocation(Activity activity) {
this.activity = activity;
getLocation();
}
public Location getCurrentLocation() {
return currentLocation;
}
public void setMap(Android.Gms.Maps.GoogleMap map) {
this.map = map;
}
private Location getLocation() {
// Use Standard Android Location Service Provider
try {
locMgr = activity.GetSystemService(Context.LocationService) as LocationManager;
bool isGPSEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
// Varying precision, Less power consuming. Combination of WiFi and Cellular data
bool isNetworkEnabled = locMgr.IsProviderEnabled(LocationManager.NetworkProvider);
// UNCOMMENT
// bool isPassiveEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
// UNCOMMNET
//if (isPassiveEnabled) {
// locMgr.RequestLocationUpdates(LocationManager.PassiveProvider, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
// locationPassive = locMgr.GetLastKnownLocation(LocationManager.PassiveProvider);
//}
if (isGPSEnabled) {
locMgr.RequestLocationUpdates(LocationManager.GpsProvider, LocationTracker.MIN_TIME_BW_UPDATES, LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
locationGPS = locMgr?.GetLastKnownLocation(LocationManager.GpsProvider);
}
if (isNetworkEnabled) {
locMgr.RequestLocationUpdates(LocationManager.NetworkProvider, LocationTracker.MIN_TIME_BW_UPDATES, LocationTracker.MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
locationNetwork = locMgr?.GetLastKnownLocation(LocationManager.NetworkProvider);
}
// UNCOMMENT - Method must be implement if PassiveLocation is to be used
// currentLocation = getBestLocation(locationGPS, locationNetwork, locationPassive);
currentLocation = getBestLocation(locationNetwork, locationGPS);
if (currentLocation != null) {
locationAvailable = true;
if (map != null) {
map.AnimateCamera(Android.Gms.Maps.CameraUpdateFactory.NewLatLngZoom(getLatLng(), LocationTracker.DEFAULT_ZOOM));
}
}
} catch (Exception e) {
Console.WriteLine("ERROR: getLocation() " + e.ToString());
}
return currentLocation;
}
// Determines the most recent and/or most accurate location
private Location getBestLocation(Location loc1, Location loc2) {
if (loc1 == null || loc2 == null) {
return loc1 ?? loc2; // If either location is null then return the not null location
}
long time1 = TimeUnit.Milliseconds.ToSeconds(loc1.Time);
long time2 = TimeUnit.Milliseconds.ToSeconds(loc2.Time);
long twiceUpdate = (LocationTracker.MIN_TIME_BW_UPDATES / 1000) * 2;
if (Math.Abs(time1 - time2) > twiceUpdate) { // If location times are more than twiceUpdate apart
if (time1 > time2) { // More time value, most current time
return loc1;
} else {
return loc2;
}
} else {
float accuracy1 = loc1.Accuracy;
float accuracy2 = loc2.Accuracy;
// Smaller the value (meters), the greater the accuracy
if (accuracy1 < accuracy2) {
return loc1;
} else {
return loc2;
}
}
}
public void OnStop() {
locMgr = null;
}
public void OnPause() {
locMgr?.RemoveUpdates(this);
}
public void OnStart() {
}
public void OnResume() {
if (locMgr == null || currentLocation == null) {
getLocation();
}
}
public bool canGetLocation() {
return locationAvailable;
}
public LatLng getLatLng() {
return new LatLng(currentLocation.Latitude, currentLocation.Longitude);
}
public double getLatitude() {
return currentLocation.Latitude;
}
public double getLongitude() {
return currentLocation.Longitude;
}
public void OnLocationChanged(Location location) {
currentLocation = getBestLocation(currentLocation, location);
}
// User disabled a provider
public void OnProviderDisabled(string provider) {
getLocation(); // Check if all providers are disabled and pop up alertDialog if they are so
}
// User enabled a provider
public void OnProviderEnabled(string provider) {
getLocation(); // Update all available providers for getting the best provider available
}
public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras) {
}
}
}
using Android.App;
using Android.Gms.Common;
using Android.Gms.Common.Apis;
using Android.Gms.Maps.Model;
using Android.Gms.Maps;
using Android.Locations;
using Android.Content;
using Android.Widget;
namespace Maps.Droid.LocationService {
public class LocationTracker {
public static long MIN_DISTANCE_CHANGE_FOR_UPDATES = 5; // 5 meters
public static long MIN_TIME_BW_UPDATES = 1000 * 15; // 15 seconds ok, 5 seconds really fast, 30s slow
public static float DEFAULT_ZOOM = 16f;
private bool hasGooglePlayServices;
public GoogleApiClient mGoogleApiClient;
private FusedLocation fusedLocation;
private AndroidLocation androidLocation;
private bool locationIsDisabled;
public LocationTracker(Activity activity) {
if (locationIsDisabled = isLocationDisabled(activity)) {
showSettingsAlert(activity);
} else {
hasGooglePlayServices = checkPlayServices(activity);
if (hasGooglePlayServices) {
fusedLocation = new FusedLocation(activity);
} else {
androidLocation = new AndroidLocation(activity);
}
}
}
private void showSettingsAlert(Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.SetTitle("Location Services Not Active");
builder.SetMessage("Please enable Location Services and GPS");
builder.SetPositiveButton("OK", delegate {
// Show location settings when the user acknowledges the alert dialog
var intent = new Intent(Android.Provider.Settings.ActionLocationSourceSettings);
activity.StartActivity(intent);
});
builder.SetNegativeButton("Cancel", delegate {
Toast.MakeText(activity, "Location disabled by user", ToastLength.Short).Show();
});
AlertDialog alertDialog = builder.Create();
alertDialog.SetCanceledOnTouchOutside(false);
alertDialog.Show();
}
private bool isLocationDisabled(Activity activity) {
LocationManager locMgr = activity.GetSystemService(Context.LocationService) as LocationManager;
// More precise, More power consuming
bool isGPSEnabled = locMgr.IsProviderEnabled(LocationManager.GpsProvider);
// Varying precision, Less power consuming. Combination of WiFi and Cellular data
bool isNetworkEnabled = locMgr.IsProviderEnabled(LocationManager.NetworkProvider);
// UNCOMMENT
// bool isPassiveEnabled = locMgr.IsProviderEnabled(LocationManager.PassiveProvider);
// UNCOMMENT
// return !isGPSEnabled && !isNetworkEnabled && !isPassiveEnabled; // True only when the 3 location services are disabled
return !isGPSEnabled && !isNetworkEnabled; // True only when both location services are disabled
}
// Call this method at OnMapReady callback if initial zooming/animation on user's location is desired
public void setMap(GoogleMap map) {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.setMap(map);
} else {
androidLocation.setMap(map);
}
}
public void OnResume() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnResume();
} else {
androidLocation.OnResume();
}
}
public void OnPause() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnPause();
} else {
androidLocation.OnPause();
}
}
public void OnStart() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnStart();
} else {
androidLocation.OnStart();
}
}
public void OnStop() {
if (locationIsDisabled) {
return;
}
if (hasGooglePlayServices) {
fusedLocation.OnStop();
} else {
androidLocation.OnStop();
}
}
private bool checkPlayServices(Activity activity) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.Instance;
int resultCode = apiAvailability.IsGooglePlayServicesAvailable(activity);
if (resultCode == ConnectionResult.Success) {
return true;
}
return false;
}
public double getLatitude() {
if (locationIsDisabled) {
return 0;
}
if (hasGooglePlayServices) {
return fusedLocation.getCurrentLocation() == null ? 0.0 : fusedLocation.getLatitude();
} else {
return androidLocation.getCurrentLocation() == null ? 0.0 : androidLocation.getLatitude();
}
}
public double getLongitude() {
if (locationIsDisabled) {
return 0;
}
if (hasGooglePlayServices) {
return fusedLocation.getCurrentLocation() == null ? 0.0 : fusedLocation.getLongitude();
} else {
return androidLocation.getCurrentLocation() == null ? 0.0 : androidLocation.getLongitude();
}
}
public bool canGetLocation() {
if (locationIsDisabled) {
return false;
}
if (hasGooglePlayServices) {
return fusedLocation.canGetLocation();
} else {
return androidLocation.canGetLocation();
}
}
public LatLng getLatLng() {
if (locationIsDisabled) {
return null;
}
LatLng latlng;
if (hasGooglePlayServices) {
latlng = fusedLocation.getLatLng();
} else {
latlng = androidLocation.getLatLng();
}
return latlng;
}
public Location getCurrentLocation() {
if (hasGooglePlayServices) {
return fusedLocation.getCurrentLocation();
} else {
return androidLocation.getCurrentLocation();
}
}
}
}
Then to use it on your fragment or activity:
Initialise it at OnCreate:
Location tracker = new LocationTracker(this.Activity);
make a referent for the life cycles:
public override void OnResume() {
base.OnResume();
tracker.OnResume();
}
public override void OnPause() {
base.OnPause();
tracker.OnPause();
}
public override void OnStart() {
base.OnStart();
tracker.OnStart();
}
public override void OnStop() {
base.OnStop();
tracker.OnStop();
}
if you want the animation to zoom at the users location in the beginning, then you have to add this line of code when you have the googlemap:
tracker.setMap(googleMap); // Invoke this method if zooming/animating to the user's location is desired
Spent many days on this solution. Hope it can help somebody!

Questions about android-beacon-library's scan-period

I have a problem about scan-period when i'm using android-beacon-library. And here is my problem:
I have three main class: MainActivity, BaseService and BeaconService.
MainActivity: Just do startForeground and stopForeground operation.
BaseService: Do some parameters initialization, BeaconManager and so on.
BeaconService: Beacon operation.
I describe my problems first. I’m using a foreground service to do scan operation and the backgroundScanPeriod is 20l. And i also have a MainActivity with two buttons, startService and stopService. The scan-period is 10s when First time i open the app and click startService.
And then i click HOME and kill this app the service is running normal and the scan-period is 10s also. But when i re-open MainActivity by click the notification on the picture.
The scan-period will become 1s. It's fast for me. But the scan-period would become normal if i click HOME again. That means, the scan-period will become very fast every time except the first time i open the MainActivity.
I wanna know why. And here is my important code below:
MainActivity.class
#OnClick(R.id.start_service)
void start_Service() {
if (Utils.isServiceRunning(MainActivity.this, Constants.CLASSNAME)) {
Toast.makeText(this, "service is running, don't start again", Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent(MainActivity.this, BeaconService.class);
intent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(intent);
setInfo();
}
}
#OnClick(R.id.stop_service)
void stop_Service() {
if (Utils.isServiceRunning(MainActivity.this, Constants.CLASSNAME)) {
Intent intent = new Intent(MainActivity.this, BeaconService.class);
intent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
startService(intent);
setInfo();
} else {
Toast.makeText(this, "service is dead, don't kill again", Toast.LENGTH_SHORT).show();
}
}
BaseService.class
private void setBeaconManager() {
beaconManager.setBackgroundBetweenScanPeriod(20l);
beaconManager.setBackgroundMode(true);
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(Constants.BEACON_LAYOUT.COMMON_LAYOUT));
}
BeaconService.class
public class BeaconService extends BaseService implements BootstrapNotifier, BeaconConsumer {
private static final int NOTIFICATION = R.string.notify_service_started;
private static final String TAG = "BeaconService";
private int size = -1;
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private Beacon beacon;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
regionBootstrap = new RegionBootstrap(this, region);
beaconManager.bind(this);
backgroundPowerSaver = new BackgroundPowerSaver(getApplicationContext());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getAction() != null) {
switch (intent.getAction()) {
case Constants.ACTION.STARTFOREGROUND_ACTION:
startForeground(NOTIFICATION, getNotification());
break;
case Constants.ACTION.STOPFOREGROUND_ACTION:
Log.d(TAG, "Received stop foreground request");
stopForeground(true);
stopSelf();
break;
}
}
return START_STICKY;
}
#Override
public void onDestroy() {
beaconManager.unbind(this);
regionBootstrap.disable();
Log.d(TAG, "service onDestroy");
}
/**
* Called when at least one beacon in a Region is visible.
*
* #param region region
*/
#Override
public void didEnterRegion(Region region) {
// TODO: 3/8/16 reload all the resource
Log.d(TAG, "didEnterRegion called");
L.object(region);
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
* Called when no beacons in a Region are visible.
*
* #param region region
*/
#Override
public void didExitRegion(Region region) {
// TODO: 3/8/16 close all the resource
Log.d(TAG, "didExitRegion called");
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
beaconManager.unbind(this);
regionBootstrap.disable();
L.object(region);
}
/**
* Called with a state value of MonitorNotifier.INSIDE when at least one beacon in a Region is visible
*
* #param region region
*/
#Override
public void didDetermineStateForRegion(int i, Region region) {
Log.d(TAG, "switch from seeing/not seeing beacons");
L.object(region);
}
#Override
public void onBeaconServiceConnect() {
Log.d(TAG, "onBeaconServiceConnect");
if (null == beaconManager.getRangingNotifier()) {
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
Log.d(TAG, "beacons.size():" + beacons.size() + "," + this);
if (beacons.size() != 0) {
Iterator<Beacon> iterator = beacons.iterator();
if (beacons.size() != size) {
saveBeacon(iterator);
size = beacons.size();
}
}
}
});
}
}
/**
* Save beacon p-o-j-o to SQLite.
*/
private void saveBeacon(Iterator<Beacon> iterator) {
while (iterator.hasNext()) {
beacon = iterator.next();
L.object(beacon);
entity.setId(null);
entity.setUuid(beacon.getId1().toString());
entity.setMajor(beacon.getId2().toString());
entity.setMinor(beacon.getId3().toString());
entity.setTxpower(beacon.getTxPower());
entity.setTime(Utils.getCurrentTime());
dbHelper.provideNinjaDao().insert(entity);
Log.d(TAG, "sql save success");
}
}
private Notification getNotification() {
CharSequence text = getText(R.string.notify_service_started);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ninja_turtle)
.setTicker(text)
.setWhen(System.currentTimeMillis())
.setContentTitle(getText(R.string.info_service))
.setContentText(text)
.setContentIntent(contentIntent)
.build();
return notification;
}
}
Hope you guys can help me. Thanks in advance.
A few points:
There are two different sets of settings for scan period using the Android Beacon Library, foreground and background. When using the BackgroundPowerSaver as shown in the code, the Android Beacon Library automatically switches back and forth between the foreground scan period and the background scan period.
When using the BackgroundPowerSaver, manually setting beaconManager.setBackgroundMode(true) will only have an effect until the next time the app cycles to the foreground -- the BackgroundPowerSaver will change the value of this setting automatically.
The units of the scan periods is milliseconds. So setting beaconManager.setBackgroundBetweenScanPeriod(20l); sets the scan period to be 20 milliseconds. This is way too short to pick up beacons reliably. I recommend a minimum scan period of 1100 ms. The longer the period, the higher probability of detecting a beacon, but the more battery is used.
If you want to wait 10 seconds between scans, you want to set: beaconManager.setBackgroundBetweenScanPeriod(10000l); // 10000 ms = 10.0 secs
If you want the same scan periods to apply both in the foreground and background, simply set them to be the same:
beaconManager.setBackgroundBetweenScanPeriod(10000l);
beaconManager.setForegroundBetweenScanPeriod(10000l);
beaconManager.setBackgroundScanPeriod(1100l);
beaconManager.setForegroundScanPeriod(1100l);

How do I get to load image in J2ME?

I am using TimerTask and ImageLoader class to load n image to an image item.
public class Imageloader implements Runnable{
private ImageItem item=null;
private String url=null;
/*
* initializes the imageItem
*/
public Imageloader(ImageItem item,String url){
this.item=item;
this.url=url;
}
private Image getImage(String url) throws IOException {
item.setLabel(item.getLabel()+12);
System.out.println("Test 5");
HttpConnection connection = null;
DataInputStream inp = null;
int length;
byte[] data;
try {System.out.println("Test 6");
connection = (HttpConnection) Connector.open(url);
item.setLabel(item.getLabel()+13);
connection.getResponseMessage();
System.out.println("Test 7");
length = (int) connection.getLength();
item.setLabel(item.getLabel()+14);
System.out.println("Length is "+length);
System.out.println("Test 8");
data = new byte[length];
inp = new DataInputStream(connection.openInputStream());
item.setLabel(item.getLabel()+15);
System.out.println("Test 9");
inp.readFully(data);
item.setLabel(item.getLabel()+16);
System.out.println("Test 10");
return Image.createImage(data, 0, data.length);
}
finally {
if (connection != null) connection.close();
if (inp != null)inp.close();
}
}
public void run() {
System.out.println("Test 1");
Image image=null;
try{
if (url!=null){
System.out.println("Test 2");
image=getImage(url);
System.out.println("Test 3");
item.setImage(image);
item.setLabel(item.getLabel()+17);
System.out.println("Test 4");
}
else{
item.setAltText("Map address specified is incorrect");
}
}
catch(IOException e){
item.setAltText("Map cannot be loaded now");
}
}
}
public class MapTimer extends TimerTask{
DatagramConnection connection=null;
String message=null;
Imageloader imageretriever;
ImageItem item=null;
MapTimer (DatagramConnection connection,String message,ImageItem Img_map ){
this.connection=connection;
this.message=message;
this.item=Img_map;
item.setLabel(item.getLabel()+1);
System.out.println("Map is initizlized...");
}
public void run() {
System.out.println("Map starting...");
item.setLabel(item.getLabel()+2);
String serverquery=null;
try {
item.setLabel(item.getLabel()+3);
sendMessage(message);
item.setLabel(item.getLabel()+4);
//serverquery=receiveMessage() ;
item.setLabel(item.getLabel()+5);
//item.setLabel(" Loading...." );
//formatmessage(serverquery);
String url="http://maps.google.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=14&size=512x512&maptype=roadmap"+
"&markers=color:blue|label:S|40.702147,-74.015794&markers=color:green|label:G|40.711614,-74.012318"+
"&markers=color:red|color:red|label:C|40.718217,-73.998284&sensor=false";
Imageloader Im=new Imageloader(item,url);
item.setLabel(item.getLabel()+6);
(new Thread(Im)).start();
item.setLabel(item.getLabel()+7);
System.out.println("server map query is::: "+serverquery);
} catch (IOException ex) {
System.out.println("Error2"+ex);
}
catch(Exception e){
System.out.println("Error3"+e);
}
}
/*
* Sends a message via UDP to server
*/
private void sendMessage(String message) throws IOException{
Datagram packet_send=null;
if (connection != null){
byte[] packetsenddata=message.getBytes();
packet_send = connection.newDatagram(packetsenddata,packetsenddata.length);
connection.send(packet_send);
packet_send = null;
}
}
}
This is how I set the Timer;
MapTimer maptimer=new MapTimer (connection,mapquery ,Img_map );
Timer timer=new Timer();
timer.schedule(maptimer, 5000, 100000);
It's working fine with the enulator but as I deploy it on my mob,the image is not loading..
The image label is somewhat like Stopping 234567234567 which implies that my timer is running fine. It is not entering the ImageLoader class... How do get to load this image?
This is difficult to say without further debuggind. I recommend you to use Micrologger + a web server, in order to debug your midlets on the device.
Looking to your code, I suspect of this line length = (int) connection.getLength();. Could it fail on Nokia's IO library implementation?

Resources