We are creating an app where you can share an app, which sends the user to the google play store to download another app.
My question is, how can I know if some user actually downloaded and installed that app?
Is there a some sort of callback you get from the play store?
Try calling startActivityForResult() with the Play Store intent. Then, override the onActivityResult() method in your Activity and check if the app is installed. This might help: How to check programmatically if an application is installed or not in Android?
isAppInstalledBefore("com.example.anappblabla");
private boolean isAppInstalledBefore(String packageName) {
PackageManager pm = getPackageManager();
boolean installed = false;
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
installed = true;
} catch (PackageManager.NameNotFoundException e) {
installed = false;
}
return installed; //returns boolean
}
No, but:
What I would do is trying to get the package name (generally in the URL for example: https://play.google.com/store/apps/details?id=dev.laurentmeyer.contactautocompleteview of the target app (which is unique): something like dev.laurentmeyer.whateverApp (it's the one I'm personally using). Then scan the installed apps with this Helper and you'll be sure if it has been installed or not.
Related
This question already has answers here:
Android L (5.x) Turn ON/OFF "Mobile Data" programmatically
(3 answers)
Closed 2 years ago.
Although this is a "duplicate", the current answers are out of date and, mostly, no longer apply. I thought it would be good to provide an updated resource here, if possible, to save people time, as I have just done, researching this issue.
I've been googling around to see the latest information on being able to enable and disable mobile data from within an app (if wifi is not available).
This is one of the latest things I can find:
Did you know you can no longer Disable/Enable Data on lollipop from a widget?
There is an answer to that, I quote:
There was never an API for it. Developers were using a workaround by calling the method via Reflections. All Google did was close this "exploit".
There is also this discussion:
Replacement for setMobileDataEnabled() api
Which is Feb 2015.
There are these questions here:
How to disable Mobile Data on Android
This was asked in 2010 and the latest answer was updated with a one liner on Dec 2014.
Enable/disable data connection in android programmatically
And this, the accepted answer in 2012.
What's the latest on this issue?
Can it still be done?
It wont work on non-rooted phone as they added MODIFY_PHONE_STATE permission check. This permission is only given to system or signature apps refer-here.
Check the code below from PhoneInterfaceManager:
#Override
public void setDataEnabled(boolean enable) {
enforceModifyPermission();
mPhone.setDataEnabled(enable);
}
private void enforceModifyPermission() {
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
}
Unless you have a rooted phone I don't think you can enable and disable data programmatically because in order to do so we have to include MODIFY_PHONE_STATE permission which is only given to system or signature apps.
setMobileDataEnabled() method is no longer callable via reflection. It was callable since Android 2.1 (API 7) to Android 4.4 (API 19) via reflection, but as of Android 5.0 and later, even with the rooted phones, the setMobileDataEnabled() method is not callable.
Fast forward to the end of 2018...
The short answer is it is no longer allowed to enable/disable mobile data programmatically. Here is the solution that I use all the time.
This code opens system data usage settings screen, where the user can disable mobile data manually.
public void enableDisableMobileData() {
Intent intent = new Intent();
intent.setComponent(new ComponentName(
"com.android.settings",
"com.android.settings.Settings$DataUsageSummaryActivity"));
startActivity(intent);
}
EDIT 2019:
The answer above does not work starting on API 28. This is what works:
Intent intent = new Intent(Settings.ACTION_DATA_USAGE_SETTINGS);
startActivity(intent);
None of the above worked for me, but if your device is rooted, you may use this for enabling it.
private void enableMobileData(){
try {
String[] cmds = {"svc data enable"};
Process p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd + "\n");
}
os.writeBytes("exit\n");
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
And this for disabling it:
private void disableMobileData(){
try {
String[] cmds = {"svc data disable"};
Process p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd + "\n");
}
os.writeBytes("exit\n");
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
Easy Method.
public void setMobileDataState(boolean mobileDataEnabled)
{
try{
ConnectivityManager dataManager;
dataManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
Method dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", boolean.class);
dataMtd.setAccessible(true);
dataMtd.invoke(dataManager, mobileDataEnabled);
}catch(Exception ex){
//Error Code Write Here
}
}
I have published my app now and found that it is creating two shortcut icons where as when I install through android studio it creates only one shortcut. I have added duplicate false and sharedpreference has also been used to check once icon is created. Why the app behaving different and how can I fix it now? This is my code for creating shortcut.
public void createShortCut() {
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(StartupActivity.this).edit();
editor.putBoolean("shortcut", true).apply();
Intent shortcutintent = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
shortcutintent.putExtra("duplicate", false);
shortcutintent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Smart App");
Parcelable icon = Intent.ShortcutIconResource.fromContext(getApplicationContext(), R.mipmap.ic_launcher);
shortcutintent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
shortcutintent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(getApplicationContext(), SplashScreen.class));
sendBroadcast(shortcutintent);
}
and before calling above method I have below code which runs on activity start.
if (!sharedPreferences.getBoolean("shortcut", false)) {
createShortCut();
}
When you install from Android Studio (directly from an .apk), no shortcut is made. However, apps installed from the Google Play Store will automatically sometimes create a shortcut after installation.
So when a user installs your app from the play store, two shortcuts are made, one from your app and one from the installation.
EDIT: This solution might prove useful to you: How to detect shortcut in Home screen
I am trying to write a simple piece of code that will execute some other code if true. What I want to do is check if my app is running on the 'Amazon Fire-TV (BOX, not the Fire-TV stick)' I think it would not be that hard to do but I am guessing it would be something like this?
String osName = android.getSystemOS();
if(!osName.equals("AMAZON FIRE-TV")){
Toast.makeText(MainActivity.class, "This app may not be compatible with your device..., Toast.LENGTH_LONG").show();
...
}
You can check any device name specifically using:
boolean isFireTV = Build.MODEL.equalsIgnoreCase("AFTB");
(see this page for FireTV model strings, and this one for Fire Tablets)
I'd also check out this answer for a more generic test to help you determine if your app is running on an Amazond device, or installed via the Amazon AppStore (eg on a Blackberry device)
the following function:
public static boolean isTV() {
return android.os.Build.MODEL.contains("AFT");
}
should detect either firetv or fire tv stick
see
https://developer.amazon.com/public/solutions/devices/fire-tv/docs/amazon-fire-tv-sdk-frequently-asked-questions
for details
My development phone is a Nexus 5, running Android 4.4.2.
In my application, I am attempting to create a folder on external storage that will store debug information for my application. Basically it will contain all the commands executed by the application, so that when a user encounters a problem, I have the option of having them send me the information from the debug folder to analyse.
I started off by trying to write a file to the folder, but found there was an error creating the folder. At first I was using mkdir(), then I moved onto mkdirs() which also didn't work.
I have <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in my manifest.
Here is the code for creating the folder:
File folder = new File(Environment.getExternalStorageDirectory() + "/DebugData");
String path = folder.getPath();
if(!folder.mkdirs() || !folder.exists()){
Log.e(LOG_TAG, path + " failed");
} else {
Log.d(LOG_TAG, path + " succeeded");
}
Here is what I have also tried:
//Check SD card state
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) || !Environment.MEDIA_MOUNTED.equals(state)) {
Log.e(LOG_TAG, "Error: external storage is read only or unavailable");
} else {
Log.d(LOG_TAG, "External storage is not read only or unavailable");
}
This returns that the external storage is not read only or unavailable.
I have also tried different paths, such as File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Folder1");
This is where it became really confusing.
I tried development on different phones. Firstly, I grabbed a Galaxy S4 GT-i9505 running Android 4.2.2 and it worked. I was able to create the folders and write to them. This showed me that the code was working. Also the path returned by running the code on the S4 and Nexus 5 was the same.
Then I thought it may be android version specific. So I grabbed a Nexus 4 with Android 4.4.2 and the code worked on it as well. Created the folders and allowed me to write to them.
None of the phones are rooted and are all stock standard. There's no special applications or anything I can think of settings wise on the Nexus 5 that would cause permissions problems. The connection is set to Media Device (MTP).
EDIT:
I should add that I have tried the follow which also did not work:
Writing a file to the root directory of the external storage
Creating the file in the external storage root directory and writing to it
Creating a folder in a path outlined and writing a file to it
Creating the file in the path outlined and writing to it
I am confused as to what is causing this, is there anything else I can test or change to fix the issue?
EDIT 2:
Turns out the issue was due to, I think, indexing.
Basically all of the other devices I tested on, allowed me to reconnect the USB connection and view the created files and folders.
For some reason my Nexus 5 doesn't index the folders/files, even though they exist.
I downloaded a different 3rd party file explorer application and noticed all the folders and files were there.
So to view these folders and files via USB debugging, I have to restart the phone in order to re-index them, which seems quite annoying but it is better than it not working at all.
Thanks.
In terms of this being an indexing issue with the Nexus, this worked for me:
MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
You should call it straight after creating and saving the file. By using the scanner, I was able to see newly created files and directories simply by replugging the device in.
According to the docs:
MediaScannerConnection provides a way for applications to pass a newly
created or downloaded media file to the media scanner service. The
media scanner service will read metadata from the file and add the
file to the media content provider.
Hope this helps someone else.
Turns out the issue was due to, I think, indexing.
Basically all of the other devices I tested on, allowed me to reconnect the USB connection and view the created files and folders.
For some reason my Nexus 5 doesn't index the folders/files, even though they exist.
I downloaded a different 3rd party file explorer application and noticed all the folders and files were there.
So to view these folders and files via USB debugging, I have to restart the phone in order to re-index them, which seems quite annoying but it is better than it not working at all.
For android sdk version 23 and above you should check if the user has granted permission of external storage.
private void createFolder() {
if (isStoragePermissionGranted()) {
File folder = new File(Environment.getExternalStorageDirectory()+ File.separator + "DebugData");
if(!folder.exists()){
folder.mkdir();
}
}
public boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
return true;
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
return true;
}
}
The code above worked for me and I hope it will work for you.
Had the same problem. Turned out I was testing on Android 6 and did not check for runtime WRITE_EXTERNAL_STORAGE permission.
First, new File() is just create object for file connect.
you want use this file, file is exists or createNewFile().
If you want use this file to create directory, check file is exists, isDirectory() after then mkDir().
Second, check Environment.getExternalStorageDirectory is variable path.
You can use DDMS or ADB for work.
Additionaly, I think you add permission for read external storage for something error.
If you are running an Android device with api >= 23, you need to request permission from user before you call mkdir() function.
My previous answer with example code can be found
https://stackoverflow.com/a/38694026/5089713
For Android 10+ add following into manifest:
<application
android:requestLegacyExternalStorage="true"
...
as asking for Manifest.permission.WRITE_EXTERNAL_STORAGE is no more enough.
Typically, I do this:
/**
* Return a dedicated directory named "MyApp" at the top of external storage
*/
public static file getDataDir() {
File sdcard = Environment.getExternalStorageDirectory();
if( sdcard == null || !sdcard.isDirectory() ) {
// TODO: warning popup
Log.w(TAG, "Storage card not found " + sdcard);
return null;
}
File dataDir = new File(sdcard, "MyApp");
if( !confirmDir(dataDir) ) {
// TODO: warning popup
Log.e(TAG, "Unable to create " + dataDir);
return null;
}
return dataDir;
}
private static boolean confirmDir(File dir) {
if (dir.isDirectory()) return true; // already exists
if (dir.exists()) return false; // already exists, but is not a directory
return dir.mkdirs(); // create it
}
Also, add this permission to your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
If you want private storage (typically under /data/) for your app (not on sdcard), then look into getDir(), getFilesDir(), fileList(), openFileInput(), openFileOutput(), etc.
There are also helper functions to get private directories within the sdcard for API 8 and above: getExternalFilesDir(), getExternalCacheDir(), etc.
I would to like to know if Is there any to check if I am running the application in a emulator or real phone? I want to change some configuration when I am testing in the netbeans/emulador and when it goes to real mobile phone change to another configuration such as server address. Is there any java me function to check it?
You have to use this code.
String platform = System.getProperty("microedition.platform");
platform = platform.toUpperCase();
if ((platform.indexOf("J2ME") != -1) || (platform.equalsIgnoreCase("SunMicrosystems_wtk"))) {
//EMULATOR
}else {
//Device
}
If you are using other emulator you can try doing System.out.println(platform) and see what print when yo are using on emulator
You can add a property in JAD, and just change that property when you build for real device
for example :
device-name: emulator
and you can read it in MIDlet using
getAppProperty("device-name");