Android Beacon - Issue with bind/unbind(this) - java

I'm trying to create my own "BeaconManager" to develop different actions more easily.
So I've created a new class and I've implement "BeaconConsumer" and its functions :
public class MybeaconManager implements BeaconConsumer{
private BeaconManager beaconManager;
private final String TAG = "MybeaconManager";
private boolean mEnterArea = false;
private boolean mAlreadyArea = false;
public MybeaconManager(Context ctx){
beaconManager = BeaconManager.getInstanceForApplication(ctx);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager.bind(this);
}
public void bindBeacon(BeaconConsumer consumer){
beaconManager.bind(consumer);
}
public void unBindBeacon(BeaconConsumer consumer){
beaconManager.unbind(consumer);
}
public boolean isEnterInArea() {
return mEnterArea;
}
public boolean isAlreadyInArea() {
return mAlreadyArea;
}
public void sendNotification(String Notif) {
}
#Override
public void onBeaconServiceConnect() {
beaconManager.addMonitorNotifier(new MonitorNotifier() {
#Override
public void didEnterRegion(Region region) {
mEnterArea = true;
}
#Override
public void didExitRegion(Region region) {
mEnterArea = false;
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
});
}
Next to this, I have my MainActivity :
public class MainActivity extends Activity {
MybeaconManager mybeaconManager;
BeaconManager beaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mybeaconManager = new MybeaconManager(this);
if (mybeaconManager.isEnterInArea()){
Log.i("BeaconTest", "I'm detecting a Beacon");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
mybeaconManager.unBindBeacon((BeaconConsumer) this);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
}
}
So as you can see, I'm trying to use the functions didEnterRegion/didExitRegion more easily in a way that I only have to use on line in my MainActivity code.
The problem is, the bind/unbind(this) don't compile well and I think it's because I don't implement "BeaconConsumer" on the MainActivity because he can't get the consumer right.
It's telling me : "Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference" and return me on the bind thing.
So do you have any ideas on how I can deal with this in a way that I keep my beaconManager ?
Thank you in advance.
PS : Sorry if my English is not perfect

BeaconConsumer interface is designed to be implemented by an Activity or Service class. If you want to implement this interface in a POJO as shown in the question, you need to chain the method definitions shown below.
#Override
public Context getApplicationContext() {
return getActivity().getApplicationContext();
}
#Override
public void unbindService(ServiceConnection serviceConnection) {
getActivity().unbindService(serviceConnection);
}
#Override
public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) {
return getActivity().bindService(intent, serviceConnection, i);
}
I suspect your code already has empty implementations of these methods, otherwise your code would not compile. Make sure you have provided full implementations as shown above.

Related

How to detect application runs foreground or background using Single Activity or Java class

I want to sent report to the server which means how long user Use the application in single day..I can achieve using this to method
#Override
protected void onResume() {
super.onResume();
//commonclassMethod.getInstance(UserForground);
}
#Override
protected void onStop() {
super.onStop();
//commonclassMethod.getInstance(UserBackground);
}
What happen i need to call call this method in every activity....
What i need,is there any possible to find user forground background method in single java class or activity..
Thanks in Advance.
You can can achieve this just by adding an method isAppIsInBackground(Context context) in class which is extending Application class
In that class define that method:
public static boolean isAppIsInBackground(Context context) {
boolean isInBackground = true;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
isInBackground = false;
}
}
}
}
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (componentInfo.getPackageName().equals(context.getPackageName())) {
isInBackground = false;
}
}
return isInBackground;
}
It will true if app is in background
Or another better approach would be just extend your each Activity by an BaseActivity, in this BaseActivity's override methods
protected void onResume() {
super.onResume();
//commonclassMethod.getInstance(UserForground);
}
protected void onStop() {
super.onStop();
//commonclassMethod.getInstance(UserBackground);
}
You can implement callback method to solve your case.
For example:
You create an interface first, then define a method, which would act as a callback. In this example we would have two classes, one classA and another classB
Interface:
public interface OnCustomEventListener{
public void onEvent(); //method, which can have parameters
}
the listener itself in classB (we only set the listener in classB)
private OnCustomEventListener mListener; //listener field
//setting the listener
public void setCustomEventListener(OnCustomEventListener eventListener) {
this.mListener=eventListener;
}
in classA, how we start listening for whatever classB has to tell
classB.setCustomEventListener(new OnCustomEventListener(){
public void onEvent(){
//do whatever you want to do when the event is performed.
}
});
how do we trigger an event from classB (for example on button pressed)
if(this.mListener!=null){
this.mListener.onEvent();
}
Here is some nice tutorials link1,link2,link3 which describes callbacks and the use-case well.
Create a class extending application and use registerActivityLifecycleCallbacks() to get the activity lifecycle
public class MyApp extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
if(activity.getClass().getSimpleName().equalsIgnoreCase(MainActivity.class.getSimpleName())){
//Do the required thing here
}
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
});
}
}
Also dont forget to register activity in manifest
<application
android:name=".MyApp"
You have two options.
1) Do a abstract BaseActivity and make all Activities extend it. This way you only write the code in one BaseActivity and all children activities consume it.
2) Use a custom counter class to monitor app to foreground. Here is my implementation of it if you would like to copy it.
/**
* Created by App Studio 35 on 6/23/17.
*/
public class AppLifeCycleTracker implements Application.ActivityLifecycleCallbacks {;
/*///////////////////////////////////////////////////////////////
// METHODS
*////////////////////////////////////////////////////////////////
private static final String TAG = Globals.SEARCH_STRING + AppLifeCycleTracker.class.getSimpleName();
private static AppLifeCycleTracker INSTANCE;
private static int numActivitiesInMemory = 0;
private ArrayList<IAppToForegroundListener> mAppToForegroundListeners;
private boolean isRefreshing;
private Object lockAccess = new Object();
private AlertDialog mAlertDialog = null;
/*///////////////////////////////////////////////////////////////
// PROPERTIES
*////////////////////////////////////////////////////////////////
private ArrayList<IAppToForegroundListener> getAppToForegroundListeners(){
return mAppToForegroundListeners == null ? mAppToForegroundListeners = new ArrayList<IAppToForegroundListener>() : mAppToForegroundListeners;
}
public boolean getIsRefreshing(){
return isRefreshing;
}
public boolean getAppIsInBackground(){
return numActivitiesInMemory < 1;
}
/*///////////////////////////////////////////////////////////////
// CONSTRUCTOR
*////////////////////////////////////////////////////////////////
private AppLifeCycleTracker(){
}
public synchronized static AppLifeCycleTracker getInstance(){
if(INSTANCE == null){
INSTANCE = new AppLifeCycleTracker();
}
return INSTANCE;
}
/*///////////////////////////////////////////////////////////////
// LIFE CYCLE OVERRIDES
*////////////////////////////////////////////////////////////////
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(final Activity activity) {
//App went into background, so set a flag to avoid loading while we refresh
if(numActivitiesInMemory == 0 && !(activity instanceof SplashScreenActivity) && !(activity instanceof CreateAccountActivity)){
A35Log.v(TAG, "App Returned to Foreground, refreshing Token");
//first load on splash it goes from 0 to 1 so hold off on splash
synchronized (lockAccess) {
isRefreshing = true;
}
if (DeviceInfo.getInstance(activity).getIsConnectedToInternet()) {
CognitoManager.refreshToken(activity, new GenericHandler() {
#Override
public void onSuccess() {
A35Log.v(TAG, "Token Refresh Complete, notifying listeners");
//we are good, keep going
for(IAppToForegroundListener listener : getAppToForegroundListeners()){
listener.onRefreshTokenComplete();
}
synchronized (lockAccess) {
isRefreshing = false;
}
}
#Override
public void onFailure(Exception exception) {
//boot them to login screen
if(activity instanceof LoginActivity || activity instanceof SplashScreenActivity){
return;
}
startLoginActivity(activity);
synchronized (lockAccess) {
isRefreshing = false;
}
}
});
} else {
showInternetRequiredDialog(activity);
}
}
numActivitiesInMemory++;
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
numActivitiesInMemory--;
//if numActivities == 0 then you are in the background
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
/*///////////////////////////////////////////////////////////////
// METHODS
*////////////////////////////////////////////////////////////////
public void addAppToForegroundListener(IAppToForegroundListener listener){
getAppToForegroundListeners().add(listener);
}
public void removeAppToForegroundListener(IAppToForegroundListener listener){
getAppToForegroundListeners().remove(listener);
}
private void startLoginActivity(final Activity activity){
((AMApplication) activity.getApplication()).logoutCurrentUser(activity, false, false, null, true, null);
}
/*///////////////////////////////////////////////////////////////
// INTERFACES
*////////////////////////////////////////////////////////////////
public interface IAppToForegroundListener {
/*///////////////////////////////////////////////////////////////
// METHODS
*////////////////////////////////////////////////////////////////
void onRefreshTokenComplete();
}
private void showInternetRequiredDialog(Activity activity){
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Error").setMessage("Internet is required to use this app").setNegativeButton(R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(mAlertDialog != null && mAlertDialog.isShowing()) {
mAlertDialog.dismiss();
}
}
});
mAlertDialog = builder.create();
mAlertDialog.show();
}
}
Of course this does a little more then you are looking for as mine manages refreshing the token with cognito and forcing refresh on returning from background and things like that, so just disregard that piece. But the rest is all the same still. Hope that helps.
I'm assuming you don't need an example of a BaseActivity so I won't patronize you by pasting that.
Startup in Application class
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(AppLifeCycleTracker.getInstance());
}
Then you ONLY need to access from BaseActivity or BaseFragment IF you need to be notified when the app is in foreground or background at an Activity or fragment level. Which for your situation is not the case.
But if you ever wanted to use it, simply do this:
#Override
public void onAttach(Context context) {
super.onAttach(context);
AppLifeCycleTracker.getInstance().addAppToForegroundListener(this);
}
#Override
public void onDetach() {
super.onDetach();
AppLifeCycleTracker.getInstance().removeAppToForegroundListener(this);
}
But again, I must emphasize, this part is ONLY if you care to make your activity or fragment be aware of when the app comes back to foreground to force refresh or other behaviors. Replace onDetach with onDestroy if using Activity, but for your scenario you can skip that whole last section of code, you don't need it.

