How to support auto in-app updates Android example in Java - java

I tried these libraries found on github but i didn't find a way to test if the updates really works ?
how to support auto in-app updates android?

i found this artical that solve this issue to make it clear i'll write the class code and remember there is two methods to implement in-app updates: immediate and flexible.
1 implementation 'com.google.android.play:core:1.10.3'
2.1 if you will use flexible method replace the class name with yours exemple 'MainActivity'
public class Flexible extends AppCompatActivity {
private AppUpdateManager appUpdateManager;
private InstallStateUpdatedListener installStateUpdatedListener;
private static final int FLEXIBLE_APP_UPDATE_REQ_CODE = 123;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_f);
appUpdateManager = AppUpdateManagerFactory.create(getApplicationContext());
installStateUpdatedListener = state -> {
if (state.installStatus() == InstallStatus.DOWNLOADED) {
popupSnackBarForCompleteUpdate();
} else if (state.installStatus() == InstallStatus.INSTALLED) {
removeInstallStateUpdateListener();
} else {
Toast.makeText(getApplicationContext(), "InstallStateUpdatedListener: state: " + state.installStatus(), Toast.LENGTH_LONG).show();
}
};
appUpdateManager.registerListener(installStateUpdatedListener);
checkUpdate();
}
private void checkUpdate() {
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
startUpdateFlow(appUpdateInfo);
} else if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) {
popupSnackBarForCompleteUpdate();
}
});
}
private void startUpdateFlow(AppUpdateInfo appUpdateInfo) {
try {
appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.FLEXIBLE, this, Flexible.FLEXIBLE_APP_UPDATE_REQ_CODE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FLEXIBLE_APP_UPDATE_REQ_CODE) {
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Update canceled by user! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_OK) {
Toast.makeText(getApplicationContext(),"Update success! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Update Failed! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
checkUpdate();
}
}
}
private void popupSnackBarForCompleteUpdate() {
Snackbar.make(findViewById(android.R.id.content).getRootView(), "New app is ready!", Snackbar.LENGTH_INDEFINITE)
.setAction("Install", view -> {
if (appUpdateManager != null) {
appUpdateManager.completeUpdate();
}
})
.setActionTextColor(getResources().getColor(R.color.purple_500))
.show();
}
private void removeInstallStateUpdateListener() {
if (appUpdateManager != null) {
appUpdateManager.unregisterListener(installStateUpdatedListener);
}
}
#Override
protected void onStop() {
super.onStop();
removeInstallStateUpdateListener();
}}
2.1 if you will use Immediate method replace the class name with yours exemple 'MainActivity'
public class Immediate extends AppCompatActivity {
private AppUpdateManager appUpdateManager;
private static final int IMMEDIATE_APP_UPDATE_REQ_CODE = 124;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_f);
appUpdateManager = AppUpdateManagerFactory.create(getApplicationContext());
checkUpdate();
}
private void checkUpdate() {
Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo();
appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
startUpdateFlow(appUpdateInfo);
} else if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS){
startUpdateFlow(appUpdateInfo);
}
});
}
private void startUpdateFlow(AppUpdateInfo appUpdateInfo) {
try {
appUpdateManager.startUpdateFlowForResult(appUpdateInfo, AppUpdateType.IMMEDIATE, this, Immediate.IMMEDIATE_APP_UPDATE_REQ_CODE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == IMMEDIATE_APP_UPDATE_REQ_CODE) {
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Update canceled by user! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_OK) {
Toast.makeText(getApplicationContext(), "Update success! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Update Failed! Result Code: " + resultCode, Toast.LENGTH_LONG).show();
checkUpdate();
}
}
}}
3 How to test? please follow all the steps
3.1 Generate a signed app bundle/APK. Note that the APK signing key and the applicationId should be the same as the already published application.
3.2 Share the generated APK with a tester. To do that, select the published application in the Google console, navigate to Internal App Sharing, and upload the generated APK there. Check how to use Google Internal App Sharing.
3.3 Copy the upload’s shareable link and share it with a tester. In this case, the tester should have an Android mobile phone.
3.4 Open the shared link on the phone’s browser. You will be redirected to the Play store.
3.5 Download the app and wait for the installation to complete.
3.6 Once done, generate another signed app bundle/APK. This time change versionCode and versionName in your app.gradle file to a higher version
3.7 Once you have generated the app bundle/APK, head to App Internal Sharing and upload it.
3.8 Again, copy the shareable link generated by this upload and open it with the tester. When the link launches on the Google Play store, you will get an update button, do not click update.
3.9 Close the Google Play store and open the application we installed earlier. This will launch an update UI that will prompt you to update the application. The UI may differ depending on your update type (either flexible or immediate).

Related

How to use system_alert_window popup in java

