RoboZombie | Effortless networking for your Android application | Android library

 by   sahan Java Version: 1.3.3 License: Apache-2.0

kandi X-RAY | RoboZombie Summary

RoboZombie is a Java library typically used in Mobile, Android applications. RoboZombie has no bugs, it has no vulnerabilities, it has build file available, it has a Permissive License and it has low support. You can download it from GitHub, Maven.
RoboZombie   /rō-bō'zŏm'bē/   noun. 1. Makes Android networking a breeze.   2. Accepts an interface which describes the remote service and gives you an implementation of it.   . Looks for Gson on your build path. Looks for Simple-XML on your build path. ...and be sure to invoke all synchronous requests from a worker thread. Add the following dependency to project's pom.xml file. Add the following repository and dependency to your project's build.gradle file. Download the RoboZombie-1.3.3.jar and add it to your libs folder. Note that Gson is required for JSON (de)serialization and Simple-XML is required for XML (de)serialization. Coding with RoboZombie is a breeze. It follows a simple annotation based coding style and adheres to a minimal intrusion policy. Kickoff with the quickstart and follow the rest of the wiki pages. ##License This library is licensed under Apache License, Version 2.0.
    Support
      Quality
        Security
          License
            Reuse
            Support
              Quality
                Security
                  License
                    Reuse

                      kandi-support Support

                        summary
                        RoboZombie has a low active ecosystem.
                        summary
                        It has 88 star(s) with 16 fork(s). There are 2 watchers for this library.
                        summary
                        It had no major release in the last 12 months.
                        summary
                        There are 2 open issues and 22 have been closed. On average issues are closed in 42 days. There are 1 open pull requests and 0 closed requests.
                        summary
                        It has a neutral sentiment in the developer community.
                        summary
                        The latest version of RoboZombie is 1.3.3
                        RoboZombie Support
                          Best in #Android
                            Average in #Android
                            RoboZombie Support
                              Best in #Android
                                Average in #Android

                                  kandi-Quality Quality

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

                                              kandi-Security Security

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

                                                          kandi-License License

                                                            summary
                                                            RoboZombie 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.
                                                            RoboZombie License
                                                              Best in #Android
                                                                Average in #Android
                                                                RoboZombie License
                                                                  Best in #Android
                                                                    Average in #Android

                                                                      kandi-Reuse Reuse

                                                                        summary
                                                                        RoboZombie releases are not available. You will need to build from source code and install.
                                                                        summary
                                                                        Deployable package is available in Maven.
                                                                        summary
                                                                        Build file is available. You can build the component from source.
                                                                        summary
                                                                        Installation instructions are not available. Examples and code snippets are available.
                                                                        summary
                                                                        It has 8014 lines of code, 669 functions and 179 files.
                                                                        summary
                                                                        It has low code complexity. Code complexity directly impacts maintainability of the code.
                                                                        RoboZombie Reuse
                                                                          Best in #Android
                                                                            Average in #Android
                                                                            RoboZombie Reuse
                                                                              Best in #Android
                                                                                Average in #Android
                                                                                  Top functions reviewed by kandi - BETA
                                                                                  kandi has reviewed RoboZombie and discovered the below as its top functions. This is intended to give you an instant insight into RoboZombie implemented functionality, and help decide if they suit your requirements.
                                                                                  • Creates an instance of the query string
                                                                                    • Build the URI string
                                                                                    • Encodes a part of a URL
                                                                                    • Sets parameter of URI query
                                                                                  • Extracts the response and returns the result
                                                                                    • Discovers the factory for the given object
                                                                                  • Returns a processor for the specified request
                                                                                    • Discovers the factory for the given object
                                                                                  • Returns a new response entity instance
                                                                                  • Returns a new request s headers
                                                                                  • Process a proxy response
                                                                                  • Returns true if the given entity is encoded
                                                                                  • Converts a ContentType into a ContentType header
                                                                                  • Filters all fields annotated with the given annotation
                                                                                  • Serializes the given model
                                                                                  • Register the given endpoint class
                                                                                  • Returns the character set for the given entity
                                                                                  • Returns the difference between two Fields
                                                                                  • Returns the union of two fields
                                                                                  • Returns the intersection between two fields
                                                                                  • Returns a list of POST or POST parameters
                                                                                  • Reads the contents of an entity
                                                                                  • Returns an instance of the configuration
                                                                                  • Digest URI
                                                                                  • Executes the interceptor
                                                                                  • Returns the complete request base
                                                                                  • Processes a response and returns the result
                                                                                  Get all kandi verified functions for this library.
                                                                                  Get all kandi verified functions for this library.

                                                                                  RoboZombie Key Features

                                                                                  Quickstart
                                                                                  Defining, Injecting and Invoking
                                                                                  Identifying HTTP Methods
                                                                                  Sending Query and Form Parameters
                                                                                  Sending a Request Body
                                                                                  Serializing Request Content
                                                                                  Receiving a Response Body
                                                                                  Deserializing Response Content
                                                                                  Sending and Receiving Headers
                                                                                  Executing Requests Asynchronously
                                                                                  Creating Stateful Endpoints
                                                                                  Intercepting Requests
                                                                                  Overriding, Detaching and Skipping Components
                                                                                  Wiring and Injecting Endpoints
                                                                                  Configuring RoboZombie

                                                                                  RoboZombie Examples and Code Snippets

                                                                                  No Code Snippets are available at this moment for RoboZombie.
                                                                                  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 RoboZombie

                                                                                  You can download it from GitHub, Maven.
                                                                                  You can use RoboZombie 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 RoboZombie 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
                                                                                  Install
                                                                                  Maven
                                                                                  Gradle
                                                                                  CLONE
                                                                                • HTTPS

                                                                                  https://github.com/sahan/RoboZombie.git

                                                                                • CLI

                                                                                  gh repo clone sahan/RoboZombie

                                                                                • sshUrl

                                                                                  git@github.com:sahan/RoboZombie.git

                                                                                • Share this Page

                                                                                  share link

                                                                                  Explore Related Topics

                                                                                  Consider Popular Android Libraries

                                                                                  Try Top Libraries by sahan

                                                                                  Travis-Jr

                                                                                  by sahanJava

                                                                                  IckleBot

                                                                                  by sahanJava

                                                                                  ZombieLink

                                                                                  by sahanJava

                                                                                  DroidBallet

                                                                                  by sahanJava

                                                                                  Packrat

                                                                                  by sahanJava

                                                                                  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