I am trying to play around with Beacons and I have got this code:
By following this tutorial:
Activity2.java
public class Activity2 extends AppCompatActivity {
//String myString = MyViewClass.infoToPass;
public static final String TAG = "Airport";
TextView tvFooter;
private static final Map<String, List<String>> PLACES_BY_BEACONS;
// TODO: replace "<major>:<minor>" strings to match your own beacons.
static {
Map<String, List<String>> placesByBeacons = new HashMap<>();
placesByBeacons.put("22504:48827", new ArrayList<String>() {{
add("Heavenly Sandwiches");
// read as: "Heavenly Sandwiches" is closest
// to the beacon with major 22504 and minor 48827
add("Green & Green Salads");
// "Green & Green Salads" is the next closest
add("Mini Panini");
// "Mini Panini" is the furthest away
}});
placesByBeacons.put("648:12", new ArrayList<String>() {{
add("Mini Panini");
add("Green & Green Salads");
add("Heavenly Sandwiches");
}});
PLACES_BY_BEACONS = Collections.unmodifiableMap(placesByBeacons);
}
private List<String> placesNearBeacon(Beacon beacon) {
String beaconKey = String.format("%d:%d", beacon.getMajor(), beacon.getMinor());
if (PLACES_BY_BEACONS.containsKey(beaconKey)) {
return PLACES_BY_BEACONS.get(beaconKey);
}
return Collections.emptyList();
}
private BeaconManager beaconManager;
private Region region;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
//updateCordinate("Just some random text");
Log.d(TAG, "onCreate");
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region region, List<Beacon> list) {
Log.d(TAG, "onBeaconsDiscovered");
if (!list.isEmpty()) {
Beacon nearestBeacon = list.get(0);
List<String> places = placesNearBeacon(nearestBeacon);
// TODO: update the UI here
Log.d(TAG, "Nearest places: " + places);
}
else{
// this line is not executing
Log.d(TAG, "You are not in area of beacons");
}
}
});
region = new Region("ranged region", UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null);
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
SystemRequirementsChecker.checkWithDefaultDialogs(this);
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
Log.d(TAG, "onServiceReady");
beaconManager.startRanging(region);
}
});
}
#Override
protected void onPause() {
beaconManager.stopRanging(region);
Log.d(TAG, "onPause");
super.onPause();
}
//public void updateCordinate(String text1) {
// tvFooter = (TextView) findViewById(R.id.tvFooter);
// tvFooter.setText("Location is :" + myString);
// }
}
Now what I want it:
If I don't have any Beacons around me, I want to check for it and store that value in some variable so that I can use it in other class (non-activity class).
Also how do I check for range from it? (I know it's beyond the scope of this question but little idea will be welcomed)
//you may ignore the notification code, for my usage of Beacons in my app, i
//to send notification to my app even through the app is not open when a beacon //is in/out range.
public class EstimoteService extends Service implements BeaconManager.RangingListener, BeaconManager.MonitoringListener {
private static final int NOTIFICATION_ID = 123;
private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("regionId", null, null, null);
private Beacon beaconFound;
private NotificationManager notificationManager;
private BeaconManager beaconManager;
#Override
public void onCreate() {
super.onCreate();
initResources();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
notificationManager.cancel(NOTIFICATION_ID);
// Default values are 5s of scanning and 25s of waiting time to save CPU cycles.
// In order for this demo to be more responsive and immediate we lower down those values.
beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0);
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
return START_NOT_STICKY;
}
private void initResources() {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(this);
beaconManager.setMonitoringListener(this);
}
#Override
public void onBeaconsDiscovered(Region region, List<Beacon> beacons) {
if (beaconFound == null) {
// Get the first available beaconFound
if (beacons.isEmpty())
return;
beaconFound = beacons.get(0);
final Region beaconRegion = new Region("regionId", beaconFound.getProximityUUID(), beaconFound.getMajor(), beaconFound.getMinor());
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startMonitoring(beaconRegion);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public void onEnteredRegion(Region region, List<Beacon> beacons) {
postNotification("Entered region");
System.out.println("---> enter region");
}
#Override
public void onExitedRegion(Region region) {
postNotification("Exited region");
System.out.println("---> exit region");
}
private void postNotification(String msg) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.beacon_gray).setContentTitle("XXX").setContentText(msg);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
}
Related
I am using altbeacon for android and i cant't detect my beacon. I have tried https://github.com/AltBeacon/android-beacon-library-reference sample code also but can't detect beacon. Here is my code:
public class BeaconApplication extends Application implements BootstrapNotifier {
private Region region;
private RegionBootstrap regionBootstrap;
private BeaconManager beaconManager;
#Override
public void onCreate() {
super.onCreate();
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setBackgroundScanPeriod(5000);
beaconManager.setBackgroundBetweenScanPeriod(10000);
region = new Region("backgroundRegion",
Identifier.parse("EBEFD083-70A2-47C8-9837-E7B5634DF524"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
Log.i("selfBeacon", "Bootstrap created");
}
#Override
public void didEnterRegion(Region region) {
Log.i("selfBeacon", "Bootstrap didEnterRegion");
regionBootstrap.disable();
Intent intent = new Intent(this, SelfBeaconService.class);
if (Build.VERSION.SDK_INT >= 26) {
startForegroundService(intent);
} else {
startService(intent);
}
Log.i("selfBeacon", "Service start commanded");
}
#Override
public void didExitRegion(Region region) {
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
public void resumeScanning () {
beaconManager.setBackgroundScanPeriod(5000);
beaconManager.setBackgroundBetweenScanPeriod(10000);
regionBootstrap = new RegionBootstrap(this, region);
Log.i("selfBeacon", "scanning resumed");
}
}
public class SelfBeaconService extends Service implements BeaconConsumer {
private BeaconManager beaconManager;
private Region region;
private int noBeaconDetectedCount = 0;
#Override
public void onCreate() {
super.onCreate();
Log.i("selfBeaconService", "onCreate");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("selfBeaconService", "onStartCommand");
broadcastSystemLog("Beacon Service onCreate triggered.");
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.setEnableScheduledScanJobs(false); //Stop scanning
beaconManager.setForegroundScanPeriod(2000);
beaconManager.setForegroundBetweenScanPeriod(2000);
beaconManager.bind(this);
region = new Region("foreground region",
Identifier.parse("EBEFD083-70A2-47C8-9837-E7B5634DF524"), null, null);
startForeground();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onBeaconServiceConnect() {
Log.i("selfBeaconService", "onBeaconServiceConnect");
broadcastSystemLog("onBeaconServiceConnect triggered.");
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
if (collection.size() > 0) {
noBeaconDetectedCount = 0;
double closestDistance = -1;
for (Beacon each : collection) {
if (closestDistance == -1) {
closestDistance = each.getDistance();
} else if (each.getDistance() < closestDistance) {
closestDistance = each.getDistance();
}
}
Log.i("selfBeaconService", "didRangeBeaconsInRegion, the closest beacon is about " +
closestDistance + " meters away.");
broadcastToActivity("The closest beacon is about " +
closestDistance + " meters away.");
} else {
noBeaconDetectedCount++;
broadcastToActivity("No beacon has been detected for " + noBeaconDetectedCount + " times");
if (noBeaconDetectedCount > 10) { //10*(2000ms+2000ms) = 40 seconds
stopForeground(true);
terminate();
}
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void onDestroy() {
Log.i("selfBeacon", "onDestroy");
broadcastSystemLog("BeaconService onDestroy triggered.");
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void broadcastToActivity (String message) {
Intent intent = new Intent();
intent.setAction("beaconBroadcast");
intent.putExtra("beaconService", message);
sendBroadcast(intent);
}
private void broadcastSystemLog (String message) {
Intent intent = new Intent();
intent.setAction("beaconBroadcast");
intent.putExtra("beaconServiceLog", message);
sendBroadcast(intent);
}
private void startForeground () {
NotificationCompat.Builder notificationBuilder = null;
Notification notification = null;
if (Build.VERSION.SDK_INT >= 26) {
notificationBuilder = new NotificationCompat.Builder(this, "rangingService")
.setContentTitle("Active Scanning")
.setContentText("App is scanning for nearby beacons");
notification = notificationBuilder.build();
} else {
notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle("Active Scanning")
.setContentText("App is scanning for nearby beacons");
notification = notificationBuilder.build();
}
startForeground(1234, notification);
}
private void terminate () {
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
beaconManager.removeAllRangeNotifiers();
beaconManager.unbind(this);
beaconManager.setEnableScheduledScanJobs(true);
((BeaconApplication)getApplication()).resumeScanning();
stopSelf();
Log.i("selfBeaconService", "service stopped");
broadcastSystemLog("BeaconSevice stopped.");
}
}
A few things to check:
Ensure you have added code to dynamically request location permission at runtime. See here for how to do that.
After adding the above, make sure this permission has been properly obtained. Go to. Settings->Apps->{your app name}->Permissions to see
Make sure Bluetooth and Location are enabled on your phone.
If you have checked all of the above and it still does not work, try an off the shelf beacon detector like BeaconScope. If it does not detect, there may be a problem with either your phone hardware or your beacon hardware.
I am using AltBeacon Library. I want to scan beacon in 5 min and 1 sec like that. My code not scanning properly on first time and second time scanning properly. please help me?
//this is my fragment class
public class LocationIdFragment extends Fragment {
#Override
public void onStart() {
super.onStart();
Intent intent = new Intent(getActivity(), SimpleService.class);
getActivity().getApplicationContext().startService(intent);
}
#Override
public void onResume() {
super.onResume();
Intent intent = new Intent(getActivity(), SimpleService.class);
getActivity().getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
public void onPause() {
super.onPause();
getActivity().getApplicationContext().unbindService(mConnection);
mBound = false;
}
#Override
public void onStop() {
super.onStop();
Intent intent = new Intent(getActivity(), SimpleService.class);
getActivity().getApplicationContext().stopService(intent);
}
}
//this is my service class
public class SimpleService extends Service implements BeaconConsumer {
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
#Override
public void onCreate() {
super.onCreate();
beaconManager = BeaconManager.getInstanceForApplication(getBaseContext());
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setForegroundScanPeriod(1000);//this is not scanning properly
beaconManager.setBackgroundScanPeriod(1000);
beaconManager.setForegroundBetweenScanPeriod(301000);
beaconManager.setBackgroundBetweenScanPeriod(301000);
beaconManager.bind(SimpleService.this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
try {
// Unbind scan beacon progress
if (beaconManager != null) {
beaconManager.unbind(SimpleService.this);
beaconManager.stopRangingBeaconsInRegion(new Region("sBeacon", null, null, null));
}
} catch (Exception e) {
e.printStackTrace();
}
super.onDestroy();
}
#Override
public void onBeaconServiceConnect() {
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
beacon = beacons.iterator().next();
getMajor = beacon.getId2().toString();//here i'm getting data
getMinor = beacon.getId3().toString();
beaconID = getMajor + "-" + getMinor;
DateFormat df = new SimpleDateFormat("dd-MM-yyyy/hh:mm:ss.mmm");// i'm getting different time
String sDate = df.format(Calendar.getInstance().getTime());
String[] sDateTime = sDate.split("/");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("sBeacon", null, null, null));
Log.i(TAG, "*** startRangingBeaconsInRegion ***");
Logger.info(" LocationIdFragment : Start Ranging BeaconsInRegion ");
} catch (RemoteException e) {
Log.i(TAG, "RemoteException: " + e);
}
}
}
I am developing an app that connects to a Chromecast, everything works fine when I do it from one activity, the problem is, that I want that activity to be fullscreen with no action bar, and no soft buttons. I am achiving that, hiding them when the users connects to the Chromecast, but it would be better if the users connect from the first activity (with action bar) and then goes to the second activity and the magic occurs there. But I can't pass the session between the activities. I have follow this tutorial to make the communication with the chromecast but tried to change a little to make the 2 acitivites communication.
Of course I have tested it and it returns a NullPointerException.
ConnectionFailedListener.java
public class ConnectionFailedListener implements GoogleApiClient.OnConnectionFailedListener {
private String TAG;
private MyConnectionCallbacks myConnectionCB;
public ConnectionFailedListener(String _TAG)
{
this.TAG=_TAG;
}
private void setMyConnectionCallBack(MyConnectionCallbacks _ConnectionCallbacks)
{
this.myConnectionCB = _ConnectionCallbacks;
}
#Override
public void onConnectionFailed(ConnectionResult result)
{
Log.e(TAG, "onConnectionFailed ");
myConnectionCB.teardown();
}
}
Channel.java
public class EventChannel implements Cast.MessageReceivedCallback
{
private Context myContext;
private String TAG;
/**
* #return custom namespace
*/
public EventChannel(Context _context, String _TAG)
{
this.myContext = _context;
this.TAG = _TAG;
}
public String getNamespace()
{
return myContext.getString(R.string.namespace);
}
/*
* Receive message from the receiver app
*/
#Override
public void onMessageReceived(CastDevice castDevice, String namespace,String message)
{
Log.d(TAG, "onMessageReceived: " + message);
}
}
ConnectionCallbacks.java
public class MyConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks
{
private String TAG;
private Context myContext;
public CastDevice mSelectedDevice;
private GoogleApiClient mApiClient;
private boolean mWaitingForReconnect;
private EventChannel mEventChannel;
private String mSessionId;
private boolean mApplicationStarted;
private EventChannel myChannel;
public MyConnectionCallbacks(Context _context, String _TAG)
{
this.myContext=_context;
this.TAG = _TAG;
}
public void setApiClient(GoogleApiClient _newApiClient)
{
this.mApiClient = _newApiClient;
}
#Override
public void onConnected(Bundle connectionHint)
{
Log.d(TAG, "onConnected");
if (mApiClient == null)
{
// We got disconnected while this runnable was pending execution.
return;
}
try
{
if (mWaitingForReconnect)
{
mWaitingForReconnect = false;
// Check if the receiver app is still running
if ((connectionHint != null) && connectionHint.getBoolean(Cast.EXTRA_APP_NO_LONGER_RUNNING))
{
Log.d(TAG, "App is no longer running");
teardown();
}
else
{// Re-create the custom message channel
try
{
Cast.CastApi.setMessageReceivedCallbacks(mApiClient,mEventChannel.getNamespace(),mEventChannel);
}
catch (IOException e)
{
Log.e(TAG, "Exception while creating channel", e);
}
}
}
else
{// Launch the receiver app because is connected
Cast.CastApi.launchApplication(mApiClient,myContext.getString(R.string.app_id), false).setResultCallback(
new ResultCallback<Cast.ApplicationConnectionResult>()
{
#Override
public void onResult(Cast.ApplicationConnectionResult result) {
Status status = result.getStatus();
Log.d(TAG,"ApplicationConnectionResultCallback.onResult: statusCode"+ status.getStatusCode());
if (status.isSuccess())
{
ApplicationMetadata applicationMetadata = result.getApplicationMetadata();
mSessionId = result.getSessionId();
String applicationStatus = result.getApplicationStatus();
boolean wasLaunched = result.getWasLaunched();
Log.d(TAG,"application name: "+ applicationMetadata.getName()
+ ", status: "+ applicationStatus
+ ", sessionId: "+ mSessionId
+ ", wasLaunched: "+ wasLaunched);
mApplicationStarted = true;
// Create the custom message channel
mEventChannel = new EventChannel(myContext,TAG);
try
{
Cast.CastApi.setMessageReceivedCallbacks(mApiClient,mEventChannel.getNamespace(),mEventChannel);
}
catch (IOException e)
{
Log.e(TAG,"Exception while creating channel",e);
}
// set the initial instructions on the receiver
sendMessage("starting from mobile");
}
else
{
Log.e(TAG,"application could not launch");
teardown();
}
}
});
}
}
catch (Exception e)
{
Log.e(TAG, "Failed to launch application", e);
}
}
#Override
public void onConnectionSuspended(int cause)
{
Log.d(TAG, "onConnectionSuspended");
mWaitingForReconnect = true;
}
public void sendMessage(String message)
{
if (mApiClient != null && mEventChannel != null)
{
try
{
Cast.CastApi.sendMessage(mApiClient,mEventChannel.getNamespace(), message)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status result)
{
if (!result.isSuccess())
{
Log.e(TAG, "Sending message failed");
}
}
});
}
catch (Exception e)
{
Log.e(TAG, "Exception while sending message", e);
}
}
else
{
Toast.makeText(myContext, message, Toast.LENGTH_SHORT).show();
}
}
public void teardown()
{
Log.d(TAG, "teardown");
if (mApiClient != null)
{
if (mApplicationStarted)
{
if (mApiClient.isConnected() || mApiClient.isConnecting())
{
try
{
Cast.CastApi.stopApplication(mApiClient, mSessionId);
if (myChannel != null)
{
Cast.CastApi.removeMessageReceivedCallbacks(mApiClient,myChannel.getNamespace());
myChannel = null;
}
}
catch (IOException e)
{
Log.e(TAG, "Exception while removing channel", e);
}
mApiClient.disconnect();
}
mApplicationStarted = false;
}
mApiClient = null;
}
mSelectedDevice = null;
mWaitingForReconnect = false;
mSessionId = null;
}
}
MediaRouterCallback.java
public class MyMediaRouterCallback extends MediaRouter.Callback {
private GoogleApiClient mApiClient;
private Cast.Listener mCastListener;
private Context myContext;
private ConnectionFailedListener mConnectionFailedListener;
public MyConnectionCallbacks mConnectionCallbacks;
public String TAG;
//private String mSessionId;
public MyMediaRouterCallback(Context _context, String _TAG)
{
this.myContext = _context;
this.TAG = _TAG;
mConnectionCallbacks = new MyConnectionCallbacks(myContext,TAG);
}
#Override
public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteSelected");
mConnectionCallbacks.mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
launchReceiver();
}
#Override
public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo info) {
Log.d(TAG, "onRouteUnselected: info=" + info);
mConnectionCallbacks.teardown();
mConnectionCallbacks.mSelectedDevice = null;
}
private void launchReceiver()
{
try
{
mCastListener = new Cast.Listener() {
#Override
public void onApplicationDisconnected(int errorCode) {
Log.d(TAG, "application has stopped");
mConnectionCallbacks.teardown();
}
};
//Constructors for Google Play Services Connection
//mConnectionCallbacks = new MyConnectionCallbacks(myContext,TAG);
mConnectionFailedListener = new ConnectionFailedListener(TAG);
Cast.CastOptions.Builder apiOptionsBuilder =
Cast.CastOptions.builder(mConnectionCallbacks.mSelectedDevice, mCastListener);
// ApiClient to Connect to Google Play services
mApiClient = new GoogleApiClient.Builder(myContext)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(mConnectionCallbacks)
.addOnConnectionFailedListener(mConnectionFailedListener)
.build();
mConnectionCallbacks.setApiClient(mApiClient);//setting ApiClient to achieve sendMessage
//Connect to Google Play services
mApiClient.connect();
}
catch (Exception e)
{
Log.e(TAG, "Failed launchReceiver", e);
}
}
}
FirstActivity (where the chromecast is connected)
public class ConnectCastActivity extends ActionBarActivity {
private static final String TAG = ConnectCastActivity.class.getSimpleName();
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
actionBar.setBackgroundDrawable(new ColorDrawable(android.R.color.transparent));
setContentView(R.layout.activity_connect_cast);
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder().addControlCategory(CastMediaControlIntent.categoryForCast(getResources().getString(R.string.app_id))).build();
mMediaRouterCallback = new MyMediaRouterCallback(getApplicationContext(),TAG);
TextView myTextView = (TextView)findViewById(R.id.txt_helloworld);
myTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(),MainActivity.class);
startActivity(i);
}
});
}
#Override
protected void onStart() {
super.onStart();
// Start media router discovery
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
#Override
protected void onStop() {
// End media router discovery
Log.w(TAG, "onStop");
//mMediaRouter.removeCallback(mMediaRouterCallback);
super.onStop();
}
#Override
public void onDestroy() {
Log.w(TAG, "onDestroy");
// mMediaRouterCallback.onRouteUnselected(mMediaRouter,null);
super.onDestroy();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_connect_cast, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem);
// Set the MediaRouteActionProvider selector for device discovery.
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return true;
}
}
SecondActivity (the one that will send the message)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MediaRouter mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mConnectionCallbacks = new MyConnectionCallbacks(getApplicationContext(),TAG);
setContentView(R.layout.activity_main);
//What should I put here?
}
If you have an application with multiple activities, you are better off if you do not tie the cast connectivity and related states to any of those activities, instead you can have a singleton, or use your Application instance or use a background service or ... to maintain the connection and access the required pieces that are maintained in that global place. If it fits your requirement, you might want to use the CastCompanionLibrary that already does most of the routine stuff for you; if not, you can take a look at it and the see how the CastVideos sample app uses that and try to do something similar for your application.
Suppose, Android app is detecting 3 beacons with in range with default UUID value. So, how can i set/change the name for each beacons in Anndroid (to identify each beacon)?
Appreciations for any suggestions... Thanks
Beacons are identified not only by UUID, but also by their major and minor values, and this whole set (UUID + Major + Minor) is how you can differentiate between them.
Moreover, these values are hierarchical in nature, which allows you to put some structure into your beacon deployment. Consider this example:
Whole Museum: UUID = B9407F30-F5F8-466E-AFF9-25556B57FE6D
North Wing: Major = 1
Exhibit A: Minor = 1
Exhibit B: Minor = 2
South Wing: Major = 2
This way, when your device comes in range of a beacon B9407F30-F5F8-466E-AFF9-25556B57FE6D:1:2, just by looking at it you'll know that it's at the North Wing, Exhibit B.
this is i got a solution to set different ids for different beacons. and also identifying differnet beacons and sending notifications to the user when app not in foreground.
I initially confused where to change Major and Minor values of beacons.
Simply, i installed Estimote Android app from Playstore
here,
1. Click on Beacons
2. Select one beacon and it displays one more detailed activity in that you can change Values (for me i changed Minor values for all beacon based on my requirement).
So, now Minor values for all beacons changed as per your requirement. After that find the below code
In this below code I am sending notification if App is in background or else i am dirctly updating statuses in Activity main class.
I changed Beacons values as 1,2,3,4.
public class BeaconMyService extends Service {
private static final String TAG = "BeaconMyService";
private final Handler handler = new Handler();
private BeaconManager beaconManager;
private NotificationManager notificationManager;
private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("rid",
null, null, null);
private static final int NOTIFICATION_ID = 123;
private Messenger messageHandler;
Bundle extras;
private String notifyMsg ="";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
extras = intent.getExtras();
messageHandler = (Messenger) extras.get("MESSENGER");
} catch (Exception e) {
// TODO: handle exception
}
Log.e(TAG, "Called=============");
if (beaconManager.isBluetoothEnabled()) {
connectToService();
}
return Service.START_NOT_STICKY;
}
private void connectToService() {
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
} catch (RemoteException e) {
Log.e("Myservice",
"Cannot start ranging, something terrible happened");
Log.e("", "Cannot start ranging", e);
}
}
});
}
#Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region region,
final List<Beacon> beacons) {
// Note that beacons reported here are already sorted by
// estimated
// distance between device and beacon.
for (int index = 0; index < beacons.size(); index++) {
Beacon beacon = beacons.get(index);
if (beacon != null) {
if (beacons.size() > 0) {
if (Utils.computeAccuracy(beacons.get(0)) < 1.0) {
try {
switch (beacons.get(0).getMinor()) {
case 1:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to Media Lab");
}
break;
case 2:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to Gaming Zone");
}
break;
case 3:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to eLearing Education");
}
break;
case 4:
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = beacons.get(0)
.getMinor();
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
postNotification(beacons.get(0)
.getMinor()
+ ". Welcome to Retail Department");
}
break;
default:
break;
}
} catch (Exception e) {
// TODO: handle exception
}
}else{
if (isAppInForeground(getApplicationContext())) {
Message message = Message.obtain();
message.arg1 = 10;
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
// Utils.computeAccuracy(beacons.get(0))
}
}
}
}
}
});
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
// ---helper method to determine if the app is in
// the foreground---
public static boolean isAppInForeground(Context context) {
List<RunningTaskInfo> task = ((ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1);
if (task.isEmpty()) {
return false;
}
Log.e(TAG + "isAppInForeground-----",
""
+ task.get(0).topActivity.getPackageName()
.equalsIgnoreCase(context.getPackageName()));
return task.get(0).topActivity.getPackageName().equalsIgnoreCase(
context.getPackageName());
}
private void postNotification(String msg) {
if(!notifyMsg.equalsIgnoreCase(msg)){
notifyMsg = msg;
Intent notifyIntent = new Intent(BeaconMyService.this,
MainActivity.class);
notifyIntent.putExtra("content", msg);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivities(
BeaconMyService.this, 0, new Intent[] { notifyIntent },
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(
BeaconMyService.this).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Monitoring Region").setContentText(msg)
.setAutoCancel(true).setContentIntent(pendingIntent).build();
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_LIGHTS;
notificationManager.notify(NOTIFICATION_ID, notification);
}
}
}
Coming to Activity for updating status is this
package com.hcl.beacons_notification_ex;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
static TextView tv_items;
public static Handler messageHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_items = (TextView)findViewById(R.id.tv_items);
messageHandler = new MessageHandler();
}
public static class MessageHandler extends Handler {
#Override
public void handleMessage(Message message) {
int state = message.arg1;
switch (state) {
case 1:
tv_items.setText("Welcome to Media Lab");
break;
case 2:
tv_items.setText("Welcome to Gaming Zone");
break;
case 3:
tv_items.setText("Welcome to eLearing Education");
break;
case 4:
tv_items.setText("Welcome to Retail Department");
break;
default:
tv_items.setText("Going far to Range");
break;
}
}
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Intent i = new Intent(getApplicationContext(), BeaconMyService.class);
if(isMyServiceRunning(BeaconMyService.class)){
}else{
i.putExtra("MESSENGER", new Messenger(messageHandler));
startService(i);
// startService(i);
}
try {
if (getIntent().getExtras() != null) {
tv_items.setText(""
+ getIntent().getExtras().getString("content"));
}
} catch (Exception e) {
// TODO: handle exception
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
First of all you need estimote sdk
Then you can create a beaconDetection service something like this
public class BeaconMyService extends Service
{
private static final String TAG = "BeaconMyService";
private final Handler handler = new Handler();
private BeaconManager beaconManager;
private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("rid", null, null, null);
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if (beaconManager.isBluetoothEnabled())
{
connectToService();
}
return Service.START_NOT_STICKY;
}
private void connectToService()
{
beaconManager.connect(new BeaconManager.ServiceReadyCallback()
{
#Override
public void onServiceReady()
{
try
{
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
}
catch (RemoteException e)
{
Log.e("Myservice", "Cannot start ranging, something terrible happened");
Log.e("", "Cannot start ranging", e);
}
}
});
}
#Override
public void onCreate()
{
super.onCreate();
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(new BeaconManager.RangingListener()
{
#Override
public void onBeaconsDiscovered(Region region, final List<Beacon> beacons)
{
// Note that beacons reported here are already sorted by
// estimated
// distance between device and beacon.
for (int index = 0; index < beacons.size(); index++)
{
Beacon beacon = beacons.get(index);
if (beacon != null)
{
Log.v("Beacon MacAddress", beacon.getMacAddress() + "");
if (!Constants.BEACONSDETECTEDLIST.containsKey(beacon.getMacAddress()))
{//Constants.BEACONSDETECTEDLIST is your list of beacon mac addresses
//public static HashMap<String, Long> BEACONSDETECTEDLIST = new HashMap<String, Long>();
//to check if beacon is detected for the first time
if (Constants.BEACON1.equalsIgnoreCase(beacon.getMacAddress()))
{//Constants.BEACON1 is mac address of beacon 1 assigned in constants
Constants.BEACONSDETECTEDLIST.put(beacon.getMacAddress(), System.currentTimeMillis());
handler.postDelayed(beacon1Detection, 2000);
}
else if (Constants.BEACON2.equalsIgnoreCase(beacon.getMacAddress()))
{
Constants.BEACONSDETECTEDLIST.put(beacon.getMacAddress(), System.currentTimeMillis());
handler.postDelayed(beacon2Detection, 2000);
}
}
else
{/*Do Nothing*/
}
}
}
}
});
}
private Runnable beacon1Detection = new Runnable()
{
public void run()
{
beacon1Info();
}
};
private Runnable beacon2Detection = new Runnable()
{
public void run()
{
beacon2Info();
}
};
private void beacon1Info()
{
Intent intent = new Intent(Constants.BEACON1BROADCAST_ACTION);
sendBroadcast(intent);
}//in Constants
//public static final String BEACON1BROADCAST_ACTION = "beacon1Action";
private void beacon2Info()
{
Intent intent = new Intent(Constants.BEACON2BROADCAST_ACTION);
sendBroadcast(intent);
}// in Constants
//public static final String BEACON2BROADCAST_ACTION = "beacon2Action";
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onDestroy()
{
handler.removeCallbacks(beacon1Detection);
handler.removeCallbacks(beacon2Detection);
super.onDestroy();
}
}
And then finally you need a BeaconBroadcastReceiver to receive the broadcasts in the service and open respective Activity
public class BeaconBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Constants.BEACON1BROADCAST_ACTION)) {
Intent intent2 = new Intent(context, Beacon1Layout.class);
context.startActivity(intent2);
} else if (intent.getAction().equals(Constants.BEACON2BROADCAST_ACTION)) {
Intent intent2 = new Intent(context, Beacon2Layout.class);
context.startActivity(intent2);
}
}
}
Hope this will help you, Good luck :)
I am trying to make an Activity run a certain service.
I followed the tutorial here but adapted to my code, and I can't make it work, because when I am invoking the service after starting and binding it to the activity, my Interface (IMyRemoteCallsLoggingService) object does not seem to have the connection properly created.
I have been trying to make this work for several days but I can't seem to get rid of a NullPointException.
Not sure if I made myself clear, in which case here's the code:
public class MtprojectActivity extends Activity {
[...]
private boolean started = false;
private RemoteSmsLoggingServiceConnection SmsLoggingConn = null;
private RemoteCallsLoggingServiceConnection CallsLoggingConn = null;
private IMyRemoteCallsLoggingService callsLoggingService;
private IMyRemoteSmsLoggingService smsLoggingService;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
retrievePreferences();
Button prefBtn = (Button) findViewById(R.id.prefsBtn);
prefBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Explicit intent to call the preferences
Intent preferencesActivity = new Intent(getBaseContext(),
Preferences.class);
startActivity(preferencesActivity);
}
});
}
private void retrievePreferences() {
// Get the xml/preferences.xml preferences
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
callsCheckbox = prefs.getBoolean("callsLogChk", false);
smsCheckbox = prefs.getBoolean("smsLogChk", false);
locationCheckbox = prefs.getBoolean("locationLogChk", false);
if (callsCheckbox) {
startCallsService();
bindCallsService();
try {
invokeCallsService();
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
}
private void startCallsService() {
if (started) {
Toast.makeText(MtprojectActivity.this, "Service already started",
Toast.LENGTH_SHORT).show();
} else {
Intent i = new Intent();
i.setClassName("app.mtproject", "app.mtproject.CallsLoggingService");
startService(i);
started = true;
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "startService()");
}
}
private void bindCallsService() {
if (CallsLoggingConn == null) {
CallsLoggingConn = new RemoteCallsLoggingServiceConnection();
Intent i = new Intent();
i.setClassName("app.mtproject", "app.mtproject.CallsLoggingService");
bindService(i, CallsLoggingConn, Context.BIND_AUTO_CREATE);
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "bindService()");
} else {
Toast.makeText(MtprojectActivity.this,
"Cannot bind - service already bound", Toast.LENGTH_SHORT)
.show();
}
}
private void invokeCallsService() throws RemoteException {
if (CallsLoggingConn == null) {
Toast.makeText(MtprojectActivity.this,
"Cannot invoke - service not bound", Toast.LENGTH_SHORT)
.show();
} else {
callsLoggingService.dumpCallsLog();
TextView t = (TextView) findViewById(R.id.notApplicable);
t.setText("It worked!");
Log.d(getClass().getSimpleName(), "invokeService()");
}
}
class RemoteCallsLoggingServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className,
IBinder boundService) {
callsLoggingService = IMyRemoteCallsLoggingService.Stub
.asInterface((IBinder) boundService);
Log.d(getClass().getSimpleName(), "onServiceConnected()");
}
public void onServiceDisconnected(ComponentName className) {
callsLoggingService = null;
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "onServiceDisconnected");
}
};
I get a NullPointerException right on callsLoggingService.dumpCallsLog() in the invokeCallsService() method, and I'm not sure what's the problem!
Here's the code of the service:
public class CallsLoggingService extends Service {
String date, duration, type;
private Handler serviceHandler;
private Task myTask = new Task();
#Override
public IBinder onBind(Intent arg0) {
Log.d(getClass().getSimpleName(), "onBind()");
return myRemoteCallsServiceStub;
}
private IMyRemoteCallsLoggingService.Stub myRemoteCallsServiceStub = new IMyRemoteCallsLoggingService.Stub() {
public void dumpCallsLog() throws RemoteException {
CallsLoggingService.this.dumpCallsLog();
}
};
#Override
public void onCreate() {
super.onCreate();
Log.d(getClass().getSimpleName(), "onCreate()");
}
#Override
public void onDestroy() {
super.onDestroy();
serviceHandler.removeCallbacks(myTask);
serviceHandler = null;
Log.d(getClass().getSimpleName(), "onDestroy()");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
serviceHandler = new Handler();
serviceHandler.postDelayed(myTask, 10L);
Log.d(getClass().getSimpleName(), "onStart()");
}
class Task implements Runnable {
public void run() {
try {
myRemoteCallsServiceStub.dumpCallsLog();
} catch (RemoteException e) {
e.printStackTrace();
}
serviceHandler.postDelayed(this, 86400000L);
Log.i(getClass().getSimpleName(), "Calling the dumpCallsLog");
}
}
private synchronized void dumpCallsLog() {
ContentResolver cr = getContentResolver();
String columns[] = new String[] { CallLog.Calls.DATE,
CallLog.Calls.DURATION, CallLog.Calls.TYPE };
Uri mContacts = CallLog.Calls.CONTENT_URI;
Cursor c = cr.query(mContacts, columns, // Which columns to return
null, // WHERE clause; which rows to return(all rows)
null, // WHERE clause selection arguments (none)
CallLog.Calls.DEFAULT_SORT_ORDER // Order-by clause
// (ascending
// by name)
);
if (c.moveToFirst()) {
do {
// Get the field values
date = c.getString(c.getColumnIndex(CallLog.Calls.DATE));
duration = c
.getString(c.getColumnIndex(CallLog.Calls.DURATION));
type = c.getString(c.getColumnIndex(CallLog.Calls.TYPE));
} while (c.moveToNext());
}
}
}
Thanks a lot everybody for the help!
bindService() is asynchronous. You cannot use callsLoggingService until onServiceConnected() is called.