33import android .Manifest ;
44import android .content .Context ;
55import android .content .Intent ;
6+ import android .content .IntentSender ;
67import android .content .pm .PackageManager ;
78import android .net .Uri ;
89import android .os .Bundle ;
1415
1516import androidx .annotation .NonNull ;
1617import androidx .appcompat .app .AppCompatActivity ;
18+ import androidx .core .content .ContextCompat ;
1719
1820import com .ahmadabuhasan .qrbarcode .databinding .ActivityMainBinding ;
1921import com .google .android .gms .ads .AdRequest ;
2022import com .google .android .gms .ads .MobileAds ;
23+ import com .google .android .gms .tasks .Task ;
24+ import com .google .android .material .snackbar .Snackbar ;
25+ import com .google .android .play .core .appupdate .AppUpdateInfo ;
26+ import com .google .android .play .core .appupdate .AppUpdateManager ;
27+ import com .google .android .play .core .appupdate .AppUpdateManagerFactory ;
28+ import com .google .android .play .core .install .InstallStateUpdatedListener ;
29+ import com .google .android .play .core .install .model .AppUpdateType ;
30+ import com .google .android .play .core .install .model .InstallStatus ;
31+ import com .google .android .play .core .install .model .UpdateAvailability ;
2132import com .google .zxing .Result ;
2233
2334import me .dm7 .barcodescanner .zxing .ZXingScannerView ;
3041public class MainActivity extends AppCompatActivity implements ZXingScannerView .ResultHandler {
3142
3243 private static final int PERMISSION_CODE = 100 ;
44+ private static final int FLEXIBLE_APP_UPDATE_REQ_CODE = 123 ;
3345 private static final String FLASH_STATE = "FLASH_STATE" ;
3446 private static long pressedTime ;
3547 private boolean flashlight ;
3648 private ZXingScannerView zXingScannerView ;
49+ private AppUpdateManager appUpdateManager ;
50+ private InstallStateUpdatedListener installStateUpdatedListener ;
51+
3752 private ActivityMainBinding binding ;
3853
3954 @ Override
@@ -46,6 +61,18 @@ protected void onCreate(Bundle savedInstanceState) {
4661 requestPermissions (new String []{Manifest .permission .CAMERA }, PERMISSION_CODE );
4762 }
4863
64+ appUpdateManager = AppUpdateManagerFactory .create (this );
65+ checkUpdate ();
66+ installStateUpdatedListener = state -> {
67+ if (state .installStatus () == InstallStatus .DOWNLOADED ) {
68+ popupSnackBarForCompleteUpdate ();
69+ } else if (state .installStatus () == InstallStatus .INSTALLED ) {
70+ removeInstallStateUpdateListener ();
71+ } else {
72+ Toast .makeText (getApplicationContext (), "InstallStateUpdatedListener: state: " + state .installStatus (), Toast .LENGTH_LONG ).show ();
73+ }
74+ };
75+
4976 MobileAds .initialize (this , initializationStatus -> {
5077
5178 });
@@ -144,6 +171,60 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
144171 return super .onOptionsItemSelected (item );
145172 }
146173
174+ public void onActivityResult (int requestCode , int resultCode , Intent data ) {
175+ super .onActivityResult (requestCode , resultCode , data );
176+ if (requestCode == FLEXIBLE_APP_UPDATE_REQ_CODE ) {
177+ if (resultCode == RESULT_CANCELED ) {
178+ Toast .makeText (getApplicationContext (), "Update canceled by user! " , Toast .LENGTH_LONG ).show ();
179+ } else if (resultCode == RESULT_OK ) {
180+ Toast .makeText (getApplicationContext (), "Update success! " , Toast .LENGTH_LONG ).show ();
181+ } else {
182+ Toast .makeText (getApplicationContext (), "Update failed! " , Toast .LENGTH_LONG ).show ();
183+ checkUpdate ();
184+ }
185+ }
186+ }
187+
188+ private void checkUpdate () {
189+ Task <AppUpdateInfo > appUpdateInfoTask = appUpdateManager .getAppUpdateInfo ();
190+
191+ appUpdateInfoTask .addOnSuccessListener (appUpdateInfo -> {
192+ if (appUpdateInfo .updateAvailability () == UpdateAvailability .UPDATE_AVAILABLE && appUpdateInfo .isUpdateTypeAllowed (AppUpdateType .FLEXIBLE )) {
193+ startUpdateFlow (appUpdateInfo );
194+ } else if (appUpdateInfo .installStatus () == InstallStatus .DOWNLOADED ) {
195+ popupSnackBarForCompleteUpdate ();
196+ }
197+
198+ });
199+ }
200+
201+ @ SuppressWarnings ("deprecation" )
202+ private void startUpdateFlow (AppUpdateInfo appUpdateInfo ) {
203+ try {
204+ appUpdateManager .startUpdateFlowForResult (appUpdateInfo , AppUpdateType .FLEXIBLE , this , FLEXIBLE_APP_UPDATE_REQ_CODE );
205+ } catch (IntentSender .SendIntentException e ) {
206+ e .printStackTrace ();
207+ }
208+ }
209+
210+ private void popupSnackBarForCompleteUpdate () {
211+ Snackbar snackbar =
212+ Snackbar .make (
213+ findViewById (R .id .layout_activity_main ),
214+ "An update has just been downloaded." ,
215+ Snackbar .LENGTH_INDEFINITE );
216+ snackbar .setAction ("RESTART" , view -> appUpdateManager .completeUpdate ());
217+ snackbar .setActionTextColor (
218+ ContextCompat .getColor (this , R .color .red ));
219+ snackbar .show ();
220+ }
221+
222+ private void removeInstallStateUpdateListener () {
223+ if (appUpdateManager != null ) {
224+ appUpdateManager .unregisterListener (installStateUpdatedListener );
225+ }
226+ }
227+
147228 public void onBackPressed () {
148229 if (pressedTime + 2000 > System .currentTimeMillis ()) {
149230 finishAndRemoveTask ();
0 commit comments