In app update in android always give UpdateAvailability.UPDATE_NOT_AVAILABLE - java

I am using in-app update but it is not working in production. I tried various ways but could not resolve the issue. The code is in java for android studio project
My code is below:-
private void checkUpdate() {
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
Toast.makeText(getApplicationContext(), "Update available", Toast.LENGTH_LONG).show();
startUpdateFlow(appUpdateInfo);
} else if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS){
Toast.makeText(getApplicationContext(), "Reached 2.. ", Toast.LENGTH_LONG).show();
startUpdateFlow(appUpdateInfo);
} else if (appUpdateInfo.updateAvailability()==UpdateAvailability.UPDATE_NOT_AVAILABLE){
Toast.makeText(getApplicationContext(), "Update unavailable", Toast.LENGTH_LONG).show();
Intent intent = new Intent(getApplicationContext(), StartActivity.class);
startActivity(intent);
finish();
}
});
}
```
Please tell me what is the mistake I am doing

You have not created the code to force App Update. I also created code for app updates and mine is a Flexible update. Match your code with mine and make changes in your code or use my code to test your app.
private void inAppUpdate() {
appUpdateManager = AppUpdateManagerFactory.create(this);
Task<AppUpdateInfo> task = appUpdateManager.getAppUpdateInfo();
task.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
try {
appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.FLEXIBLE, MainActivity.this, APP_UPDATE_CODE);
} catch (IntentSender.SendIntentException e) {
Log.d("Update", e.getMessage());
}
} else if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
snackPopup();
}
});
appUpdateManager.registerListener(istListener);
}
Let me know if my code does not work in your app.

Thanks to #Martijn Pieters for reminding me to either tailor my answer or suggest as possible duplicate. I'd agree with #M-Dev you need to call appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.FLEXIBLE, MainActivity.this, APP_UPDATE_CODE); to start the update correctly.
You could also add appUpdateInfoTask.addOnFailureListener {} or appUpdateInfoTask.addOnCompleteListener to check that its successfully checking google play for new versions.
You should check that it works with internal App sharing.
Please also see my post on how Google App signing can cause problems with in-app updates in production

Related

How to delay an app's closure till all the code finishes executing?

I have a dialog that tells the user that their trial has ended and then redirects them to the full version on the Play Store. When the dialog is dismissed the app should close so that the user can no longer use it. Problem is that sometimes this leads to the app getting closed before it gets the chance to open the Play Store link.
Here's the dialog:
private void showTrialEndedDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialog_regular);
builder.setTitle("Trial ended")
.setMessage("To continue using the app you can purchase the full version from the Play Store")
.setPositiveButton("Go to Play Store", (dialog, which) -> {
final String appPackageName = "com.braapproductions.redalertemulatorpro";
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
} catch (ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}
})
.setNegativeButton("Cancel", (dialog, which) -> {
})
.setOnDismissListener(dialog -> closeApp())
.create().show();
}
public void closeApp() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAndRemoveTask(); //closes the application
} else {
finishAffinity();
System.exit(0); //use these two lines of code are for older versions of android
}
}
Most of the time when pressing the button to go to the Play Store, the app just closes instead of opening the Play Store link, though it does work sometimes. So apparently the app is being closed before the startActivity() command is reached. How can I make it wait till everything is finished before it closes?
How can I make it wait till everything is finished before it closes?
Don't try to "close" your app.
Your Problem
When you open the app store that instance of the activity is in your app's task list. Therefore calling finishAndRemoveTask will close the app store along with your app.
A Solution
Just use a regular finish call - killing the entire task is unnecessary.
.setOnDismissListener(dialog -> finish())
And definitely avoid using System.exit(0) - that's an anti-pattern. Worry about your Activities - let the Android framework worry your app's process.
You could post a delay using a Handler before closing the app:
public void closeApp() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAndRemoveTask(); //closes the application
} else {
finishAffinity();
System.exit(0); //use these two lines of code are for older versions of android
}
}
}, 3000); // 3 seconds
}
private void showTrialEndedDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
AlertDialog builderDialog;
builder.setTitle("Trial ended")
.setMessage("To continue using the app you can purchase the full version from the Play Store")
.setPositiveButton("Go to Play Store", (dialog, which) -> {
})
.setNegativeButton("Cancel", (dialog, which) -> {
})
.setOnDismissListener(dialog -> closeApp());
builderDialog = builder.create();
builderDialog.show();
builderDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(view -> {
final String appPackageName = "com.braapproductions.redalertemulatorpro";
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
} catch (ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}
builderDialog.dismiss();
});
}
public void closeApp() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAndRemoveTask(); //closes the application
} else {
finishAffinity();
System.exit(0); //use these two lines of code are for older versions of android
}
}

Android Studio Emulator bug? Alarm sound keeps looping even if I set mediaPlayer.setLooping(false)

I am not sure if this is just an emulator bug or did I miss something. I am writing an alarm app. My app gets a ringtone Uri with RingToneManager, then use MediaPlayer to play the ringtone Uri. I want to control whether the ringtone loops or not. It works fine on my real smartphone, as well as with the Android Studio emulator using Uri gets with RingtoneManager.TYPE_NOTIFICATION and RingtoneManager.TYPE_RINGTONE. However, if I use Uri gets with RingtoneManager.TYPE_ALARM with the emulator, it just keeps looping even if I set mediaPlayer.setLooping(false).
This seems like an emulator bug to me. However, I want to make sure I do not miss something that I need to set. I do not want to find out after the app is released and it turned out that other people's smartphones have the same problem as the emulator. Is there anything I can do or check?
Below is the related code:
activeAlarmSound = new MediaPlayer();
activeAlarmSound.setAudioAttributes(
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_ALARM)
.build()
);
try {
activeAlarmSound.setDataSource(this, Uri.parse(ringToneString));
if (!hasBGMusic && !timeUpItem.sayDate && !timeUpItem.sayDay && !timeUpItem.sayTime) {
activeAlarmSound.setLooping(true);
} else {
activeAlarmSound.setLooping(false);
}
activeAlarmSound.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
if (playedBGMusic && timeUpItem.getDismissMethod() == 0) {
stopSelf();
} else {
playedAlarmSound = true;
if (activeBGMusic == null) {
playBGMusic();
} else {
activeBGMusic.start();
}
if (timeUpItem.getRepeatAlarm() > 0) {
endAlarmHandler = new Handler();
endAlarmHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (activeBGMusic != null) {
activeBGMusic.pause();
}
playAlarmSoundAndTime();
}
}, timeUpItem.getRepeatAlarm() * 60000);
}
}
}
});
activeAlarmSound.prepare();
activeAlarmSound.start();
} catch (IOException e) {
e.printStackTrace();
}```