I need to have my app draw over other apps, and I tried getting SYSTEM_ALERT_WINDOW permission shown below.
public class excessiveusageactivity extends AppCompatActivity {
static final int REQUEST_OVERLAY_PERMISSION = 1; //request code
TextView result;
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
result = findViewById(R.id.result);
if (requestCode == REQUEST_OVERLAY_PERMISSION) {
if (Settings.canDrawOverlays(this)) {
Toast permissionok = Toast.makeText(this, "permission granted!", Toast.LENGTH_SHORT);
permissionok.show();
//permission granted do stuff
result.setText("yay");
}else{
Toast permissionnotgrantedtoast = Toast.makeText(this,"permission request failed, try again!", Toast.LENGTH_LONG);
permissionnotgrantedtoast.show();
//permission not granted
result.setText("not granted");
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_excessiveusageactivity);
if(
Settings.canDrawOverlays(this)
) {
// ask for overlay permission
Intent requestoverlaypermissionintent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(requestoverlaypermissionintent, REQUEST_OVERLAY_PERMISSION);
result.setText("here");
}
}
}
I got this code from here by user Jayman Jani.
I wish to make a custom system alert popup when the user uses an app for X minutes/hour consecutively, but I can't seem to find any information on how to set up this popup. I am quite new to all this so it would be great if someone can explain it mostly step-by-step. Thank you!

Get Google Drive Folder Name and Path using DriveId

I am using google drive api contents given on GitHub for selecting folder. With below code , I could able to get folder id to transfer data but I m not able to get folder name or folder path. Can some one help over this? I tried to use asDriveFolder but did not get required info.
Here is code to get drive Id of selected folder.
public class GoogleFolderSelector extends GoogleDriveBaseActivity {
String TAG = "Google Folder Picker";
private static final int REQUEST_CODE_OPENER = 1;
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
IntentSender intentSender = Drive.DriveApi
.newOpenFileActivityBuilder()
.setMimeType(new String[]{DriveFolder.MIME_TYPE})
.build(getGoogleApiClient());
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.w(TAG, "Unable to send intent", e);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
try {
switch (requestCode) {
case REQUEST_CODE_OPENER:
if (resultCode == RESULT_OK) {
DriveId driveId = (DriveId) data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
DriveFolder driveFolder = driveId.asDriveFolder();
showMessage("Folder Path"+ driveFolder);
showMessage("Selected folder's ID: " + driveId);
}
finish();
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
} catch (Exception e) {
e.printStackTrace();
Popup.longpopup("Connection Established, Click to select Folder", this);
}
}
}
In order to get folder name, let use meta data as below
Task<Metadata> getMetadataTask = getDriveResourceClient().getMetadata(file);
getMetadataTask
.addOnSuccessListener(this,
metadata -> {
showMessage(getString(
R.string.metadata_retrieved, metadata.getTitle()));
finish();
})
.addOnFailureListener(this, e -> {
Log.e(TAG, "Unable to retrieve metadata", e);
showMessage(getString(R.string.read_failed));
finish();
});
Here is the full instruction
For the folder path, I used to try to retrieve but it seems it is not necessary as you could manipulate everything with driveId such as add file into this driveId folder or create another folder inside this driveId folder. Explore google sample app will give you a better sight.

Make the application wait until the location services has been turned on?

I have an application that depends on location services being enabled.
Thus, when the user starts the application- a dialog box appears and it checks if the location service is enabled or not. However, I want the application to pause until the user goes to the settings page (Which he is redirected to on clicking "okay" in the dialog box) and enables location services. Once he does, he should be able to return back to the MainActivity and the code should continue where he left off.
If I don't let the app pause, the code just continues and tries to execute code that requires the location services to be on, and the app crashes.
I currently have this, so how can I modify it so that it waits?
if(!location_enabled) {
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setMessage("Location services are currently not " +
"enabled. You must enable this in order to continue. Would you like to do this now?");
dialog.setPositiveButton("Take me to location services", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
// WAIT UNTIL LOCATION SERVICES ENABLED
}
});
dialog.setNegativeButton(context.getString(R.string.Cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
//EXIT APPLICATION
}
});
dialog.show();
}
if(location_enabled) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) {
//DO FANCY STUFF WITH LOCATION
}
}
You can easily use startActivityForResult in your case.
When you're starting the settings to enable your location, you may start the intent like this.
// Declare a global variable first
private final int ACTION_LOCATION_SETTING = 100;
// Now change the onClickListener like this
dialog.setPositiveButton("Take me to location services", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
Intent locationSettingIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(locationSettingIntent, ACTION_LOCATION_SETTING);
}
});
Now when you return from the location setting, you'll get a callback here.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ACTION_LOCATION_SETTING:
if (resultCode == Activity.RESULT_OK) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) {
//DO FANCY STUFF WITH LOCATION
}
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
Simple!

