AndroidUtilCode | :fire: Android developers should collect the following utils(updating) | Android library

 by   Blankj Java Version: 1.31.1 License: Apache-2.0

kandi X-RAY | AndroidUtilCode Summary

AndroidUtilCode is a Java library typically used in Mobile, Android applications. AndroidUtilCode has no bugs, it has no vulnerabilities, it has build file available, it has a Permissive License and it has medium support. You can download it from GitHub, Maven.
AndroidUtilCode :fire: is a powerful & easy to use library for Android. This library encapsulates the functions that commonly used in Android development which have complete demo and unit test. By using it's encapsulated APIs, you can greatly improve the development efficiency. The program mainly consists of two modules which is utilcode, which is commonly used in development, and subutil which is rarely used in development, but the utils can be beneficial to simplify the main module. :fire:.
    Support
      Quality
        Security
          License
            Reuse
            Support
              Quality
                Security
                  License
                    Reuse

                      kandi-support Support

                        summary
                        AndroidUtilCode has a medium active ecosystem.
                        summary
                        It has 31968 star(s) with 10562 fork(s). There are 1182 watchers for this library.
                        summary
                        There were 1 major release(s) in the last 6 months.
                        summary
                        There are 245 open issues and 1270 have been closed. On average issues are closed in 120 days. There are 10 open pull requests and 0 closed requests.
                        summary
                        It has a neutral sentiment in the developer community.
                        summary
                        The latest version of AndroidUtilCode is 1.31.1
                        AndroidUtilCode Support
                          Best in #Android
                            Average in #Android
                            AndroidUtilCode Support
                              Best in #Android
                                Average in #Android

                                  kandi-Quality Quality

                                    summary
                                    AndroidUtilCode has 0 bugs and 0 code smells.
                                    AndroidUtilCode Quality
                                      Best in #Android
                                        Average in #Android
                                        AndroidUtilCode Quality
                                          Best in #Android
                                            Average in #Android

                                              kandi-Security Security

                                                summary
                                                AndroidUtilCode has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
                                                summary
                                                AndroidUtilCode code analysis shows 0 unresolved vulnerabilities.
                                                summary
                                                There are 0 security hotspots that need review.
                                                AndroidUtilCode Security
                                                  Best in #Android
                                                    Average in #Android
                                                    AndroidUtilCode Security
                                                      Best in #Android
                                                        Average in #Android

                                                          kandi-License License

                                                            summary
                                                            AndroidUtilCode is licensed under the Apache-2.0 License. This license is Permissive.
                                                            summary
                                                            Permissive licenses have the least restrictions, and you can use them in most projects.
                                                            AndroidUtilCode License
                                                              Best in #Android
                                                                Average in #Android
                                                                AndroidUtilCode License
                                                                  Best in #Android
                                                                    Average in #Android

                                                                      kandi-Reuse Reuse

                                                                        summary
                                                                        AndroidUtilCode releases are available to install and integrate.
                                                                        summary
                                                                        Deployable package is available in Maven.
                                                                        summary
                                                                        Build file is available. You can build the component from source.
                                                                        AndroidUtilCode Reuse
                                                                          Best in #Android
                                                                            Average in #Android
                                                                            AndroidUtilCode Reuse
                                                                              Best in #Android
                                                                                Average in #Android
                                                                                  Top functions reviewed by kandi - BETA
                                                                                  kandi has reviewed AndroidUtilCode and discovered the below as its top functions. This is intended to give you an instant insight into AndroidUtilCode implemented functionality, and help decide if they suit your requirements.
                                                                                  • Get the country code from the map .
                                                                                    • Stack bitmap .
                                                                                      • Convert a Uri to a File .
                                                                                        • Update char sequence .
                                                                                          • Handle touch event .
                                                                                            • Initialize the title bar .
                                                                                              • Returns the RomInfo object
                                                                                                • Visit a method .
                                                                                                  • Operations operations .
                                                                                                    • Returns the foreground process name .
                                                                                                      Get all kandi verified functions for this library.
                                                                                                      Get all kandi verified functions for this library.

                                                                                                      AndroidUtilCode Key Features

                                                                                                      :fire: Android developers should collect the following utils(updating).

                                                                                                      AndroidUtilCode Examples and Code Snippets

                                                                                                      No Code Snippets are available at this moment for AndroidUtilCode.
                                                                                                      Community Discussions

                                                                                                      Trending Discussions on Android

                                                                                                      Captured Image is not storing in android 11
                                                                                                      chevron right
                                                                                                      How to set Image resource for an Image view Dynamically in android using Data binding
                                                                                                      chevron right
                                                                                                      Android: Iterative queue-based flood fill algorithm 'expandToNeighborsWithMap()' function is unusually slow
                                                                                                      chevron right
                                                                                                      Mandatory Consent for Admob User Messaging Platform
                                                                                                      chevron right
                                                                                                      Huawei auth service integration with .net core 3.1, unable to validate JWT
                                                                                                      chevron right
                                                                                                      viewmodel factory class doesn't work after update lifecycle version
                                                                                                      chevron right
                                                                                                      Android 12: How to prevent activity restart on changing phone wallpaper?
                                                                                                      chevron right
                                                                                                      Why did Android Application start 3 times on single launch?
                                                                                                      chevron right
                                                                                                      Android: Resource linking fails on test execution even when nothing has been changed
                                                                                                      chevron right
                                                                                                      Library to change to fix Google app publish error; Billing Library version 3 in android studio
                                                                                                      chevron right

                                                                                                      QUESTION

                                                                                                      Captured Image is not storing in android 11
                                                                                                      Asked 2022-Mar-02 at 10:46

                                                                                                      I'm unable to store captured image in (getExternalFilesDir(Environment.DIRECTORY_PICTURES)) Android 11 device.

                                                                                                      I have added in manifest and all file access also. But it's not working.

                                                                                                      if (Build.VERSION.SDK_INT >= 30) {
                                                                                                                  if (!Environment.isExternalStorageManager()) {
                                                                                                                      try {
                                                                                                                          val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
                                                                                                                          intent.addCategory("android.intent.category.DEFAULT")
                                                                                                                          intent.data = Uri.parse(String.format("package:%s", applicationContext.packageName))
                                                                                                                          startActivityForResult(intent, 2296)
                                                                                                                      } catch (e: Exception) {
                                                                                                                          val intent = Intent()
                                                                                                                          intent.action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
                                                                                                                          startActivityForResult(intent, 2296)
                                                                                                                      }
                                                                                                                  }
                                                                                                              }
                                                                                                      

                                                                                                      This code is working below Android 11 device. But on Android 11 file is not creating File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) .toString() + "/" + FolderName )

                                                                                                      ANSWER

                                                                                                      Answered 2021-Jul-31 at 10:25

                                                                                                      use this code for save captured image

                                                                                                      String mPath = Environment.getExternalStorageDirectory() + "/Print";
                                                                                                          Bitmap tmp = BitmapFactory.decodeFile(mPath);
                                                                                                      
                                                                                                       File imageFile = new File(mPath);
                                                                                                      
                                                                                                      
                                                                                                          FileOutputStream outStream;
                                                                                                      
                                                                                                          try
                                                                                                          {
                                                                                                              outStream = new FileOutputStream(imageFile);
                                                                                                      
                                                                                                              try
                                                                                                              {
                                                                                                                  bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);
                                                                                                                  outStream.flush();
                                                                                                                  outStream.close();
                                                                                                              } catch (IOException e)
                                                                                                              {
                                                                                                                  e.printStackTrace();
                                                                                                              }
                                                                                                      
                                                                                                          } catch (Exception e)
                                                                                                          {
                                                                                                              e.printStackTrace();
                                                                                                          }
                                                                                                      

                                                                                                      Source https://stackoverflow.com/questions/68600921

                                                                                                      QUESTION

                                                                                                      How to set Image resource for an Image view Dynamically in android using Data binding
                                                                                                      Asked 2021-Dec-31 at 10:36

                                                                                                      can someone let me know the right usage of populating image resource in Image view using Data Binding

                                                                                                      ANSWER

                                                                                                      Answered 2021-Dec-31 at 10:21

                                                                                                      You can use it in such way:

                                                                                                      
                                                                                                      

                                                                                                      more info can be found here and here plus docs.

                                                                                                      Source https://stackoverflow.com/questions/70541212

                                                                                                      QUESTION

                                                                                                      Android: Iterative queue-based flood fill algorithm 'expandToNeighborsWithMap()' function is unusually slow
                                                                                                      Asked 2021-Dec-30 at 04:27

                                                                                                      (Solution has been found, please avoid reading on.)

                                                                                                      I am creating a pixel art editor for Android, and as for all pixel art editors, a paint bucket (fill tool) is a must need.

                                                                                                      To do this, I did some research on flood fill algorithms online.

                                                                                                      I stumbled across the following video which explained how to implement an iterative flood fill algorithm in your code. The code used in the video was JavaScript, but I was easily able to convert the code from the video to Kotlin:

                                                                                                      https://www.youtube.com/watch?v=5Bochyn8MMI&t=72s&ab_channel=crayoncode

                                                                                                      Here is an excerpt of the JavaScript code from the video:

                                                                                                      Converted code:

                                                                                                      Tools.FILL_TOOL -> {
                                                                                                                  val seedColor = instance.rectangles[rectTapped]?.color ?: Color.WHITE
                                                                                                      
                                                                                                                  val queue = LinkedList()
                                                                                                      
                                                                                                                  queue.offer(MathExtensions.convertIndexToXYPosition(rectangleData.indexOf(rectTapped), instance.spanCount.toInt()))
                                                                                                      
                                                                                                                  val selectedColor = getSelectedColor()
                                                                                                      
                                                                                                                  while (queue.isNotEmpty() && seedColor != selectedColor) { // While the queue is not empty the code below will run
                                                                                                                      val current = queue.poll()
                                                                                                                      val color = instance.rectangles.toList()[convertXYDataToIndex(instance, current)].second?.color ?: Color.WHITE
                                                                                                      
                                                                                                                      if (color != seedColor) {
                                                                                                                          continue
                                                                                                                      }
                                                                                                      
                                                                                                                      instance.extraCanvas.apply {
                                                                                                                          instance.rectangles[rectangleData[convertXYDataToIndex(instance, current)]] = defaultRectPaint // Colors in pixel with defaultRectPaint
                                                                                                                          drawRect(rectangleData[convertXYDataToIndex(instance, current)], defaultRectPaint)
                                                                                                      
                                                                                                                          for (index in expandToNeighborsWithMap(instance, current)) {
                                                                                                                              val candidate = MathExtensions.convertIndexToXYPosition(index, instance.spanCount.toInt())
                                                                                                                              queue.offer(candidate)
                                                                                                                          }
                                                                                                                      }
                                                                                                                  }
                                                                                                              }
                                                                                                      

                                                                                                      Now, I want to address two major issues I'm having with the code of mine:

                                                                                                      • Performance

                                                                                                      • Flooding glitch (fixed by suggestion from person in the comments)

                                                                                                      Performance

                                                                                                      A flood fill needs to be very fast and shouldn't take less than a second, the problem is, say I have a canvas of size 50 x 50, and I decide to fill in the whole canvas, it can take up to 8 seconds or more.

                                                                                                      Here is some data I've compiled for the time it's taken to fill in a whole canvas given the spanCount value:

                                                                                                      spanCount approx time taken in seconds to fill whole canvas 10 <1 seconds 20 ~2 seconds 40 ~6 seconds 60 ~15 seconds 100 ~115 seconds

                                                                                                      The conclusion from the data is that the flood fill algorithm is unusually slow.

                                                                                                      To find out why, I decided to test out which parts of the code are taking the most time to compile. I came to the conclusion that the expandToNeighbors function is taking the most time out of all the other tasks:

                                                                                                      Here is an excerpt of the expandToNeighbors function:

                                                                                                      fun expandToNeighbors(instance: MyCanvasView, from: XYPosition): List {
                                                                                                          var asIndex1 = from.x
                                                                                                          var asIndex2 = from.x
                                                                                                      
                                                                                                          var asIndex3 = from.y
                                                                                                          var asIndex4 = from.y
                                                                                                      
                                                                                                          if (from.x > 1) {
                                                                                                              asIndex1 = xyPositionData!!.indexOf(XYPosition(from.x - 1, from.y))
                                                                                                          }
                                                                                                      
                                                                                                          if (from.x < instance.spanCount) {
                                                                                                              asIndex2 = xyPositionData!!.indexOf(XYPosition(from.x + 1, from.y))
                                                                                                          }
                                                                                                      
                                                                                                          if (from.y > 1) {
                                                                                                              asIndex3 = xyPositionData!!.indexOf(XYPosition(from.x, from.y - 1))
                                                                                                          }
                                                                                                      
                                                                                                          if (from.y < instance.spanCount) {
                                                                                                              asIndex4 = xyPositionData!!.indexOf(XYPosition(from.x, from.y + 1))
                                                                                                          }
                                                                                                      
                                                                                                          return listOf(asIndex1, asIndex2, asIndex3, asIndex4)
                                                                                                      } 
                                                                                                      

                                                                                                      To understand the use of the expandToNeighbors function, I would recommend watching the video that I linked above.

                                                                                                      (The if statements are there to make sure you won't get an IndexOutOfBoundsException if you try and expand from the edge of the canvas.)

                                                                                                      This function will return the index of the north, south, west, and east pixels from the xyPositionData list which contains XYPosition objects.

                                                                                                      (The black pixel is the from parameter.)

                                                                                                      The xyPositionData list is initialized once in the convertXYDataToIndex function, here:

                                                                                                      var xyPositionData: List? = null
                                                                                                      var rectangleData: List? = null
                                                                                                      
                                                                                                      fun convertXYDataToIndex(instance: MyCanvasView, from: XYPosition): Int {
                                                                                                      
                                                                                                          if (rectangleData == null) {
                                                                                                              rectangleData = instance.rectangles.keys.toList()
                                                                                                          }
                                                                                                      
                                                                                                          if (xyPositionData == null) {
                                                                                                              xyPositionData = MathExtensions.convertListOfSizeNToListOfXYPosition(
                                                                                                                  rectangleData!!.size,
                                                                                                                  instance.spanCount.toInt()
                                                                                                              )
                                                                                                          }
                                                                                                      
                                                                                                          return xyPositionData!!.indexOf(from)
                                                                                                      }
                                                                                                      

                                                                                                      So, the code works fine (kind of) but the expandToNeighbors function is very slow, and it is the main reason why the flood fill algorithm is taking a long time.

                                                                                                      My colleague suggested that indexOf may be slowing everything down, and that I should probably switch to a Map-based implementation with a key being XYPosition and a value being Int representing the index, so I replaced it with the following:

                                                                                                      fun expandToNeighborsWithMap(instance: MyCanvasView, from: XYPosition): List {
                                                                                                          var asIndex1 = from.x
                                                                                                          var asIndex2 = from.x
                                                                                                      
                                                                                                          var asIndex3 = from.y
                                                                                                          var asIndex4 = from.y
                                                                                                      
                                                                                                          if (from.x > 1) {
                                                                                                              asIndex1 = rectangleDataMap!![XYPosition(from.x - 1, from.y)]!!
                                                                                                          }
                                                                                                      
                                                                                                          if (from.x < instance.spanCount) {
                                                                                                              asIndex2 =  rectangleDataMap!![XYPosition(from.x + 1, from.y)]!!
                                                                                                          }
                                                                                                      
                                                                                                          if (from.y > 1) {
                                                                                                              asIndex3 =  rectangleDataMap!![XYPosition(from.x, from.y - 1)]!!
                                                                                                          }
                                                                                                      
                                                                                                          if (from.y < instance.spanCount) {
                                                                                                              asIndex4 = rectangleDataMap!![XYPosition(from.x, from.y + 1)]!!
                                                                                                          }
                                                                                                      
                                                                                                          return listOf(asIndex1, asIndex2, asIndex3, asIndex4)
                                                                                                      }
                                                                                                      

                                                                                                      It functions the same way, only this time it uses a Map which is initialized here:

                                                                                                      var xyPositionData: List? = null
                                                                                                      var rectangleData: List? = null
                                                                                                      var rectangleDataMap: Map? = null
                                                                                                      
                                                                                                      fun convertXYDataToIndex(instance: MyCanvasView, from: XYPosition): Int {
                                                                                                      
                                                                                                          if (rectangleData == null) {
                                                                                                              rectangleData = instance.rectangles.keys.toList()
                                                                                                          }
                                                                                                      
                                                                                                          if (xyPositionData == null) {
                                                                                                              xyPositionData = MathExtensions.convertListOfSizeNToListOfXYPosition(
                                                                                                                  rectangleData!!.size,
                                                                                                                  instance.spanCount.toInt()
                                                                                                              )
                                                                                                          }
                                                                                                      
                                                                                                          if (rectangleDataMap == null) {
                                                                                                              rectangleDataMap = MathExtensions.convertListToMap(
                                                                                                                  rectangleData!!.size,
                                                                                                                  instance.spanCount.toInt()
                                                                                                              )
                                                                                                          }
                                                                                                      
                                                                                                          return xyPositionData!!.indexOf(from)
                                                                                                      }
                                                                                                      

                                                                                                      Converting the code to use a map increased the speed by around 20%, although the algorithm is still slow.

                                                                                                      After spending a couple of days trying to make the algorithm work faster, I'm out of ideas and I'm unsure why the expandToNeighbors function is taking a long time. Any help would be appreciated to fix this issue.

                                                                                                      Apologies if I didn't do a good enough job of explaining the exact issue, but I have tried my best. Implementation-wise it is quite messy unfortunately because of the whole list index to XYPosition conversions, but at least it works - the only problem is the performance.

                                                                                                      So I have two one major problem, if anyone can try and find a solution for it, it would be great because I have tried to myself without much luck.

                                                                                                      I've actually pushed the fill tool to GitHub as a KIOL (Known Issue or Limitation), so the user can use the fill tool if they want, but they need to be aware of the limitations/issues. This is so anyone who wants to help me fix this can have a look at my code and reproduce the bugs.

                                                                                                      Link to repository:

                                                                                                      https://github.com/realtomjoney/PyxlMoose

                                                                                                      Edit after bounty

                                                                                                      I understand that this question is extremely difficult to answer and will require a lot of thinking. I've tried myself to fix these issues but haven't had much success, so I'm offering 50 reputation for anyone who can assist.

                                                                                                      I would recommend you clone PyxlMoose and reproduce the errors, then work from there. Relying on the code snippets isn't enough.

                                                                                                      Formula for converting XY position to an index

                                                                                                      Somebody in the comments suggested a formula for converting an XYPosition to an index value, I came up with the following method which works:

                                                                                                          fun convertXYPositionToIndex(xyPosition: XYPosition, spanCount: Int): Int {
                                                                                                              val positionX = xyPosition.x
                                                                                                              val positionY = xyPosition.y
                                                                                                      
                                                                                                              return (spanCount - positionY) + (spanCount * (positionX - 1))
                                                                                                          }
                                                                                                      

                                                                                                      The only problem is - it increases the speed by around 50% but it's still taking around 10-15 seconds to fill in an area of 80 by 80 pixels, so it has helped to a large degree although it's still very slow. But thank you very much for the suggestion anyways, it has helped a lot :)

                                                                                                      ANSWER

                                                                                                      Answered 2021-Dec-29 at 08:28

                                                                                                      I think the performance issue is because of expandToNeighbors method generates 4 points all the time. It becomes crucial on the border, where you'd better generate 3 (or even 2 on corner) points, so extra point is current position again. So first border point doubles following points count, second one doubles it again (now it's x4) and so on.

                                                                                                      If I'm right, you saw not the slow method work, but it was called too often.

                                                                                                      Source https://stackoverflow.com/questions/70490938

                                                                                                      QUESTION

                                                                                                      Mandatory Consent for Admob User Messaging Platform
                                                                                                      Asked 2021-Dec-12 at 16:09

                                                                                                      I switched from the deprecated GDPR Consent Library to the new User Messaging Platform, and used the code as stated in the documentation.

                                                                                                      I noticed that when the user clicks on Manage Options then Confirm choices, ads will stop displaying altogether (Ad failed to load, no ad config), and I can't find anyway to check if the user didn't consent to the use of personal data.

                                                                                                      This is problematic as my app relies purely on ads, and I will be losing money if ads don't show up, so I want to make it mandatory for users to consent to the use of their personal data, otherwise the app should be unusable.

                                                                                                      I have made a test project on Github so everyone can test this behavior. If you are not using an emulator, then you need to change the "TEST_DEVICE_ID" to yours.

                                                                                                      How can I achieve this?

                                                                                                      ANSWER

                                                                                                      Answered 2021-Nov-02 at 17:50

                                                                                                      I found a workaround for this, but this is no final official solution.

                                                                                                      It seems that if a user consented to Personalized ads, a string in SharedPreferences, which key is IABTCF_VendorConsents, will contain ones and zeros corresponding to some vendors (I think). If he didn't consent, this string will be equal to 0.

                                                                                                      private val sp = PreferenceManager.getDefaultSharedPreferences(appContext)
                                                                                                      fun consentedToPersonalizedAds() = sp.getString("IABTCF_VendorConsents", null) != "0"
                                                                                                      

                                                                                                      Source https://stackoverflow.com/questions/69307205

                                                                                                      QUESTION

                                                                                                      Huawei auth service integration with .net core 3.1, unable to validate JWT
                                                                                                      Asked 2021-Nov-12 at 17:04

                                                                                                      We have a react-native application running in production with firebase phone auth. Lately, we received feedback from users owning new Huawei devices not being able to authenticate with their phone numbers using firebase.

                                                                                                      Since a lot of users started having this issue, we decided to implement Huawei auth services only for devices under HarmonyOS and keep the regular firebase phone authentication for other users.

                                                                                                      After integrating the Huawei App Gallery Connect Auth SDK in our react-native app, we are able to receive the OTP and sign the user in using credentialWithVerifyCode and we are also able to retrieve the user's token using

                                                                                                      idToken =(await (await AGCAuth.getInstance().currentUser()).getToken()).token;
                                                                                                      

                                                                                                      The idToken is a JWT token that looks something like this

                                                                                                      eyJhbGciOiJIUzUxMiJ9.eyJ0b2tlbiI6IjVCMzQ5OTM5ODBFNEYxRUQwNDBDOTBEMjA1Q0U4QTJCNzRFMTg3RkUyRDNDQzY4N0E3MUVCMUZFQ0VBMDZDQTEifQ.xtAXTzfpzqRHAvDP3fJjdctnNoFHFmqawWJBGqG4y3qBSeo1XNHFyNOPnL-V6BCmkpxGIO3eq2eYJShIJhad-A
                                                                                                      

                                                                                                      The payload inside contains another token (Not JWT), but we don't think that is the problem, we also tried a token with all user information.

                                                                                                      After sending the JWT to our .NET core 3.1 web API we are unable to validate the token using JwtBearerExtensions.AddJwtBearer

                                                                                                      services
                                                                                                      .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                                                                                                      .AddJwtBearer(
                                                                                                          JwtBearerDefaults.AuthenticationScheme,
                                                                                                          o =>
                                                                                                          {
                                                                                                              o.Authority = "https://oauth-login.cloud.huawei.com";
                                                                                                          });
                                                                                                      

                                                                                                      the authority is set to https://oauth-login.cloud.huawei.com which has the issuer set to https://accounts.huawei.com which seems off because in firebase the issuer looks more like: https://securetoken.google.com/YOUR_PROJECT

                                                                                                      The error we are getting is:

                                                                                                          Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
                                                                                                      Exceptions caught:
                                                                                                       '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
                                                                                                      token: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
                                                                                                         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
                                                                                                         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
                                                                                                         at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
                                                                                                      info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7]
                                                                                                      

                                                                                                      The error is happening probably because the Authority is not correct.

                                                                                                      We can't figure out what is the problem, we are not able to find the authority we need to validate the token with.

                                                                                                      ANSWER

                                                                                                      Answered 2021-Nov-09 at 03:04

                                                                                                      You are advised to use the following method to validate the token.

                                                                                                      try {
                                                                                                      
                                                                                                        AuthAccessToken authAccessToken = agcAuth.verifyAccessToken(accessToken, true);
                                                                                                      } catch (AGCAuthException e) {
                                                                                                       if (e.getErrorCode() == AuthErrorCode.VERIFY_ACCESS_TOKEN_ACCESS_TOKEN_IS_NULL.getErrorCode()) {
                                                                                                           // The user access token is empty.
                                                                                                        } else if (e.getErrorCode() == AuthErrorCode.JWT_VERIFY_FAILED.getErrorCode()) {
                                                                                                           // Failed to authenticate the user access token.
                                                                                                        } else if (e.getErrorCode() == AuthErrorCode.JWT_EXPIRE.getErrorCode()) {
                                                                                                           // The user access token has expired.
                                                                                                        } else if (e.getErrorCode() == AuthErrorCode.JWT_REVOKED.getErrorCode()) {
                                                                                                           // The user access token has been revoked.
                                                                                                        } 
                                                                                                      
                                                                                                      

                                                                                                      For more details, pls kindly refer to this docs.

                                                                                                      Source https://stackoverflow.com/questions/69891350

                                                                                                      QUESTION

                                                                                                      viewmodel factory class doesn't work after update lifecycle version
                                                                                                      Asked 2021-Nov-09 at 05:09

                                                                                                      I was using def lifecycle_version = "2.3.1" ,

                                                                                                      implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version") .

                                                                                                      but I had to update version to def lifecycle_version = "2.4.0-alpha03" to use some features, but ViewModelProvider.Factory class doesn't work after I use def lifecycle_version = "2.4.0-alpha03".

                                                                                                      class ViewModelFactory(private val param:String,private val param2: String) : ViewModelProvider.Factory {
                                                                                                          override fun  create(modelClass: Class): T {
                                                                                                              return if (modelClass.isAssignableFrom(ReviewViewModel::class.java)) {
                                                                                                                  ReviewViewModel(param,param2) as T
                                                                                                              }else if(modelClass.isAssignableFrom(FoodViewModel::class.java)){
                                                                                                                  FoodViewModel(param,param2) as T
                                                                                                              else {
                                                                                                                  throw IllegalArgumentException()
                                                                                                              }
                                                                                                          }
                                                                                                      }
                                                                                                      

                                                                                                      the error messages are

                                                                                                      ! Class 'ViewModelFactory' is not abstract and does not implement abstract member public abstract fun create(modelClass: Class): T defined in androidx.lifecycle.ViewModelProvider.Factory

                                                                                                      ! 'create' overrides nothing

                                                                                                      Thanks..

                                                                                                      ANSWER

                                                                                                      Answered 2021-Nov-09 at 03:38

                                                                                                      You've written:

                                                                                                      override fun  create(modelClass: Class): T {
                                                                                                      

                                                                                                      But what the error message is saying is that create must always have a non-null ViewModel type. You need to change your method signature to remove the ? that indicates nullability on your :

                                                                                                      override fun  create(modelClass: Class): T {
                                                                                                      

                                                                                                      This is specifically called out in the Lifecycle 2.4 release notes:

                                                                                                      Source-breaking change: ViewModelProvider has been rewritten in Kotlin. ViewModelProvider.Factory.create method now longer allows nullable generic.

                                                                                                      Source https://stackoverflow.com/questions/69892377

                                                                                                      QUESTION

                                                                                                      Android 12: How to prevent activity restart on changing phone wallpaper?
                                                                                                      Asked 2021-Nov-06 at 05:20

                                                                                                      On Android 12,

                                                                                                      1. If we open an activity

                                                                                                      2. Go to the home screen of the phone to change the wallpaper

                                                                                                      3. Switch back to our activity, the activity restarts.

                                                                                                      It seems it is related to the Material You theming.

                                                                                                      I would like to disable the restarting of activity when my app comes to the foreground. Is there a way?

                                                                                                      ANSWER

                                                                                                      Answered 2021-Oct-31 at 18:39

                                                                                                      It is a non-traditional configuration change. By "non-traditional", I mean that it cannot be blocked by android:configChanges — your activity will be destroyed and recreated whether you like it or not.

                                                                                                      If you have Configuration objects from before and after the change, you can determine that this scenario occurred by calling diff() on the newer Configuration to compare it to the older one:

                                                                                                      val diff = resources.configuration.diff(vm.originalConfiguration)
                                                                                                      
                                                                                                      Log.d("WallpaperCCTest", "matches CONFIG_ASSETS_PATHS? ${(diff.toLong() and 0x80000000) != 0L}")
                                                                                                      

                                                                                                      Here, vm.originalConfiguration points to the older Configuration, and we get the current Configuration from the Resources object. (diff.toLong() and 0x80000000) != 0L will evaluate to true if a wallpaper change or something similar triggered the configuration change. There are other edge cases for this — this whole "unblockable configuration change" thing came about when Sony got Google to add support for runtime resource overlays (RROs) back in 2017. So, some of those "change the system theme" apps might trigger this same unblockable configuration change.

                                                                                                      As Nguyễn Hoài Nam notes, you can detect this from onConfigurationChanged() of a custom Application. Or, have your viewmodel hold onto the previous Configuration and compare it with the current one in onCreate() of your activity.

                                                                                                      I have more on this issue in this blog post. AFAIK, there is no way to opt out of this configuration change, so if your app was designed to avoid configuration changes, you may be out of luck.

                                                                                                      Source https://stackoverflow.com/questions/69741827

                                                                                                      QUESTION

                                                                                                      Why did Android Application start 3 times on single launch?
                                                                                                      Asked 2021-Nov-05 at 03:21

                                                                                                      I create an app from the template, and populate with some Logs as below

                                                                                                      class MainActivity : AppCompatActivity() {
                                                                                                          override fun onCreate(savedInstanceState: Bundle?) {
                                                                                                              super.onCreate(savedInstanceState)
                                                                                                              MainApplication.something++
                                                                                                              Log.d("Tracking", "onCreate ${MainApplication.something} ${Thread.currentThread()}")
                                                                                                              setContentView(R.layout.activity_main)
                                                                                                          }
                                                                                                      
                                                                                                          override fun onStart() {
                                                                                                              super.onStart()
                                                                                                              Log.d("Tracking", "onStart")
                                                                                                          }
                                                                                                      
                                                                                                          override fun onResume() {
                                                                                                              super.onResume()
                                                                                                              Log.d("Tracking", "onResume")
                                                                                                          }
                                                                                                      
                                                                                                          override fun onConfigurationChanged(newConfig: Configuration) {
                                                                                                              super.onConfigurationChanged(newConfig)
                                                                                                              Log.d("Tracking", "onConfigurationChanged")
                                                                                                          }
                                                                                                      
                                                                                                          override fun onPause() {
                                                                                                              super.onPause()
                                                                                                              Log.d("Tracking", "onPause")
                                                                                                          }
                                                                                                      
                                                                                                          override fun onStop() {
                                                                                                              super.onStop()
                                                                                                              Log.d("Tracking", "onStop")
                                                                                                          }
                                                                                                      
                                                                                                          override fun onSaveInstanceState(outState: Bundle) {
                                                                                                              super.onSaveInstanceState(outState)
                                                                                                              Log.d("Tracking", "onSaveInstanceState")
                                                                                                          }
                                                                                                      
                                                                                                          override fun onDestroy() {
                                                                                                              super.onDestroy()
                                                                                                              Log.d("Tracking", "onDestroy")
                                                                                                          }
                                                                                                      }
                                                                                                      

                                                                                                      and

                                                                                                      class MainApplication: Application() {
                                                                                                          companion object {
                                                                                                              var something = 0
                                                                                                          }
                                                                                                      
                                                                                                          override fun onCreate() {
                                                                                                              super.onCreate()
                                                                                                              Log.d("Tracking", "Application onCreate $something ${Thread.currentThread()}")
                                                                                                          }
                                                                                                      }
                                                                                                      

                                                                                                      When I run it, I notice that sometimes it launch 3 times. (some other times, it launch 2 times and sometimes 1 time).

                                                                                                      The log as below

                                                                                                      2021-11-04 23:55:31.409 7810-7810/com.example.empty D/Tracking: Application onCreate 0 Thread[main,5,main]
                                                                                                      2021-11-04 23:55:31.445 7810-7810/com.example.empty D/Tracking: onCreate 1 Thread[main,5,main]
                                                                                                      2021-11-04 23:55:31.409 7810-7810/com.example.empty D/Tracking: Application onCreate 0 Thread[main,5,main]
                                                                                                      2021-11-04 23:55:31.445 7810-7810/com.example.empty D/Tracking: onCreate 1 Thread[main,5,main]
                                                                                                      2021-11-04 23:55:31.508 7810-7810/com.example.empty D/Tracking: onStart
                                                                                                      2021-11-04 23:55:31.445 7810-7810/com.example.empty D/Tracking: onCreate 1 Thread[main,5,main]
                                                                                                      2021-11-04 23:55:31.509 7810-7810/com.example.empty D/Tracking: onResume
                                                                                                      2021-11-04 23:55:31.508 7810-7810/com.example.empty D/Tracking: onStart
                                                                                                      2021-11-04 23:55:31.509 7810-7810/com.example.empty D/Tracking: onResume
                                                                                                      2021-11-04 23:55:31.509 7810-7810/com.example.empty D/Tracking: onResume
                                                                                                      
                                                                                                      

                                                                                                      Initially, I thought it's the Activity gets launched 3 times, but then when I log out the Application onCreate, it also 3 times. I explicitly put a static variable something, and clearly see that the Applications are 3 different instances (since the variable didn't get incremented across the 3 times).

                                                                                                      To confirm it is not because configuration change or activity got killed (as per explained in https://stackoverflow.com/a/3588750/3286489), I also log out when onPause, onStop, onSavedInstanceState and onDestroy, none of them get called.

                                                                                                      Does anyone know why did the application start 3 times when only launch once?

                                                                                                      Note: I compiled on Android SDK 31 and 30, and Emulator API S and API 29, all of them have the same behavior. Also tried on the actual device Android 8.0. Same behavior shown.

                                                                                                      Update I notice it only happens after the second compile. Perhaps it's just a repeated uncleared Log (though I have clear it).

                                                                                                      ANSWER

                                                                                                      Answered 2021-Nov-05 at 03:21

                                                                                                      Apparently, it's an Android Studio filtering issue. I'm having the Tracking there to filter the log. And it shows multiple log of the same type.

                                                                                                      When I remove a character from the log, then the filter get corrected. After putting back the character, the filter is still okay.

                                                                                                      See the GIF below.

                                                                                                      Source https://stackoverflow.com/questions/69839732

                                                                                                      QUESTION

                                                                                                      Android: Resource linking fails on test execution even when nothing has been changed
                                                                                                      Asked 2021-Oct-18 at 21:34

                                                                                                      I'm starting to get errors when I am executing a test for a release variant which was always working fine. The code has always been executed in a Docker container so we can ensure that the build will always be clean.

                                                                                                      Today for some reason with no changes at all to the code, I am starting to see errors on the test run:

                                                                                                      Execution failed for task:
                                                                                                      am:processReleaseResources'.
                                                                                                      > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
                                                                                                         > Android resource linking failed
                                                                                                           /.gradle/caches/transforms-2/files-2.1/ff28653768e2ccb1135467db3600af3a/core-1.7.0-alpha02/res/values/values.xml:105:5-114:25: AAPT: error: resource android:attr/lStar not found.
                                                                                                      

                                                                                                      I've made some research about the error, but I only find errors related to another resource, but nothing about lStar. So far about, I have found that lStar is code added to Android 31 (Android 12) in particular, which makes no sense to me why it should start working on Android 12 if my compileSdkVersion value is 28.

                                                                                                      
                                                                                                          
                                                                                                          
                                                                                                          
                                                                                                          
                                                                                                          
                                                                                                          
                                                                                                          
                                                                                                          
                                                                                                      
                                                                                                      

                                                                                                      What could be the cause of this error even though nothing has been changed?

                                                                                                      ANSWER

                                                                                                      Answered 2021-Sep-03 at 11:31

                                                                                                      I've found the issue and I was able to fix it.

                                                                                                      The issue was that one of the external libraries the app depends on has a dependency on androidx.core:core-ktx:+ which meant that was always compiling with the latest version. My app is still working on SDK 28, but the latest version of androidx.core:core-ktx has the minimal SDK of 31, which resulted in this conflict.

                                                                                                      Source https://stackoverflow.com/questions/69019631

                                                                                                      QUESTION

                                                                                                      Library to change to fix Google app publish error; Billing Library version 3 in android studio
                                                                                                      Asked 2021-Sep-10 at 12:03

                                                                                                      While upload my app in Google playstore I get this error; We've detected this app uses an unsupported version of Play billing. Please upgrade to Billing Library version 3 or newer to publish this app.

                                                                                                      Below are the dependencies on my android studio app, which of them is the billing library to change?

                                                                                                       implementation fileTree(dir: 'libs', include: ['*.jar'])
                                                                                                          implementation 'com.google.android.material:material:1.1.0'
                                                                                                          implementation 'com.github.AnchorFreePartner.hydra-sdk-android:sdk:3.1.1'
                                                                                                          implementation 'com.github.AnchorFreePartner.hydra-sdk-android:openvpn:3.1.1'
                                                                                                          implementation 'junit:junit:4.12'
                                                                                                          implementation 'androidx.appcompat:appcompat:1.1.0'
                                                                                                          implementation 'androidx.cardview:cardview:1.0.0'
                                                                                                          implementation 'androidx.recyclerview:recyclerview:1.1.0'
                                                                                                          implementation 'com.android.support:multidex:1.0.3'
                                                                                                          implementation 'com.jakewharton:butterknife:10.1.0'
                                                                                                          implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
                                                                                                          annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
                                                                                                          implementation 'com.google.android.gms:play-services-ads:19.0.1'
                                                                                                          implementation 'com.facebook.android:audience-network-sdk:5.6.1'
                                                                                                          implementation 'com.onesignal:OneSignal:3.12.7@aar'
                                                                                                          implementation 'com.google.firebase:firebase-analytics:17.3.0'
                                                                                                          implementation 'com.google.android.gms:play-services-gcm:17.0.0'
                                                                                                          implementation 'com.google.android.gms:play-services-location:17.0.0'
                                                                                                          implementation 'com.anjlab.android.iab.v3:library:1.1.0'
                                                                                                          implementation 'com.squareup.retrofit2:retrofit:2.6.2'
                                                                                                          implementation 'com.google.code.gson:gson:2.8.5'
                                                                                                          implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
                                                                                                      

                                                                                                      ANSWER

                                                                                                      Answered 2021-Sep-10 at 12:03

                                                                                                      You are using this library for InApp purchasing but this library says we have updated to V3 but Google play store warn about this library that library is not updated to V3 or V4

                                                                                                      implementation 'com.anjlab.android.iab.v3:library:1.1.0'
                                                                                                      

                                                                                                      You should use Official documents for InApp Purchasing

                                                                                                      Example V4

                                                                                                      build.gradle

                                                                                                      implementation 'com.android.billingclient:billing:4.0.0'
                                                                                                      

                                                                                                      strings.xml

                                                                                                      Place Your ID Here
                                                                                                      android.test.purchased
                                                                                                      

                                                                                                      InAppPurchase.kt

                                                                                                      import android.app.Activity
                                                                                                      import android.content.Context
                                                                                                      import android.widget.Toast
                                                                                                      import com.android.billingclient.api.*
                                                                                                      import java.io.IOException
                                                                                                      import java.util.ArrayList
                                                                                                      
                                                                                                      class InAppPurchase(context: Context) : PurchasesUpdatedListener{
                                                                                                          private val mContext: Context = context
                                                                                                          private var billingClient: BillingClient
                                                                                                          var ackPurchase =
                                                                                                              AcknowledgePurchaseResponseListener { billingResult ->
                                                                                                                  if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                                                                                                                      //if purchase is acknowledged
                                                                                                                      // Grant entitlement to the user. and restart activity
                                                                                                                      SharedPreferencesUtils.setPurchasedBillingValue(mContext, true)
                                                                                                                      showMessage("Item Purchased")
                                                                                                                      (mContext as Activity).recreate()
                                                                                                                  }
                                                                                                              }
                                                                                                      
                                                                                                          init {
                                                                                                              billingClient =
                                                                                                                  BillingClient.newBuilder(mContext).enablePendingPurchases().setListener(this).build()
                                                                                                              billingClient.startConnection(object : BillingClientStateListener {
                                                                                                                  override fun onBillingSetupFinished(billingResult: BillingResult) {
                                                                                                                      if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                                                                                                                          val queryPurchase = billingClient.queryPurchases(BillingClient.SkuType.INAPP)
                                                                                                                          val queryPurchases = queryPurchase.purchasesList
                                                                                                                          if (queryPurchases != null && queryPurchases.size > 0) {
                                                                                                                              handlePurchases(queryPurchases)
                                                                                                                          } else {
                                                                                                                              SharedPreferencesUtils.setPurchasedBillingValue(mContext, false)
                                                                                                                          }
                                                                                                                      }
                                                                                                                  }
                                                                                                      
                                                                                                                  override fun onBillingServiceDisconnected() {}
                                                                                                              })
                                                                                                          }
                                                                                                      
                                                                                                          fun productPurchase() {
                                                                                                              //check if service is already connected
                                                                                                              if (billingClient.isReady) {
                                                                                                                  initiatePurchase()
                                                                                                              } else {
                                                                                                                  billingClient =
                                                                                                                      BillingClient.newBuilder(mContext).enablePendingPurchases().setListener(this).build()
                                                                                                                  billingClient.startConnection(object : BillingClientStateListener {
                                                                                                                      override fun onBillingSetupFinished(billingResult: BillingResult) {
                                                                                                                          if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                                                                                                                              initiatePurchase()
                                                                                                                          } else {
                                                                                                                              showMessage("Error" + billingResult.debugMessage)
                                                                                                                          }
                                                                                                                      }
                                                                                                      
                                                                                                                      override fun onBillingServiceDisconnected() {}
                                                                                                                  })
                                                                                                              }
                                                                                                          }
                                                                                                      
                                                                                                          private fun initiatePurchase() {
                                                                                                              val skuList: MutableList = ArrayList()
                                                                                                              skuList.add(mContext.resources.getString(R.string.product_id))
                                                                                                              val params = SkuDetailsParams.newBuilder()
                                                                                                              params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP)
                                                                                                              billingClient.querySkuDetailsAsync(
                                                                                                                  params.build()
                                                                                                              ) { billingResult, skuDetailsList ->
                                                                                                                  if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                                                                                                                      if (skuDetailsList != null && skuDetailsList.size > 0) {
                                                                                                                          val flowParams = BillingFlowParams.newBuilder()
                                                                                                                              .setSkuDetails(skuDetailsList[0])
                                                                                                                              .build()
                                                                                                                          billingClient.launchBillingFlow(mContext as Activity, flowParams)
                                                                                                                      } else {
                                                                                                                          //try to add item/product id "purchase" inside managed product in google play console
                                                                                                                          showMessage("Purchase Item not Found")
                                                                                                                      }
                                                                                                                  } else {
                                                                                                                      showMessage(" Error " + billingResult.debugMessage)
                                                                                                                  }
                                                                                                              }
                                                                                                          }
                                                                                                      
                                                                                                          /**
                                                                                                           * Verifies that the purchase was signed correctly for this developer's public key.
                                                                                                           *
                                                                                                           * Note: It's strongly recommended to perform such check on your backend since hackers can
                                                                                                           * replace this method with "constant true" if they decompile/rebuild your app.
                                                                                                           *
                                                                                                           */
                                                                                                          private fun verifyValidSignature(signedData: String, signature: String): Boolean {
                                                                                                              return try {
                                                                                                                  // To get key go to Developer Console > Select your app > Development Tools > Services & APIs.
                                                                                                                  val base64Key = mContext.getString(R.string.license_key)
                                                                                                                  Security.verifyPurchase(base64Key, signedData, signature)
                                                                                                              } catch (e: IOException) {
                                                                                                                  false
                                                                                                              }
                                                                                                          }
                                                                                                      
                                                                                                          fun handlePurchases(purchases: List) {
                                                                                                              for (purchase in purchases) {
                                                                                                                  //if item is purchased
                                                                                                                  if (mContext.getString(R.string.product_id) == purchase.skus[0] && purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
                                                                                                                      if (!verifyValidSignature(purchase.originalJson, purchase.signature)) {
                                                                                                                          // Invalid purchase
                                                                                                                          // show error to user
                                                                                                                         showMessage("Invalid Purchase")
                                                                                                                          return
                                                                                                                      }
                                                                                                      //                 else purchase is valid
                                                                                                      //                if item is purchased and not acknowledged
                                                                                                                      if (!purchase.isAcknowledged) {
                                                                                                                          val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                                                                                                                              .setPurchaseToken(purchase.purchaseToken)
                                                                                                                              .build()
                                                                                                                          billingClient.acknowledgePurchase(acknowledgePurchaseParams, ackPurchase)
                                                                                                                      } else {
                                                                                                                          // Grant entitlement to the user on item purchase
                                                                                                                          // restart activity
                                                                                                                          if (!SharedPreferencesUtils.getPurchasedBillingValue(mContext)) {
                                                                                                                              SharedPreferencesUtils.setPurchasedBillingValue(mContext,true)
                                                                                                                              showMessage("Item Purchased")
                                                                                                                              (mContext as Activity).recreate()
                                                                                                                          }
                                                                                                                      }
                                                                                                                  } else if (mContext.getString(R.string.product_id) == purchase.skus[0] && purchase.purchaseState == Purchase.PurchaseState.PENDING) {
                                                                                                                      showMessage("Purchase is Pending. Please complete Transaction")
                                                                                                                  } else if (mContext.getString(R.string.product_id) == purchase.skus[0] && purchase.purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE) {
                                                                                                                      SharedPreferencesUtils.setPurchasedBillingValue(mContext,false)
                                                                                                                      showMessage("Purchase Status Unknown")
                                                                                                                  }
                                                                                                              }
                                                                                                      
                                                                                                      
                                                                                                          }
                                                                                                      
                                                                                                      
                                                                                                          private fun showMessage(message: String) {
                                                                                                              (mContext as Activity).runOnUiThread{
                                                                                                                  Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show()
                                                                                                              }
                                                                                                      
                                                                                                          }
                                                                                                      
                                                                                                          override fun onPurchasesUpdated(billingResult: BillingResult, purchases: MutableList?) {
                                                                                                              //if item newly purchased
                                                                                                              if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
                                                                                                                  handlePurchases(purchases)
                                                                                                              } else if (billingResult.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
                                                                                                                  val queryAlreadyPurchasesResult =
                                                                                                                      billingClient.queryPurchases(BillingClient.SkuType.INAPP)
                                                                                                                  val alreadyPurchases = queryAlreadyPurchasesResult.purchasesList
                                                                                                                  alreadyPurchases?.let { handlePurchases(it) }
                                                                                                              } else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
                                                                                                                  showMessage("Purchase Canceled")
                                                                                                              } else {
                                                                                                                  showMessage("Error updated" + billingResult.debugMessage)
                                                                                                              }
                                                                                                          }
                                                                                                      
                                                                                                      
                                                                                                          fun onDestroyBilling() {
                                                                                                              billingClient.endConnection()
                                                                                                          }
                                                                                                      
                                                                                                      }
                                                                                                      

                                                                                                      Security.kt

                                                                                                      import android.text.TextUtils
                                                                                                      import android.util.Base64
                                                                                                      import java.io.IOException
                                                                                                      import java.security.*
                                                                                                      import java.security.spec.InvalidKeySpecException
                                                                                                      import java.security.spec.X509EncodedKeySpec
                                                                                                      
                                                                                                      /**
                                                                                                       * Security-related methods. For a secure implementation, all of this code should be implemented on
                                                                                                       * a server that communicates with the application on the device.
                                                                                                       */
                                                                                                      object Security {
                                                                                                      
                                                                                                          private const val KEY_FACTORY_ALGORITHM = "RSA"
                                                                                                          private const val SIGNATURE_ALGORITHM = "SHA1withRSA"
                                                                                                      
                                                                                                          /**
                                                                                                           * Verifies that the data was signed with the given signature, and returns the verified
                                                                                                           * purchase.
                                                                                                           * @param base64PublicKey the base64-encoded public key to use for verifying.
                                                                                                           * @param signedData the signed JSON string (signed, not encrypted)
                                                                                                           * @param signature the signature for the data, signed with the private key
                                                                                                           * @throws IOException if encoding algorithm is not supported or key specification
                                                                                                           * is invalid
                                                                                                           */
                                                                                                          @Throws(IOException::class)
                                                                                                          fun verifyPurchase(
                                                                                                              base64PublicKey: String, signedData: String,
                                                                                                              signature: String
                                                                                                          ): Boolean {
                                                                                                              if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey)
                                                                                                                  || TextUtils.isEmpty(signature)
                                                                                                              ) {
                                                                                                                  //Purchase verification failed: missing data
                                                                                                                  return false
                                                                                                              }
                                                                                                              val key = generatePublicKey(base64PublicKey)
                                                                                                              return verify(key, signedData, signature)
                                                                                                          }
                                                                                                      
                                                                                                          /**
                                                                                                           * Generates a PublicKey instance from a string containing the Base64-encoded public key.
                                                                                                           *
                                                                                                           * @param encodedPublicKey Base64-encoded public key
                                                                                                           * @throws IOException if encoding algorithm is not supported or key specification
                                                                                                           * is invalid
                                                                                                           */
                                                                                                          @Throws(IOException::class)
                                                                                                          fun generatePublicKey(encodedPublicKey: String): PublicKey {
                                                                                                              return try {
                                                                                                                  val decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT)
                                                                                                                  val keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM)
                                                                                                                  keyFactory.generatePublic(X509EncodedKeySpec(decodedKey))
                                                                                                              } catch (e: NoSuchAlgorithmException) {
                                                                                                                  // "RSA" is guaranteed to be available.
                                                                                                                  throw RuntimeException(e)
                                                                                                              } catch (e: InvalidKeySpecException) {
                                                                                                                  val msg = "Invalid key specification: $e"
                                                                                                                  throw IOException(msg)
                                                                                                              }
                                                                                                          }
                                                                                                      
                                                                                                          /**
                                                                                                           * Verifies that the signature from the server matches the computed signature on the data.
                                                                                                           * Returns true if the data is correctly signed.
                                                                                                           *
                                                                                                           * @param publicKey public key associated with the developer account
                                                                                                           * @param signedData signed data from server
                                                                                                           * @param signature server signature
                                                                                                           * @return true if the data and signature match
                                                                                                           */
                                                                                                          private fun verify(publicKey: PublicKey, signedData: String, signature: String): Boolean {
                                                                                                              val signatureBytes: ByteArray = try {
                                                                                                                  Base64.decode(signature, Base64.DEFAULT)
                                                                                                              } catch (e: IllegalArgumentException) {
                                                                                                                  //Base64 decoding failed
                                                                                                                  return false
                                                                                                              }
                                                                                                              try {
                                                                                                                  val signatureAlgorithm = Signature.getInstance(SIGNATURE_ALGORITHM)
                                                                                                                  signatureAlgorithm.initVerify(publicKey)
                                                                                                                  signatureAlgorithm.update(signedData.toByteArray())
                                                                                                                  return signatureAlgorithm.verify(signatureBytes)
                                                                                                              } catch (e: NoSuchAlgorithmException) {
                                                                                                                  // "RSA" is guaranteed to be available
                                                                                                                  throw RuntimeException(e)
                                                                                                              } catch (e: InvalidKeyException) {
                                                                                                                  //Invalid key specification
                                                                                                              } catch (e: SignatureException) {
                                                                                                                  //Signature exception
                                                                                                              }
                                                                                                              return false
                                                                                                          }
                                                                                                      
                                                                                                      }
                                                                                                      

                                                                                                      MainActivity.kt

                                                                                                      var inAppPurchase: InAppPurchase  = InAppPurchase(this)
                                                                                                      btnInApp.setOnClickListener {
                                                                                                                  inAppPurchase.productPurchase()
                                                                                                              }
                                                                                                      

                                                                                                      Source https://stackoverflow.com/questions/69131336

                                                                                                      Community Discussions, Code Snippets contain sources that include Stack Exchange Network

                                                                                                      Vulnerabilities

                                                                                                      No vulnerabilities reported

                                                                                                      Install AndroidUtilCode

                                                                                                      You can download it from GitHub, Maven.
                                                                                                      You can use AndroidUtilCode like any standard Java library. Please include the the jar files in your classpath. You can also use any IDE and you can run and debug the AndroidUtilCode component as you would do with any other Java program. Best practice is to use a build tool that supports dependency management such as Maven or Gradle. For Maven installation, please refer maven.apache.org. For Gradle installation, please refer gradle.org .

                                                                                                      Support

                                                                                                      For any new features, suggestions and bugs create an issue on GitHub. If you have any questions check and ask questions on community page Stack Overflow .
                                                                                                      Find more information at:
                                                                                                      Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
                                                                                                      Find more libraries
                                                                                                      Explore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits​
                                                                                                      Save this library and start creating your kit
                                                                                                      CLONE
                                                                                                    • HTTPS

                                                                                                      https://github.com/Blankj/AndroidUtilCode.git

                                                                                                    • CLI

                                                                                                      gh repo clone Blankj/AndroidUtilCode

                                                                                                    • sshUrl

                                                                                                      git@github.com:Blankj/AndroidUtilCode.git

                                                                                                    • Share this Page

                                                                                                      share link

                                                                                                      Explore Related Topics

                                                                                                      Consider Popular Android Libraries

                                                                                                      Try Top Libraries by Blankj

                                                                                                      FreeProGuard

                                                                                                      by BlankjJava

                                                                                                      SwipePanel

                                                                                                      by BlankjJava

                                                                                                      ALog

                                                                                                      by BlankjJava

                                                                                                      resume

                                                                                                      by BlankjCSS

                                                                                                      Compare Android Libraries with Highest Support

                                                                                                      android

                                                                                                      by nextcloud

                                                                                                      fresco

                                                                                                      by facebook

                                                                                                      butterknife

                                                                                                      by JakeWharton

                                                                                                      PictureSelector

                                                                                                      by LuckSiege

                                                                                                      Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
                                                                                                      Find more libraries
                                                                                                      Explore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits​
                                                                                                      Save this library and start creating your kit