Call method in MainActivity class from another class

What I want to do is call a method which is placed in my MainActivity.java file from another subclass. But everytime i want to call this method, my app crashes.
I already tried to make SetGerateStat() static but that didn't change anything. Also, I can build the apk without any errors, the application only crashes when the SetGerateStat() is called from the Thread.
What am I doing wrong here?
My code is below (please note that this is only a snippet):
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private CheckedTextView gerätestat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void setGeraeteStat(boolean x) {
if (x==true) {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_online);
} else {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_busy);
}
}
public void onClick(View v) {
if(v==button_refresh) {
Thread connection = new Thread(new Conn("refresh", MainActivity.this));
connection.start();
}
}
Conn.java:
public class Conn implements Runnable {
private MainActivity act;
private String actioncommand;
public Conn(String a) {
actioncommand = a;
act = null;
}
public Conn(String a, MainActivity m) {
actioncommand = a;
act = m;
}
public void run() {
switch(actioncommand) {
case "refresh": {
act.setGeraeteStat(true);
}
break;
}
}
Have you forgot to initialize gerätestat ? You have to initialize gerätestat after setcontentview. After that use runOnUIThread method as below
public void setGeraeteStat(final boolean x){
runOnUiThread (new Runnable() {
public void run() {
if (x==true) {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_online);
} else {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_busy);
}
}
});}

