How to check if application is running on background? - android

I am using firebase to send notifications to the application and based on the notification the user will be directed to some activity. so far so good, the problem I am having is that if the application is running on background the activity that will be shown is the main activity but I can not quite managed it to do it.
I believe there ar several questions like this, but do not quite get the answer I am looking for.
Any help or suggestion would be great, thanks

try
/**Flag to determine if the Activity is visible*/
private static boolean activityVisible;
private static boolean activityDestroy;
/**Is the application actually visible on the mobile screen*/
public static boolean isActivityVisible(){
return activityVisible;
}
/**Is the application actually destroyed*/
public static boolean isActivityDestroy(){
return activityDestroy;
}
/**Is the application actually destroyed*/
public static void activityDestroy(boolean isDestroy){
activityDestroy = isDestroy;
}
/**Is the application actually in the background*/
public static boolean isActivityInBackground(){
return !activityVisible;
}
/**Change the state of the Application to resume*/
public static void activityResumed() {
activityVisible = true;
}
/**Change the state of the Application to paused*/
public static void activityPaused() {
activityVisible = false;
}
and then for checking
Application app = ((Application)getApplicationContext());
boolean visible = app.isActivityVisible();

Android 10 (API level 29) and higher place restrictions on when apps can start activities when the app is running in the background. These restrictions help minimize interruptions for the user and keep the user more in control of what's shown on their screen.

You could use importance field of ActivityManager.
Below the method for Xamarin using by C#, but it's pretty similiar to Java.
P.S.: If you want I could port that code to Java
public static Importance GetAppState(Context context, string packageName)
{
try
{
var manager = (ActivityManager)context.GetSystemService(Context.ActivityService);
var processes = manager.RunningAppProcesses;
if (processes != null)
foreach (var process in processes)
if (process.ProcessName.Equals(packageName))
return process.Importance;
}
catch
{
}
return Importance.Gone;
}

Related

How to disallow emulator, isdebuggable check for debug build

I am resolving some security defects for my app.
Defect is:
Should not allow release app to be run in emulator
Release app should not be debuggable
Should not connect to debugger
Release app should be installed from play store not from other resource
And app signature verification
Code 1)
private static boolean isEmulator() {
try {
boolean goldfish = getSystemProperty("ro.hardware").contains("goldfish");
boolean emu = getSystemProperty("ro.kernel.qemu").length() > 0;
boolean sdk = getSystemProperty("ro.product.model").equals("sdk");
if (emu || goldfish || sdk) {
return true;
}
} catch (Exception e) {
}
return false;
}
Code 2)
public static boolean isDebuggable(Context context) {
if (IdscProperties.getIsDebug()) {
return true;
}
if (isDebuggableEnabled(context) || detectDebugger() || detectThreadCpuTimeNanos()) {
return true;
}
return false;
}
private static boolean isDebuggableEnabled(Context context) {
return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
Code 3)
private static boolean detectDebugger() {
return Debug.isDebuggerConnected();
}
Code 4)
private static boolean isInstallerPlayStore(Context context) {
final String installer = context.getPackageManager().getInstallerPackageName(context.getPackageName());
return installer != null && installer.startsWith(PLAY_STORE_APP_ID);
}
Code 5)
private static boolean isAppSignatureMatches(Context context) {
String signature = PackageVerifier.getCertificateHash(context, context.getPackageName());
return SIGNATURE.equals(signature);
}
So, My aim is to not allow these checks in debug builds.
We shall create a flag in some prob file and read it when these checks happen and disallow the function execution.
But the flag shall be modified by the hacker and re-pack the APK to dis-allow these checks.
My expectation is allow these checks in release build and not in debug build without any modifiable flag checks.
Before you start on this path, I want to make sure that you realize 2 things:
Every precaution you implement can be (relatively easily) circumvented on a rooted device
Your app can be easily decompiled into bytecode offline, and any security-related code will be plainly visible.
So, knowing this, if your aim is to prevent piracy, you also need to realize that anything you do will only add some extra steps for the attacker to go through. But if someone really wants to do it, it will not stop them.
If you still want advice on how to implement this, let me know

Interprocess or adb communication with AndroidJUnit

