I have seen some apps where you get an in-app reward for installing another app. These are usually able to check whether or not the app is present on the device, and I'm wondering how they're able to do this.
How can I, from an Android app, check if a specific app is installed on the device?
Define a method that returns true if the PackageManager can find it:
Example:
private boolean checkThisApp(String uri) {
PackageManager myPackageManager = getPackageManager();
boolean app_installed;
try {
myPackageManager.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
}
catch (PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed;
}
and use it in the Activity/Fragment like:
boolean isAppInstalled = checkThisApp("com.facebook.katana");
Related
I am trying to build a parental control app. So now i want to disable or lock app (like Whatsapp, Facebook, etc). I have tried using PackageManager.setComponentEnabledSetting(). But it is throwing java.lang.SercurityException.
So how can I make a parental control app such that I can disable any app I want without root.
my code is
pm.setComponentEnabledSetting(new ComponentName(temp.activityInfo.packageName,
temp.activityInfo.name+".class"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
my error was this
java.lang.SecurityException: Permission Denial: attempt to change component state from pid=11537, uid=10067, package uid=10029
You must add below permissions to manifest.
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
but , these permissions are for System apps and you can not use. :(
You can not write a app to lock or close another app.this is a policy in Google.
for lock a app you must check running apps repeatedly, if specific app is open,then show a activity over that.
while(!Thread.currentThread().isInterrupted())
{
String topActivity = getFrontApp();
if(topActivity.isEmpty())
{
threadSleep(500);
continue;
}
if(topActivity.equals("lockApp"))
{
showLockActivity();
}
threadSleep(500);
}
// for Api21+ need permission
public static String getFrontApp()
{
if (Build.VERSION.SDK_INT >= 21)
{
UsageStatsManager usageManager = SystemMaster.getUsageStatsManager();
long now = System.currentTimeMillis();
List<UsageStats> localList = usageManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, now - 900_000L, now);
String str = "";
if (localList != null)
{
SortedMap<Long,UsageStats> mySortedMap = new TreeMap<>();
for(UsageStats usageStats : localList)
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
if(!mySortedMap.isEmpty())
str = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
return str;
}
else
{
ActivityManager am = (ActivityManager) getApplication().getSystemService(Context.ACTIVITY_SERVICE);
return am.getRunningTasks(1).get(0).topActivity.getPackageName();
}
above code is very simple , for real app must write more.
I have an android VPN app running on OpenVPN core, so I want to check if a specific app is installed, on connecting the app, it will stop and request for such app to be uninstalled before it works.
I have seen such on an app using JSON for all the app id blacklisted and I really don't know to go about it on my own app.
here is the JSON image file:
Blacklist.json
thank you.
You need to figure out what is the right package name of any installed application on your device.
Getting Package Info:
private boolean isPackageInstalled(String packageName, PackageManager packageManager) {
try {
packageManager.getPackageInfo(packageName, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
Then you can check in here like,
PackageManager pm = context.getPackageManager();
boolean isInstalled = isPackageInstalled("com.somepackage.name", pm);
if(isInstalled) {
// NO VPN
}
else {
// start your service
}
Check if an app, for example, Instagram is started by user.
Note: My app is targeting lollipop and above versions in android
Yeah the only way you can do it is through the Accessibility Service. Look at this page to understand how to create it. https://developer.android.com/training/accessibility/service.html They will also need to enable the service via the services -> accessibility screen.
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED you can probably interrogate the package in front to figure out if Instigram is on top.
You definitely don't want to use getRunningTasks since the function was modified in Android 5.0+
I figured out that I can do this by using usage access feature.
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static String getForegroundProcess(Context context) {
String topPackageName = null;
UsageStatsManager usage = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> stats = usage.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (stats != null) {
SortedMap<Long, UsageStats> runningTask = new TreeMap<Long,UsageStats>();
for (UsageStats usageStats : stats) {
runningTask.put(usageStats.getLastTimeUsed(), usageStats);
}
if (runningTask.isEmpty()) {
return null;
}
topPackageName = runningTask.get(runningTask.lastKey()).getPackageName();
}
if(topPackageName==null) {
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
context.startActivity(intent);
}
return topPackageName;
}
Now continuously check if the desired app is in the foreground.
String fg=getForegroundProcess(getApplicationContext());
if(fg != null && fg.contains("com.instagram.android")){
//Instagram is in foreground
}else {
}
I continuously run the above code with a job service.Which is available for
lollipop and above.
I have a small functionality. Switching on the torch and keeping it on, till the user switches it off from my app or my app exits. Using :
params = camera.getParameters();
if (params.getFlashMode().equals(Parameters.FLASH_MODE_TORCH)) {
isFlashOn = true;
return;
}
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
And to switch off :
if (params.getFlashMode().equals(Parameters.FLASH_MODE_OFF)) {
isFlashOn = false;
return;
}
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.stopPreview();
But I notice that this is not very robust. Works fine the first time, but after that (especially on my API levle 22 phone) might not work. I was thinking of testing with the android.hardware.camera2 as suggested here
Plan to use if (android.os.Build.VERSION.SDK_INT >20) and a strategy (a base interface implemented by two classes, one using old API and one the new camera2 API.
Is this safe on all devices? I saw that we can do it for android classes, but is it okay for our own classes too? Or are there devices which scan all our code and reject it if it has code that refers to API it does not know about?
I do not want to make two APKs as its a small functionality.
I make sure flash is available like this , not tested on all devices but in an emulator by Genymotion app did not crash.
public boolean torchInit() {
try {
PackageManager pm = app.getPackageManager();
// First check if device supports flashlight
boolean hasFlash = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (!hasFlash) {
Toast.makeText(app, "Flash not found or can\'t get hold of it. No torch", Toast.LENGTH_LONG).show();
return false;
}
camera = Camera.open();
Camera.Parameters params = camera.getParameters();
Log.i(LogId, "camera params flash: " + params.getFlashMode());
return true;
} catch (Throwable e) {
Log.e(LogId, "cameraFlashSetup " + e, e);
Toast.makeText(app, "Flash error, no torch. Description : " + e, Toast.LENGTH_LONG).show();
camera = null;
}
return false;
}
The flash interface to change between the two classes is :
public abstract class TorchInterface {
protected AppCompatActivity app;
public void init(AppCompatActivity ap){
app = ap;
}
public abstract boolean torchInit();
public boolean torchReInit(){
return torchInit();//if re init is not different than init
}
public abstract boolean torchOn();
public abstract boolean torchOff();
}
Update: new code worked but only if I:
mBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
Instead of:
mBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL);
But then switches on flash as soon as init the app. I was going to chuck it, then realised on my Camera2Impl I can :
public boolean torchInit() {
//do nothing on usual init that app calls on create
return true;
}
And instead do the init on torch on (flash on):
public boolean torchOn() {
//if not in it, try first 3 times
if(mBuilder == null || mSession == null){
if(firstFewTimesTorchOn > 0){
firstFewTimesTorchOn--;
torchInit2();
try{
Thread.sleep(150);
}catch(Exception e){}
if(mBuilder == null || mSession == null) {
return false;
}
}
}
try {
mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);//and etc
Android devices do not "scan" code - compiler does. Therefore, I don't see any issue with your idea. On contrary - using Strategy pattern is way better then if-else all over the code.
Something along these lines should work:
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
mFlashlightStrategy = new PostLollipopStrategy();
} else {
mFlashlightStrategy = new PreLollipopStrategy();
}
Is this safe on all devices?
Why dont't you put one check whether flash is available or not.
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
which will return true if a flash is available, false if not. You can write your further code in true block.
My Problem... I have accessed the Camera App from my third party app , I then take a picture. then I go to the Menu and I have added in a menuitem (MENUITEM_CAMERA_PREVIEW) . My menu item must perform a function and once it has I want my app to close the camera and open the previose screen before the Camera app was opened.
I am facing the same problems as this thread :
http://supportforums.blackberry.com/t5/Java-Development/How-to-exit-camera-app-properly/m-p/1924127#M209092
Can someone please tell me they understand the solution, if not and you maybe know the solution your help would be much appreciated.
I have seen these post:
Closing the default camera in Blackberry programatically after taking a picture
http://supportforums.blackberry.com/t5/Java-Development/Unable-to-close-camera-using-EventInjector-for-touch-screen/m-p/785247#M143879
How to exit a blackberry application from another application programatically?
But I am not sure what I am supposed to add to exit the camera application from my third party application.
Can Someone Please help me understand....
Trying to close the Camera app from your app is tricky. I don't know of a clean way to do it, but I have done it this way.
Basically, your app needs to request permission
ApplicationPermissions.PERMISSION_INPUT_SIMULATION
to inject keystrokes. It will then simulate the pressing of the ESC key, which is how a user would/could close the Camera app manually. To make this technique more reliable, I need to have the code (conditionally) inject the ESC key multiple times.
The way I make this more reliable is that I have a Screen in my app that is showing, before I launch the Camera app. I then monitor that screen to see when it has been exposed again. When I detect that it has been exposed, I assume that I must have injected enough ESC key sequences to close the Camera (or I guess the user could have pressed ESC themselves, to get back to my app).
Update: per comment below, here is some additional code I used in this solution, to detect proper Camera closure by monitoring the exposed state of one of my Screens below it:
private boolean _isExposed = false;
protected void onExposed() {
super.onExposed();
_isExposed = true;
}
protected void onObscured() {
super.onObscured();
_isExposed = false;
}
public boolean isExposed() {
return _isExposed;
}
You can also set _isExposed to false in whatever method you use to open the Camera app in the first place, if you like.
This is the code I ended up using, its much better.
public class MyScreen extends MainScreen{
Player _p;
VideoControl _videoControl;
FileConnection fileconn;
String PATH;
String GetfileName;
LabelField GetPhotofileName = new LabelField("",LabelField.FOCUSABLE){
protected boolean navigationClick(int status, int time){
Dialog.alert("Clicked");
return true;
}
};
public static boolean SdcardAvailabulity() {
String root = null;
Enumeration e = FileSystemRegistry.listRoots();
while (e.hasMoreElements()) {
root = (String) e.nextElement();
if( root.equalsIgnoreCase("sdcard/") ) {
return true;
}else if( root.equalsIgnoreCase("store/") ) {
return false;
}
}
class MySDListener implements FileSystemListener {
public void rootChanged(int state, String rootName) {
if( state == ROOT_ADDED ) {
if( rootName.equalsIgnoreCase("sdcard/") ) {
}
} else if( state == ROOT_REMOVED ) {
}
}
}
return true;
}
protected boolean invokeAction(int action){
boolean handled = super.invokeAction(action);
if(SdcardAvailabulity()){
PATH = System.getProperty("fileconn.dir.memorycard.photos")+"Image_"+System.currentTimeMillis()+".jpg";//here "str" having the current Date and Time;
} else {
PATH = System.getProperty("fileconn.dir.photos")+"Image_"+System.currentTimeMillis()+".jpg";
}
if(!handled){
if(action == ACTION_INVOKE){
try{
byte[] rawImage = _videoControl.getSnapshot(null);
fileconn=(FileConnection)Connector.open(PATH);
if(fileconn.exists()){
fileconn.delete();
}
fileconn.create();
OutputStream os=fileconn.openOutputStream();
os.write(rawImage);
GetfileName =fileconn.getName();
fileconn.close();
os.close();
Status.show("Image is Captured",200);
GetPhotofileName.setText(GetfileName);
if(_p!=null)
_p.close();
}catch(Exception e){
if(_p!=null){
_p.close();
}
if(fileconn!=null){
try{
fileconn.close();
}catch (IOException e1){
}
}
}
}
}
return handled;
}
public MyScreen(){
setTitle("Camera App");
try{
_p = javax.microedition.media.Manager.createPlayer("capture://video?encoding=jpeg&width=1024&height=768");
_p.realize();
_videoControl = (VideoControl) _p.getControl("VideoControl");
if (_videoControl != null){
Field videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field");
_videoControl.setDisplayFullScreen(true);
_videoControl.setVisible(true);
_p.start();
if(videoField != null){
add(videoField);
}
}
}catch(Exception e){
if(_p!=null) {
_p.close();
}
Dialog.alert(e.toString());
}
add(GetPhotofileName);
}
}