I know this has been asked many times already, with no answers, but I still hope that someone has finally solved the problem.
The problem: I have a non-rooted device running Android 2.3. I need to create a service which:
makes a phone call;
waits until the call is answered;
hangs the phone after the call is answered (with a timeout);
Like many others, I've got stuck with #2. Below is the summary of the solutions ever suggested:
Use PhoneStateListener (most popular): does not work, for an outgoing call it cannot detect what I need.
Use com.android.internal.telephony.CallManager and its methods like registerForPreciseCallStateChanged (e.g., this one): does not work, no phones are registered within it, so the events do not fire.
Use com.android.internal.telephony.PhoneFactory to obtain a com.android.internal.telephony.Phone instance (which is the key to everything): does not work, the factory is not initialized; attempts to initialize it with a makeDefaultPhones call result in a security exception (like here).
Detect the outgoing ringtone (link): the author - Dany Poplawec - states that detecting ringtones may help to solve the problem, but does not provide any details, so I was not able to try this technique.
It looks like everything has been tried already, but there still may be one more trick that will save me :)
I'm trying to get this too and can't find any solution yet.
Looking on the Android Source Code I found these lines in ~/kitchen/jellybean/frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java
public enum State {
IDLE, ACTIVE, HOLDING, DIALING, ALERTING, INCOMING, WAITING, DISCONNECTED, DISCONNECTING;
public boolean isAlive() {
return !(this == IDLE || this == DISCONNECTED || this == DISCONNECTING);
}
public boolean isRinging() {
return this == INCOMING || this == WAITING;
}
public boolean isDialing() {
return this == DIALING || this == ALERTING;
}
}
I think one could know if an outgoing call was answered checking the ACTIVE state, but I don't know how to read this value from an app, maybe modifying the framework by adding a specific function for this like:
public boolean isActive() {
return this == ACTIVE;
}
This is just an idea, but I'm not sure how to implement this, because obviously other modifications have to be done for accessing this new function from the application layer.
If you find this viable or know how to do it, help and feedback will be very appreciated.
The solution in your 3rd bullet should be possible in rooted devices, if you follow the instructions in Android INJECT_EVENTS permission
Step by step, it is something like:
Signing the app with the platform certificate. This requires the following steps:
add android:sharedUserId="android.uid.phone" to the manifest-tag of your apk´s manifest.
add android:process="com.android.phone" to the application-tag of the manifest.
you may need to add a few extra permissions to your manifest, and will also need to change the severity for ProtectedPermission in the "Android Lint Preferences" of your project.
get the platform.pk8 + platform.x509.pem from {Android Source}/build/target/product/security (I have used the ones for 4.4.4r1 in https://android.googlesource.com/platform/build/+/android-4.4.4_r1/target/product/security/)
Download keytool-importkeypair from https://github.com/getfatday/keytool-importkeypair
Use this script to obtain the keystore for the platform with command: keytool-importkeypair -k google_certificate.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform . I ran it on cygwin, with a minor modification of the script.
Sign the apk using this keystore.
install the application as a system app using adb:
adb root
adb remount
adb push MyApp.apk /system/app
adb shell chmod 644 /systen/app/MyApp.apk
Restart the device.
I have actually tried the solution in the 2nd bullet and it does not work for me either (on a Galaxy S5 running Kitkat).
The solution in the 3rd bullet item does work quite OK. Regardless of the package name, the app runs as com.android.phone , so you need to attach to that process if you want to debug the app.
Related
I found out there's a system function called IBluetoothManager.enableNoAutoConnect(), which by the name, seems to do exactly what I've been searching for hours: enable Bluetooth without auto-connecting to devices.
I can call the function, but...
java.lang.SecurityException: no permission to enable Bluetooth quietly
Because...
if (callingAppId != Process.NFC_UID) {
throw new SecurityException("no permission to enable Bluetooth quietly");
}
So, is there any other way of calling this function? Like some ADB command? Or through another class? I also found a function that does the same here, in AdapterService.java. But I don't know how to get to it (doesn't even appear on Android Studio).
Note: I have root and system-privileged permissions (just not signature ones), and I'm using the internal/hidden SDK, so I have access to the classes and everything without needing reflection (and still, AdapterService doesn't show up - unless there's a problem with the "SDK" and it's not showing all it should?).
(PS: I say "quietly" in the title because in the source, the variable that tells if it's auto-connect or not is called quietMode.)
EDIT: actually the function is directly in BluetoothAdapter, without needing to go for the interface. Not sure how I didn't notice it. But anyway, same problem.
EDIT 2: more specifically for Android Oreo and below (or Pie and below), as I just found a function called setSilenceMode() on BluetoothDevice, and it might do what I'm wanting (not tested), but still, missing on older APIs.
Thank you
I have made some researches, and what they say is : "Not for use by third-party applications" on the android permission documentation, and there is a lot of question already asked, but havent found none with a final answer,
So I was wondering, have anyone succeeded ? and may he help ? ^^
Step #1: Have a <uses-permission android:name="android.permission.REBOOT"> element in the proper spot in your manifest.
Step #2: Call reboot() on an instance of PowerManager.
Then, either:
Step #3a: Build your own custom build of Android, rolled into your own ROM mod. Then, sign your app with the same signing key that you used to sign the OS in the ROM mod.
or:
Step #3b: Have the user of a rooted device make your app be a system app.
Without Step #3a or #3b, your app will not be eligible to hold the REBOOT permission and your reboot() call will fail.
My boss hopes that there is no information leak when users use our android apps.
And I found even I set the android:debuggable="false" it still can see my logs from Logcat or command line.
I searched android:debuggable someone also have the same problem.
I got some answers from internet, such as next:
There are a property called debugable of Avd. You can print by adb
shell get prop. I don't (know) if it is the cause of your problem.
If you have a pre-production device, you
can still debug an app that has debuggable set to false.
I just think, even I delete all my logs, there are also many logs about my app from OS.
My questions:
1.Is there a way I can do let my "android:debuggable" work well and
2.Is there any other way to hide all my logs except delete all my logs?
3.What does "android:debuggable" really mean?
4.What is "a pre-production device" when it goes on android device?
Thank you for your help. I will try some other ways, and try my best to share my information in here.
I simply create wrapper functions around Log that first check the value of a static boolean called loggineEnabled if it is set to true then log gets called otherwise the calls to log are ignored.
Then I simply set this variable to false before I compile a version of my app that I distribute.
void LogD(String msg){
if (loggingEnabled)
Log.d(MyTag, msg)
}
Is your code guaranteed to be bug-free? If not, why do you want to stop users having information that they might be able to use to shed light on bugs in your app?
Come back when you can write bug-free code, then we’ll talk.
I want to add a secret logging toggle switch so that when the QA guys here test the app, they should be able to do some magic secret trick which will switch on the logging for them onltytheir phones.
Magic secret trick meaning something like clicking on a few parts of the screen should switch it on or something else you suggest. This secret should be known only to the QA team and this should not affect the app in any other way.
I am planning to log the statements in a file on sd card.
What are your thoughts? What's the best way to do it?
What's the usual way of doing it?
Make a build for QA with logging on, turn it off for production. Avoid magic tricks.
A very simple way would be checking if a file (empty one, doesn't matter) exists on the sdcard. You could make the filename dynamic (based on date/month) or very obscure.
You could choose to not hide the functionality and just put a button (e.g. in your about box) that will enabled logging. Then if you have a problem at a customer site, that you have a hard time reproducing, you also have the possibility of having the customer sending you a log.
Otherwise I would also suggest checking for some magic file on the sd-card (e.g. app-xyz-enable-log) and if that exists you would automatically start logging to that sd-card. All your QA people would then make a empty file on their sd-card with that name prior to running your app.
The normal way to do it (other than having separate builds) is to use the standard Android logging. You can teach your QA guys to extract the LogCat logs or build a small script for them to do so. Then when you log, make sure to log only the level necessary. For example:
private static String LOG_TAG = "MyLogTag";
private static boolean D = Log.isLoggable(LOG_TAG, Log.DEBUG);
...
if (D) {
Log.d(LOG_TAG, "Something happened that I want to log!");
}
Then normally that statement won't log, but if you want to turn it on, you can run:
adb shell setprop log.tag.MyLogTag DEBUG
I'm writing an application that must not run on rooted devices. I want to store some secure data and which is possible only on non-rooted devices as nobody can access files in /data/data/package-name.
Does anyone know:
1) Is it possible to prevent the installation of an application on rooted devices? I read something about the "copy-protection mechanism" of Android Market. This feature seems to be outdated and replaced by the licensing feature. However, licensing is only possible for paid application and mine is free...
2) Is it possible to check programmatically whether a device is rooted or not? If it would be possible to do so I could simply stop the application if the device is rooted.
Any help regarding this topic is appreciated!
Execute
Runtime.getRuntime().exec("su");
and check the result code.
In other words, if you can exec su, then you have root access. it doesn't matter if the user allows or denies it, you have your answer.
I think your approach is a bit flawed. First of all, the user can first install your application and data, then "root" the device (even if rooting wipes the data, one can make the backup first). Next, the general rule is that whatever is in user's hands is not yours anymore. The hacker will find a way to get to your data sooner or later.
If you care about secure data, don't put it to device. As Android is net-centric device (yes, I know, that's subjective, but it was initially developed and positioned as such), accessing the data online is not uncommon.
What I would say is to run su and then check the output. If the user allows your app to have root, then use root to uninstall your own application (one way might be to place a script into init.d and then force a reboot).
If the user DOES NOT allow your app to run as root, then:
They DENIED your app permissions.
They are not rooted.
Now, denying permissions (and rooted) means that they have some sort of SUPERUSER management app, and that's where this next part comes in.
I would then proceed to use PackageManager to retrieve a list of all packages and then check them against the handful SuperUser management apps available, namely the ones by Koush, ChainsDD, and Chainfire
The relevant package names are:
com.noshufou.android.su
eu.chainfire.supersu
com.koushikdutta.superuser
Use those methods which will help you check for root
public static boolean findBinary(String binaryName) {
boolean found = false;
if (!found) {
String[] places = { "/sbin/", "/system/bin/", "/system/xbin/",
"/data/local/xbin/", "/data/local/bin/",
"/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/" };
for (String where : places) {
if (new File(where + binaryName).exists()) {
found = true;
break;
}
}
}
return found;
}
private static boolean isRooted() {
return findBinary("su");
}
Now try to check whether the device is rooted.
if (isRooted() == true){
//Do something to prevent run this app on the device
}
else{
//Do nothing and run app normally
}
For example you can force stop the app if the device is rooted
If you are trying to protect data for the user, it's their business to worry about other apps.
If you are trying to protect data from the user, what business do you have putting it on their device?
To answer your question, they are in control of the machine so expect them to be able to trap any call to an API checking 'Is this rooted?' and lie to you. Instead, encrypt the data on the client with a key known to the client, but make it non-obvious where and how you are doing it. Generally make things annoying for whoever is looking.
Enjoy the ensuing game of whack-a-mole. Every time someone cracks into it, you'll make a better fix, they'll make a better crack, and all along the way you will be raising the barrier for cracking it.
Don't fight against freedom - why should you turn away customers with free devices anyway? - instead, if you want a particular outcome, make it so Bother To Get Data > Value Of Getting Data. Then it won't happen. If you truly must have fool-proof security, keep the data server-side.
I believe that one of the 'drawbacks' of the traditional copy protection was that it did not allow the application to be installed on rooted devices, but it also has its own share of problems and will be deprecated soon.
As for client-side checks, you simply cannot rely on a programmatic approach to detect if you're running on a rooted device or not -- anything that is in client-side code can and will be hacked and removed. You'd be surprised at how easy it is to modify even Proguard-obfuscated code. At best, you force the hacker to spend a few hours or days to edit the code and recompile. This is security through obscurity, and not a viable protection mechanism.
1) no. how would you deny installation? why would a rooted device deny installation of something the user wants to install on the fs? being the whole point of rooting that you can make the device do basically whatever.
2) no. not for your purposes. you can check if you can gain root for your application through the usual methods. so you can make a check for a positive but you cannot prove programmatically that it is not rooted, from within your app.
also, what you are asking if you can make perfect copy protection drm system - you might also be missing the point that the user can alter your application, removing your root check. if you have a checksum/crc check of some kind, the user can fake the result of that as well.