Calling finish() from SurfaceView does not destroy Activity

I want to finish() the activity VideoPlayer from the class RenderView. However calling finish() from RenderView does not call onDestroy(). The Activity is not destroyed and does not return back to the previous Main Activity.
public class VideoPlayer extends Activity {
#Override
protected void onPause(){
super.onPause();
renderView.pause();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onDestroy() {
super.onDestroy();
naClose2();
}
}
mFinished = true but it returns back to the method parseServerInfo() where finish() was called and continues executing the rest of the code.
EDIT
public class RenderView extends SurfaceView implements SurfaceHolder.Callback {
private Context mContext;
private Runnable prDisplayVideoTask = new Runnable() {
public void run() {
if(zoomState.isPlaying()==false){
if(zoomState.getFlag()==FlagType.PAUSE){
zoomState.setFlag(FlagType.NONE);
naPause();
}
} else {
naStart();
}
prVideoDisplayHandler.postDelayed(this, prDelay);
}
};
public RenderView(...) {
super(_context);
this.mContext = _context;
init(address, windowWidth, windowHeight, videoWidth, videoHeight,
server_ip, server_port);
SurfaceHolder holder = getHolder();
holder.setFormat(PixelFormat.RGBA_8888);
holder.addCallback(this);
}
#SuppressLint("NewApi")
public void init(...) {
parseServerInfo(receivedData);
prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
}
public void pause(){
naPause();
prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
}
public void resume(){
prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
}
public void parseServerInfo(String data) {
if (numCameras == 0) {
Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();
// Finish is called here
VideoPlayer videoplayer = (VideoPlayer) mContext;
videoplayer.finish();
return;
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (mCreated == true) {
surfaceDestroyed(holder);
}
Surface surface = holder.getSurface();
render(surface);
mCreated = true;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCreated = false;
}
}
Hope someone could help point out what I am doing wrong.
This is why it is continuing on and freezing up (as mentioned in the comments to your question). It should. That is how the java language works. Here,
#SuppressLint("NewApi")
public void init(...) {
parseServerInfo(receivedData);
...
}
You call parseServerInfo(receivedData); which does
public void parseServerInfo(String data) {
if (numCameras == 0) {
Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();
// Finish is called here
VideoPlayer videoplayer = (VideoPlayer)getContext();
videoplayer.finish();
return;
}
}
So you are seeing the Toast, getting finish called, and saying good to go. But you aren't looking back at where you came from. With comments, what your init method should say is
#SuppressLint("NewApi")
public void init(...) {
// make a call to check that the number of cameras is not 0
parseServerInfo(receivedData);
// AND CONTINUE NO MATTER WHAT...
prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
}
What you need is
public boolean parseServerInfo(String data) {
if (numCameras == 0) {
Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();
// Finish is called here... AND FALSE IS RETURNED
VideoPlayer videoplayer = (VideoPlayer) mContext;
videoplayer.finish();
return false;
}
return true;
}
then
#SuppressLint("NewApi")
public void init(...) {
// make a call to check that the number of cameras is not 0
// AND CONTINUE IF GOOD (TRUE)
if(parseServerInfo(receivedData)){
prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
}
}
this will parse your data, finish the activity if it should, and then stop progress with your SurfaceView init method. Sorry for so much redundant code but it is just easiest to explain :P
You have to reference the Activity which you would like to finish inside the SurfaceView. You get the context from the constructor of the SurfaceView class. Use this to finish() your activity, like so
//class member
private Context mContext;
public RenderView(...) {
super(_context);
//make the context accessible from the whole class
this.mContext = _context;
...
}
Finally you call finish() on the that context to finish your VideoPlayer activity.

Android AsyncTask runs multiple times

In my app ,there is an one button which get input from database.When I press it more than one in a short time it crashes.
How can i avoid this error with using asynctask?
show.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
showinf();
}
});
}
private String[] columns={"name","surname"};
private void showinf(){
SQLiteDatabase db=v1.getReadableDatabase();
Cursor c=db.query("infos",columns,null,null, null,null,null);
Random mn2=new Random();
int count=c.getCount();
String mn=String.valueOf(count);
int i1=mn2.nextInt(count+1);
c.move(i1);
t1.setText(c.getString(c.getColumnIndex("name")));
t2.setText(c.getString(c.getColumnIndex("surname")));
}
thanks...
You can create a boolean flag (let's say bDiscardButtonAction), and set it to true in onPreExecute() and set it to false in onPostExecute(), something like:
public class FooTask extends AsyncTask<Foo, Foo, Foo>
{
private static boolean bDiscardButtonAction = false;
private boolean isDiscareded = false;
#Override
public void onPreExecute()
{
if(bDiscardButtonAction)
{
isDiscareded = true;
return;
}
bDiscardButtonAction = true;
}
#Override
public Foo doInBackground(Foo... params)
{
if(isDiscareded) return;
// ...
}
#Override
public void onPostExecute(Void result)
{
if(!isDiscareded) bDiscardButtonAction = false;
}
#Override
public void onCancelled(Foo result)
{
if(!isDiscareded) bDiscardButtonAction = false;
}
}
disable the show button in onPreExecute() and enable it back onPostExecute().
public class getAsyncDataTask extends AsyncTask<Void, Void, Void>
{
#Override
public void onPreExecute()
{
show.setAlpha(0.5);
show.setEnable(false);
}
#Override
public void doInBackground(Void... params)
{
//retrieve the data from db;
}
#Override
public void onPostExecute()
{
show.setAlpha(1.0);
show.setEnable(true);
}
}
I hope this code will help u out.
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
new AsynchTaskManualLocation().execute();
});
public class AsynchTaskGetData extends AsyncTask<String,Void,String>
{
#Override
protected String doInBackground(String... url) {
//showinf(); this method contains operation of getting data from //database OR ur logic to getdata
return showinf();
}
#Override
protected void onPostExecute(String result) {
//here u get result in resul var and process the result here
}
}
}