Android AppUpdateManager not initializing the auto update

I want to update my app immediately every time I publish an update. I followed the instructions from the official android documentation on how to test the auto update feature , but nothing happens. I placed some logs in order to check whether these functions initialize, but the logcat shows nothing either. Is this a problem in my syntax, or should I place these functions somewhere else? Currently, all my update code is written inside the main, starting class of the app.
On create method of the class
private static final int REQUEST_APP_UPDATE = 560;
private AppUpdateManager appUpdateManager;
private InstallStateUpdatedListener installStateUpdatedListener;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
appUpdateManager = AppUpdateManagerFactory.create(this);
installStateUpdatedListener = new
InstallStateUpdatedListener() {
#Override
public void onStateUpdate(InstallState state) {
if (state.installStatus() == InstallStatus.DOWNLOADED){
} else if (state.installStatus() == InstallStatus.INSTALLED){
if (appUpdateManager != null){
appUpdateManager.unregisterListener(installStateUpdatedListener);
}
} else {
Log.i(TAG, "InstallStateUpdatedListener: state: " + state.installStatus());
}
}
};
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
appUpdateInfo -> {
Log.d("TAG", "here");
// Checks that the platform will allow the specified type of update.
if ((appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE)
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE))
{
// Request the update.
try {
Log.d("TAG", "here");
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
REQUEST_APP_UPDATE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
appUpdateManager.registerListener(installStateUpdatedListener);
...
On resume and on stop handling methods:
#Override
protected void onResume() {
super.onResume();
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
appUpdateInfo -> {
if (appUpdateInfo.updateAvailability()
== UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
// If an in-app update is already running, resume the update.
try {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
REQUEST_APP_UPDATE);
Log.d("TAG", "tu");
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
}
#Override
protected void onStop() {
super.onStop();
if (appUpdateManager != null) {
appUpdateManager.unregisterListener(installStateUpdatedListener);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_APP_UPDATE) {
if (resultCode != RESULT_OK) {
Log.d("TAG", "Update flow failed! Result code: " + resultCode);
// If the update is cancelled or fails,
// you can request to start the update again.
}
}
}
I suggest you to move all your AppUpdateInfo retrieving to onResume() since it is more reliable entry point of an activity (for example, if Activity has came to background and then was opened again by user). OnCreate method will be called only if activity was destroyed, since that, you may not see update dialog after reopening application if it was minimized.
#Override
public void onResume() {
super.onResume();
appUpdateManager.getAppUpdateInfo().addOnSuccessListener( info -> {
boolean isStalledUpdate = info.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS;
boolean isReadyForUpdate =
info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE;
if (isReadyForUpdate || isStalledUpdate) {
appUpdateManager.startUpdateFlowForResult(
info,
AppUpdateType.IMMEDIATE,
this,
REQ_CODE
);
}
}
Sometimes app is not automatically synchronized with Play Store updates, so you need to do the following:
Make sure you have an update available manually - go to Play Store, check for updates and make sure that you have an update available for your application.
After that open your app (your activity, that calls update manager in onResume) and you will see immediate update dialog.
Also, one tip for you - make your Activity implement InstallStateUpdateListener and override method onStateUpdate like this to handle different events.
#Override
public void onResume() {
// All previous logic
// If update is available or was stalled call this
appUpdateManager.registerListener(this);
}
#Override
public void onStateUpdate(InstallState state) {
if (state == null) return;
switch (state.installStatus()) {
case InstallStatus.INSTALLED:
appUpdateManager.unregisterListener(this)
return;
case InstallStatus.FAILED:
appUpdateManager.unregisterListener(this)
return;
case InstallStatus.CANCELED:
appUpdateManager.unregisterListener(this)
return;
default:
// provide your own logic
return;
}
}
This will help you to avoid calling separate instance of listener in activity lifecycle methods.
The code that I provided was working, the problem of not updating was a matter of the device itself not knowing whether an update is available. After refreshing the update list on the Play Store, the app update manager initialized the auto update window when starting the app.

Android 6.0 instagram image sharing using intent not working

I have this code that works fine on other versions of android but seems like its misbehaving on android 6.0.
There is no error as such but the image is not posted.
public void onClick(View v) {
Intent intent = getPackageManager().getLaunchIntentForPackage("com.instagram.android");
if (intent != null)
{
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setPackage("com.instagram.android");
try {
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), imagePath, "I am Happy", "Share happy !")));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
shareIntent.setType("image/jpeg");
startActivity(shareIntent);
}
else
{
// bring user to the market to download the app.
// or let them choose an app?
intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("market://details?id="+"com.instagram.android"));
startActivity(intent);
}
}
As Amir suggested, You need to allow permissions to each and every app for every feature. Steps : Android settings -> apps -> select app -> permissions -> allow all those permissions that you want to share.
It's because of Instagram permissions. You have to allow storage in:
Android settings -> apps -> Instagram -> permissions
Probably it is because of android permissions. They have some changes in android 6. Check this link to understand. Go to the device settings>apps and select your app then accept permissions manually and check if your problem is solved.

Android barcode scanner app ,after pressing the scan button the camera does not open

I am using android studio with intentintegrator and intentResult classes for a barcode scanner app. The scan button does not open up the camera to scan. I have checked the code with all the tutorials and it is correct with no errors on build. I have all the permissions and libraries imported. All suggestions welcome thanks
I had your same issue and took me alot of time to find the reason...it's due to the permission....check your camera code you will find a code some thing like this:
`if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkPermission()) {
Toast.makeText(this, "Premission granted", Toast.LENGTH_LONG).show();
} else {
requestPermissions();
}
}`
this means that the permission will be send and granted to the devices which have only andriod version "M" or above...you can rewrite the if condition to send the permission to lower versions...for me I made it start from "JELLY_BEAN_MR1" and the if condition is like this :
` if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (checkPermission()) {
Toast.makeText(this, "Premission granted", Toast.LENGTH_LONG).show();
} else {
requestPermissions();
}
}`
and make sure to rewrite every if condition to the same thing.
Hope this will help you :)

Categories

Resources