I want to know, does any way exist to communicate with system during instrumentation test execution.
For example:
I have a phone with IR port on onboard & I can work with it through private SDK, also I can tune it with my application. In my Instrumentation test cases I want test app behavior based on external events which I want to configure before test separate test execution.
It's looks like
#Test
public void test() throws Exception {
setupExternalCondition(condition1_ON); // setup external transiver
assertNotNull(IR.read());
assertTrue(assertIR.write());
setupExternalCondition(condition1_OFF);
assertNotNull(IR.read());
assertFalse(IR.write());
}
It's very simple example but there is a lot of "conditions", and sdk updating frequencies to high. I can't do all of this verification manually, and can't ask "transiver&SDK team" make a mock states list for writing just a unit test for coverage. So I want somehow inject external component execution to TestRuner for receiving events(or testName before test case execution) on local machine(or CI machine) to setup external condition.
Simple solution(I think) to run a tcp server on appUnderTest and request external condition change - I am not sure does it possible, and not sure about stable connection(wifi), so may be it's possible to do over adb.
Any suggestions?
P.S: test device has root permissions.
So, find not bad but not ideal solution.
Still wait for better proposition, if not may be this answer will be helpful for someone;
For "building the bridge" between local machine and AndroidJUnitTest I add next class to tests:
class IPCServiceBridge extends BroadcastReceiver {
private static final String FILTER_ID = "IPC_SERVICE";
private static IPCServiceBridge sInstance;
private boolean mIsPermitted;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("ipc.service.action")) {
mIsPermitted = true;
}
}
public static IPCServiceBridge getInstance() {
if (sInstance == null) {
sInstance = new IPCServiceBridge();
IntentFilter filter = new IntentFilter();
filter.addAction("ipc.service.action");
Context context = InstrumentationRegistry.getContext();
context.registerReceiver(sInstance, filter);
}
return sInstance;
}
public void sendIpcCommand(String commandName) {
try {
int i = 30;
mIsPermitted = false;
while (i > 0) {
pub("request:" + commandName);
Thread.sleep(1000);
if (mIsPermitted) {
break;
}
i--;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!mIsPermitted) {
throw new RuntimeException("IPC service does not respond");
}
}
private static void pub(String msg) {
Log.e(FILTER_ID, msg);
}
}
Than I start adb logcat -s "filter_name", parse and check which condition should be applied for InsttUnit test. When conditions is ready i send back broadcast receiver with required action.
#Test
public void test2() throws Exception {
IPCServiceBridge.getInstance().sendIpcCommand("CONDITION#123");
}
Work good, but I'm not sure that it will be super stable.

getAccessibilityButtonController Android Accessibility Service

I have been looking at the new methods available for Accessibility in Android O. I ran across this new method called getAccessibilityButtonController, I am unsure precisely what it does and an intended use. I know that in Android O there is a navigation button that can be used for an accessibility service. Does this accessibility button only launch the accessibility service, or could it have other functionality within the service such as to do specific tasks? I am curious possible uses for the accessibility and the getAccessibilityButtonController methods. Thank you for your time.
It can do pretty much anything you want it to. From the android accessibility doc, the button allows you to register a callback that has an onClicked method. If you enable the button and provide said callback you can execute whatever you'd like in the context of that callback.
Edit: The android documentation has been updated so the following should no longer be necessary.
Note that if you read the doc there's currently an example that has a call to getAccessibilityButtonController() within onCreate(). This is incorrect because the controller isn't valid until onServiceConnected is called. I've modified the example below to show something that should work.
private AccessibilityButtonController mAccessibilityButtonController;
private AccessibilityButtonController
.AccessibilityButtonCallback mAccessibilityButtonCallback;
private boolean mIsAccessibilityButtonAvailable;
#Override
protected void onServiceConnected() {
mAccessibilityButtonController = getAccessibilityButtonController();
mIsAccessibilityButtonAvailable =
mAccessibilityButtonController.isAccessibilityButtonAvailable();
if (!mIsAccessibilityButtonAvailable) {
return;
}
AccessibilityServiceInfo serviceInfo = getServiceInfo();
serviceInfo.flags
|= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
setServiceInfo(serviceInfo);
mAccessibilityButtonCallback =
new AccessibilityButtonController.AccessibilityButtonCallback() {
#Override
public void onClicked(AccessibilityButtonController controller) {
Log.d("MY_APP_TAG", "Accessibility button pressed!");
// Add custom logic for a service to react to the
// accessibility button being pressed.
}
#Override
public void onAvailabilityChanged(
AccessibilityButtonController controller, boolean available) {
if (controller.equals(mAccessibilityButtonController)) {
mIsAccessibilityButtonAvailable = available;
}
}
};
if (mAccessibilityButtonCallback != null) {
mAccessibilityButtonController.registerAccessibilityButtonCallback(
mAccessibilityButtonCallback, null);
}
}