Integrating ZXing in my application

I need to build an app which will recognize QR codes without forcing the user to install other apps. In future, I will also need to manipulate the scanned image before recognizing the code (codes scanned by me will have inverted colors).
Trying to follow hints and tutorials from these links:
Integrating the ZXing library directly into my Android application
Embedding ZXing in android app
http://karanbalkar.com/2013/12/tutorial-65-implement-barcode-scanner-using-zxing-in-android/
After creating some basic code and running the app I click my Scan button and get an error that No Activity found to handle Intent { act=com.google.zxing.client.android.SCAN (has extras) }
What I've done:
Create new project
Copy core-3.2.1.jar to libs/
Add intent calling and result handling
intent/result code added by me:
private Button scan;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scan= (Button)findViewById(R.id.btnScan);
scan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
// Handle successful scan
MultiFormatWriter writer = new MultiFormatWriter();
} else if (resultCode == RESULT_CANCELED) {
// Handle cancel
Log.i("App","Scan unsuccessful");
}
}
}
How to start the intent? What am I doing wrong?
you should launch scan like this:
#Override
public void onClick(View v) {
IntentIntegrator integrator = new IntentIntegrator(MainActivity.this);
integrator.setDesiredBarcodeFormats(IntentIntegrator.ALL_CODE_TYPES);
//in case you want to customize a bit.
integrator.setPrompt("Scan a QR/Bar code");
integrator.setCameraId(0);
integrator.setBeepEnabled(false);
integrator.initiateScan();
}
Receive results like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case IntentIntegrator.REQUEST_CODE: {
if (resultCode != RESULT_CANCELED) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
String data = scanResult.getContents();
// use this data
} else {
// error
}
break;
}
}
}
Edit 1:
Add this to build.gradle of your app as dependencies:
compile 'com.journeyapps:zxing-android-embedded:3.0.2#aar'
compile 'com.google.zxing:core:3.2.0'
Try the below link it worked for me:
https://github.com/dlazaro66/QRCodeReaderView

Android Speech Recogntion won't work in a separate class

I'm a beginner in Android development. What I'm trying to create is an app the speaks to you then waits for your answer so its kind of text to speech works ,then it activates speech recognition and with my code the text to speech works then it calls speech recognition.Then an erro msg is shown ,the catch block is executed.
The problem is that I have to add Speech Recognition in a separate class, then add an Object of it in the Adapter not Main Activity. Speech Recognition won't work and since all tutorials for speech recognition for Android are adding the code in Main Activity and I'm doing it as class called in the adapter is the problem ?
UPDATE startActivityForResult() method is not working
Here is the code for SpeechRecogntion class
public class SpeechRecog extends Activity {
private static final int VOICE_RECOGNITION_REQUEST_CODE = 1001;
String textResult ;
public void Start (Intent i , Context c){
i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
i.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Are You Done , yet? ");
try{
startActivityForResult(i,VOICE_RECOGNITION_REQUEST_CODE);
} catch(Exception e) {
Toast.makeText(c, "SpeechRecogntion is not avalible on your device ", Toast.LENGTH_LONG).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ((requestCode == VOICE_RECOGNITION_REQUEST_CODE)&& (resultCode== RESULT_OK)) {
textResult= data.getStringExtra(RecognizerIntent.EXTRA_RESULTS);
if (checkResult())
Toast.makeText(getApplicationContext(), "You are done ", Toast.LENGTH_LONG).show();
else
Toast.makeText(getApplicationContext(), "You are not done ", Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
private boolean checkResult() {
if (textResult.equals("done")||(textResult.equals("yes")))
return true ;
return false;
}
}
And Here is the object of it in the Adapter class
private SpeechRecog mySP;
private Intent mySpIntetn ;
public ListAdapterClass(Context context) {
mytts = new TxtToSpeechClass(context);
mySP = new SpeechRecog();
}
And Here is where my problem relies ,the on clicklistener inside the Adapter class
Lh.btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
if (Lh.btn.getText().equals("Play"))
{
Lh.btn.setText("Pause"); //change the btn status so user know how to stop it
List<Items> hResults=db.getAllItems(Lh.idList + 1);
for (int i = 0; i < hResults.size(); i++)
{
Items item = hResults.get(i);
String s = item.getItemname();
mytts.Talk(s,1);
mySP.Start(mySpIntetn , context ); //the code in here wont work is there something I'm missing here
Toast.makeText(context,s, Toast.LENGTH_SHORT).show();
}
mytts.Talk("Congrats ",1);// 1 means Queue_add
} else {
Lh.btn.setText("Play");
mytts.Talk("See you later", 0); // 0 means Queue_Flush
}
}
);
mySpIntetn is private. Try to change it to public in the Adapter class.

Categories