how to detect head movement via glass gdk api?

I write an app for google glass platform using the gdk.
how can I detect and react to head movement?
I don't find the proper listener not the Gesture enum (e.g. Gesture.SWIPE_UP)
gestureDetector.setBaseListener(new GestureDetector.BaseListener() {
#Override
public boolean onGesture(Gesture gesture) {
if (gesture == Gesture.TAP) {
//do something
}
return true;
} else if (gesture == Gesture.SWIPE_UP) {
gestureDetector.setScrollListener(new ScrollListener() {
#Override
public boolean onScroll(float arg0, float arg1, float arg2) {
// TODO Auto-generated method stub
return false;
}
})
Take a look here: https://developers.google.com/glass/develop/gdk/location-sensors . It should help you out with the accelerator and other sensors that are accessible via the GDK. The code you have copied is for the touch pad, not for head movement.
take a look at this repo:
https://github.com/thorikawa/glass-head-gesture-detector
Usage:
public class MainActivity extends Activity implements OnHeadGestureListener {
private HeadGestureDetector mHeadGestureDetector;
#Override
protected void onCreate(Bundle savedInstanceState) {
…
mHeadGestureDetector = new HeadGestureDetector(this);
mHeadGestureDetector.setOnHeadGestureListener(this);
…
}
#Override
protected void onResume() {
…
mHeadGestureDetector.start();
}
#Override
protected void onPause() {
…
mHeadGestureDetector.stop();
}
#Override
public void onNod() {
// Do something
}
#Override
public void onShakeToLeft() {
// Do something
}
#Override
public void onShakeToRight() {
// Do something
}
}

Categories