I am only starting with Java/Android and trying to implement custom SDK.
I am making Capacitor plugin for android, but for now trying to do Android side logic.
I have method that I want to be able to execute on demand AndroidConfigManager.stopDetection(getActivity()); which enables/disables NFC read.
so If I execute AndroidConfigManager.stopDetection(getActivity()); I get NFC Detection Enabled in log and all is good.
However that executes every time app goes to background and resumes after. I've tried to override onPause and onResume but the way I have it doesn't seem to be doing anything.
I can't figure out how to suppress it
public class ExamplePlugin extends Plugin implements IDetectCardCallback, IITSOFrameworkCallback, ITransactionControllerCallback {
private Application app;
private Context context;
public void echo(PluginCall call) {
String value = call.getString("value");
app = getActivity().getApplication();
context = getContext();
AndroidConfigManager.initialise(app);
AndroidConfigManager.stopDetection(getActivity());
}
#Override
public void onResume(){
super.onResume();
AndroidConfigManager.stopDetection(getActivity());
// ITSOFramework.getInstance().detectCard(this, false);
}
#Override
public void onPause(){
super.onPause();
// ITSOFramework.getInstance().detectCard(null, false);
}
}
Related
I am trying to implement beacon functionality in my Android application.
Unfortunately there are a few strange behaviours I couldn't solve yet.
I am using the Android Beacon Library in Version 2.15 and Android 6.0.1.
I have an Activity
class MainActivity extends AppCompatActivity implements BeaconConsumer
where I want to search for nearby beacons. I initialize the BeaconManager like
private BeaconManager m_beaconManager;
[...]
m_beaconManager = BeaconManager.getInstanceForApplication(this);
m_beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT));
m_beaconManager.bind(this);
in the onCreate() method.
The way I search for beacons
#Override
public void onBeaconServiceConnect() {
m_beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
// do something
}
});
try {
m_beaconManager.startRangingBeaconsInRegion(m_region);
} catch(RemoteException e) {
e.printStackTrace();
}
}
works perfectly fine.
In my application I want to display these beacons in a list and if I click onto one of them I want to start a new activity with more informations about the beacon (MAC address, distance etc.).
My current approach is to unbind my BeaconManager in the onPause() method and create a whole new BeaconManager in my new Activity. This also works flawless.
But a soon as I finish() my second activity it does not stop searching for beacons. I also unbind my BeaconManager like so
#Override
public void onPause() {
super.onPause();
m_beaconManager.unbind(this);
}
#Override
public void onDestroy() {
super.onDestroy();
m_beaconManager.unbind(this);
}
#Override
public void onStop() {
super.onStop();
m_beaconManager.unbind(this);
}
but back in my MainActivity I get 2 searches for beacons. One from my MainActivity and the other one from my already finished second activity.
Furthermore if I click on another item of my list which means I create my second activity again, it looks for the beacon from the first start and the new one. Each new click on the list adds a new search to the existing ones.
I already searched for known Bugs but there is nothing similar.
What am I doing wrong?
In order to prevent duplicate callbacks, in addition to unbinding, you should call (a) stopRangingBeaconsInRegion(...) and (b) removeRangeNotifier(...). To remove the notifier you will need to keep a reference to your callback class.
I want to make a cloud synchronization everytime my app is brought to front and a second time if the app disappears in background.
So I overwrote the onStart and onStop event methods of my activity:
#Override
protected void onStart() {
super.onStart();
doSync();
}
#Override
protected void onStop() {
doSync();
super.onStop();
}
Ok, that works fine for me but I found out that these methods are also called if I start a new activity (f.e. SettingsActivity.class) within my app (onStop) and come back to the main activity (onStart).
Is there a good way to ignore the calls of my own activities and only react on calls from "outside", f.e. I only want to synchronize if the user stops the app by pressing the home button and I also want to synchronize only if the user returns to the app by starting it from the app dreawer or app switcher?
+++ SOLUTION +++
Now I found a solution for my problem and I want to share it. Maybe it's not the best way because it's no SDK-based functionality but it works and it's quite simple.
I declared a flag, set it to false when the activity is created. Everytime I start another activity in the same app, I will set the flag to true and check its state in onPause and onResume.
public class MainActivity extends Activity {
private boolean transition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
transition = false;
}
private void startSettingsActivity() {
transition = true;
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
private void doSync() {
// all steps for the cloud synchronization
}
#Override
protected void onResume() {
super.onResume();
if (!transition) {
// this is the case the user returns from
// the app drawer or app switcher or starts
// the app for the first time, so do sync
doSync();
} else {
// this is the case the user returns from another
// activity, so don't sync but reset the flag
transition = false;
}
}
#Override
protected void onPause() {
if (!transition) {
// this is the case the user presses the home button or
// navigate back (leaves the app), so do final sync
doSync();
} else {
// this is the case the user starts another activity, but
// stays in the app, so do nothing
}
super.onPause();
}
}
I want to make mygame (unity) run in background on android when I click a button.
There is the information that i need to set up plugin and use service so I connected plugin between unity and android and made a button on unity.
When the button is clicked , the onCreate method should be activated and the service should be activated.
But i have no idea what to do next. There is no paper to make whole unity game run in background. there is only about the way how to deliver the string like "a, b, c , 1, 2,3" .
according to the docs, i need to use the method called " unitysendmessage()" .but if i use it i can't make methods on unity as service. it just sends strings.
is there any solution to make unity run in background ?
Button on unity
public void andro() {
_plugins.Call("onCreate");
}
Android code
public class MainActivity extends UnityPlayerActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(this, my.class));
}
}
public class my extends Service {
public int onStartCommand(Intent intent, int flags, int startld) {
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I have a BaseActivity that gets extended by every other activity. The thing is, I have the music muted whenever the user leaves (onPause) the activity. I also stop listening for telephone calls. The problem is, onPause is getting called whenever the user switches between activities, meaning the app is unnecessarily muting and stopping telephonymanager, even though it should only be muting and stopping telephonymanager if the user were to leave the app.:
#Override
protected void onPause() {
Log.v(TAG, "IN onPause!");
// unregister phone listener to telephony manager
tManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
mute();
super.onPause();
}
Now say I switch between public class myClass extends BaseActivity and switch to public class myOtherClass extends BaseActivity. This switch is unnecessarily executing onPause, even though I only want onPause to be called when the user leaves the app. What should I do?
Thanks for the expert advice,
Rich
From my understanding you are muting your music playing in onPause of BaseActivity, instead of that write it inside your Music play activity
Ex :
public class BaseActivity extends AppCompatActivity{
#Override
public void onPause(){
//do things that common for all activities
}
}
public void MusicPlayActivity extends AppCompatActivity{
#Override
public void onPause(){
music.mute()
}
}
This will work
UPDATE
There are few ways to detect whether your application is running in the background, but only one of them is completely reliable:
Track visibility of your application by yourself using Activity.onPause, Activity.onResume methods. Store "visibility" status in some other class.
Example
: Implement custom Application class (note the isActivityVisible() static method):
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
Register your application class in AndroidManifest.xml:
<application
android:name="your.app.package.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name" >
Add onPause and onResume to every Activity in the project (you may create a common ancestor for your Activities if you'd like to, but if your activity is already extended from MapActivity/ListActivity etc. you still need to write the following by hand):
#Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
#Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
ActivityLifecycleCallbacks were added in API level 14 (Android 4.0). You can use them to track whether an activity of your application is currently visible to the user. Check Cornstalks' answer below for the details.
From your comments you only want to stop the music when the last Activity of your application is exiting. Overriding the finish() method of your BaseActivity like this should accomplish what you want:
#Override
public void finish() {
super.finish();
if (isTaskRoot()) {
// This is the last Activity in the stack so mute your music here...
}
}
Actually you probably want onDestroy() or onStop() as I'm not sure finish() executes unless you call it but the idea is the same:
#Override
protected void onDestroy() {
super.onDestroy();
if (isTaskRoot()) {
// This is the last Activity in the stack so mute your music here...
}
}
Here's info on isTaskRoot():
Return whether this activity is the root of a task. The root is the first activity in a task.
Returns
True if this is the root activity, else false.
I am designing an android app which uses notification.
Before this, I was using a full screen activity, so if a notification came, in full view I didn't get any alert.
Now I am using a blank activity with notifications enabled.
I don't want to show notifications when I am already inside the app (like skype).
Or else, I want to cancel them immediately once flashed.
How to achieve this?
Thank you in advance.
You can define a superclass for all of your activities and track the state of the app. If all activities are in stopped state - app in the background, otherwise - in the foreground. In onStart() and onStop() methods of your super activity you can increment and decrement the number of visible activites.
public class SuperActivity extends Activity {
private static int sVisibleActivitiesCount;
#Override
public void onStart(){
super.onStart();
sVisibleActivitiesCount++;
}
#Override
public void onStop(){
super.onStart();
sVisibleActivitiesCount--;
}
public static boolean isAppInForeground() {
return sVisibleActivitiesCount > 0;
}
}
Now you can check somewhere for an application status and not create notification if SuperActivity.isAppInForeground returns true.
The second approach is to use ActivityLifecycleCallbacks (min API 14) for monitoring activities lifecycle and track application state in a single place without having a super class for all activities. So I would rather use this approach if your app has minSdkVersion="14".
You can try to get the running processes list and check if the one in foreground is your app.
private boolean isAppInForeground() {
ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> mRunningProcesses = mActivityManager
.getRunningAppProcesses();
Iterator<RunningAppProcessInfo> i = mRunningProcesses.iterator();
while (i.hasNext()) {
RunningAppProcessInfo runningAppProcessInfo = i.next();
if (runningAppProcessInfo.uid == getApplicationInfo().uid && runningAppProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
{
return true;
}
}
return false;
}