Android : DbxAccountManager.hasLinkedAccount() always return false on Remote Service

On my Activity :
public class MainActivity extends Activity {
private mDbxAccountManager mDbxAccountManager = null;
...
#Override
public void onCreate(Bundle savedInstanceState) {
...
mDbxAccountManager = DbxAccountManager.getInstance(getApplicationContext(), getString(R.string.dbx_app_key), getString(R.string.dbx_app_secret));
...
}
...
public void buttonOnClick(View view) {
if(mDbxAccountManager.hasLinkedAccount()) {
//Do something
}
else {
mDbxAccountManager.startLink(this, 0);
}
...
}
}
And on my Remote Service :
public class CloudService extends Service {
private mDbxAccountManager mDbxAccountManager = null;
#Override
public void onCreate() {
...
mDbxAccountManager = DbxAccountManager.getInstance(getApplicationContext(), getString(R.string.dbx_app_key), getString(R.string.dbx_app_secret));
if(!mDbxAccountManager.hasLinkedAccount()) {
return;
stopSelf();
}
...
}
}
The result is, after I link my app with dropbox using installed dropbox client, the hasLinkedAccount() on my Activity return true, meanwhile the same code on my Remote Service always return false.
I also check the logcat and it showed that my app already linked with dropbox.
My suspect is that the dropbox API create some SharedPreferences when it successfully link with my app, but my Remote Service can't access that or get a cached version of that SharedPreferences... I don't know...
Please help...
Thank you
Edited :
If I reinstall the app, then the result is as expected and hasLinkedAccount() return true, but if I uninstall and install again which cause clearing the user-data, then I link my app again with Dropbox, then the same strange behaviour appear again.
What I'm doing wrong? I'm turning my head almost 24-hours....
Solved!!!
After trying and trying...
I get conclusion that the Service that runs before the app linked with dropbox will always get DbxAccountManager.hasLinkedAccount() return false.
I try to kill the process by calling Process.killProcess(myservicePid) after I link my app with Dropbox and start the service again and it work.
So... I solved it by not starting the service before the app was linked with dropbox and start the service only if it already linked, because stopSelf() on the service doesn't kill the process.
I think this issue have something to do with the Context getApplicationContext() which is passed to DbxAccountManager.getInstance(), and I don't know why looks like the Context is not updated when the dropbox was link with the app.
Thank you.

ActivityWatcher & ProcessObserver

I would like to know the purpose of foloowing two files:
frameworks/base/core/java/android/app/IActivityWatcher.aidl
[description: Callback interface to watch the user's traversal through activities.]
frameworks/base/core/java/android/app/IProcessObserver.aidl
[no description]
I am trying to build an app wherein user can decide which apps can be run during particular period of time (say, from 10am till 4pm).
Is there any way where my app will get notified if one the apps specified by the user starts? This way my app can send kill command (I am assuming that root access is available.)
It seems that IActivityWatcher has been removed beginning with JellyBean, in order to monitor which Activity is running foreground, you can use IProcessObserver as following:
mActivityManagerNative = ActivityManagerNative.getDefault();
if (mActivityManagerNative != null) {
try {
mActivityManagerNative.registerProcessObserver(mProcessObserver);
} catch (RemoteException e) {
Log.e("TAG", "onCreate() RemoteException!");
}
}
private IProcessObserver.Stub mProcessObserver = new IProcessObserver.Stub() {
#Override
public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
doWhatUWantHere();
}
#Override
public void onImportanceChanged(int pid, int uid, int importance) {
}
#Override
public void onProcessDied(int pid, int uid) {
}
};
P.S.
You can use following code snippets to get the package name of foreground running Activity:
private String getForegroundPackage() {
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RecentTaskInfo> taskInfo = am.getRecentTasks(1,
ActivityManager.RECENT_IGNORE_UNAVAILABLE);
return taskInfo.isEmpty()
? null : taskInfo.get(0).baseIntent.getComponent().getPackageName();
}

Categories

Resources