Skip to content

Latest commit

 

History

History
432 lines (355 loc) · 13 KB

Android.md

File metadata and controls

432 lines (355 loc) · 13 KB

Usage for Android applications

Amber uses Intents and Content Resolvers to communicate between applications.

To be able to use Amber in your application you should add the following in your AndroidManifest.xml:

<queries>
  <intent>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="nostrsigner" />
  </intent>
</queries>

Then you can use this function to check if there's an external signer installed:

fun isExternalSignerInstalled(context: Context): Boolean {
  val intent =
    Intent().apply {
      action = Intent.ACTION_VIEW
      data = Uri.parse("nostrsigner:")
    }
  val infos = context.packageManager.queryIntentActivities(intent, 0)
  return infos.size > 0
}

Using Intents

To get the result back from Amber you should use registerForActivityResult or rememberLauncherForActivityResult in Kotlin. If you are using another framework check the documentation of your framework or a third party library to get the result.

Create the Intent using the nostrsigner scheme:

val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$content"))
  • Set the Amber package name
intent.`package` = "com.greenart7c3.nostrsigner"

Methods

  • get_public_key

    • params:

      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:"))
      intent.`package` = "com.greenart7c3.nostrsigner"
      
      // You can send some default permissions for the user authorize for ever
      val permissions = listOf(
        Permission(
            "sign_event",
            22242
        ),
        Permission(
            "nip04_encrypt"
        ),
        Permission(
            "nip04_decrypt"
        ),
        Permission(
            "nip44_encrypt"
        ),
        Permission(
            "nip44_decrypt"
        ),
        Permission(
            "decrypt_zap_event"
        ),
      )
      intent.putExtra("permissions", permissions.toJson())
      
      intent.putExtra("type", "get_public_key")
      context.startActivity(intent)
    • result:

      • If the user approved intent it will return the npub in the signature field

        val npub = intent.data?.getStringExtra("signature")
        // The package name of the signer application
        val packageName = intent.data?.getStringExtra("package")
  • sign_event

    • params:

      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$eventJson"))
      intent.`package` = "com.greenart7c3.nostrsigner"
      intent.putExtra("type", "sign_event")
      // to control the result in your application in case you are not waiting the result before sending another intent
      intent.putExtra("id", event.id)
      // Send the current logged in user npub
      intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
      
      // If you are sending multiple intents without awaiting you can add some intent flags to sign all events without opening multiple screens
      intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
      
      context.startActivity(intent)
    • result:

      • If the user approved intent it will return the signature, id and event fields

        // if you used the flags (Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) when sending the intent and there's more than 1 event amber will return an array with the results
        [
          {"package":null,"signature":"event_signature","id":"event_id"},
          {"package":null,"signature":"event_signature","id":"event_id"},
          {"package":null,"signature":"event_signature","id":"event_id"}
        ]
        
        // if you sent only 1 event or did not used the flags (Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) Amber will return the fields signature, id and event
        val signature = intent.data?.getStringExtra("signature")
        // the id you sent
        val id = intent.data?.getStringExtra("id")
        val signedEventJson = intent.data?.getStringExtra("event")
  • nip04_encrypt

    • params:

      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$plaintext"))
      intent.`package` = "com.greenart7c3.nostrsigner"
      intent.putExtra("type", "nip04_encrypt")
      // to control the result in your application in case you are not waiting the result before sending another intent
      intent.putExtra("id", "some_id")
      // Send the current logged in user npub
      intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
      // Send the hex pubKey that will be used for encrypting the data
      intent.putExtra("pubKey", pubKey)
      
      context.startActivity(intent)
    • result:

      • If the user approved intent it will return the signature and id fields

        val encryptedText = intent.data?.getStringExtra("signature")
        // the id you sent
        val id = intent.data?.getStringExtra("id")
  • nip44_encrypt

    • params:

      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$plaintext"))
      intent.`package` = "com.greenart7c3.nostrsigner"
      intent.putExtra("type", "nip44_encrypt")
      // to control the result in your application in case you are not waiting the result before sending another intent
      intent.putExtra("id", "some_id")
      // Send the current logged in user npub
      intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
      // Send the hex pubKey that will be used for encrypting the data
      intent.putExtra("pubKey", pubKey)
      
      context.startActivity(intent)
    • result:

      • If the user approved intent it will return the signature and id fields

        val encryptedText = intent.data?.getStringExtra("signature")
        // the id you sent
        val id = intent.data?.getStringExtra("id")
  • nip04_decrypt

    • params:

      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$encryptedText"))
      intent.`package` = "com.greenart7c3.nostrsigner"
      intent.putExtra("type", "nip04_decrypt")
      // to control the result in your application in case you are not waiting the result before sending another intent
      intent.putExtra("id", "some_id")
      // Send the current logged in user npub
      intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
      // Send the hex pubKey that will be used for decrypting the data
      intent.putExtra("pubKey", pubKey)
      
      context.startActivity(intent)
    • result:

      • If the user approved intent it will return the signature and id fields

        val plainText = intent.data?.getStringExtra("signature")
        // the id you sent
        val id = intent.data?.getStringExtra("id")
  • nip44_decrypt

    • params:

      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$encryptedText"))
      intent.`package` = "com.greenart7c3.nostrsigner"
      intent.putExtra("type", "nip04_decrypt")
      // to control the result in your application in case you are not waiting the result before sending another intent
      intent.putExtra("id", "some_id")
      // Send the current logged in user npub
      intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
      // Send the hex pubKey that will be used for decrypting the data
      intent.putExtra("pubKey", pubKey)
      
      context.startActivity(intent)
    • result:

      • If the user approved intent it will return the signature and id fields

        val plainText = intent.data?.getStringExtra("signature")
        // the id you sent
        val id = intent.data?.getStringExtra("id")
  • decrypt_zap_event

    • params:

      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$eventJson"))
      intent.`package` = "com.greenart7c3.nostrsigner"
      intent.putExtra("type", "decrypt_zap_event")
      // to control the result in your application in case you are not waiting the result before sending another intent
      intent.putExtra("id", "some_id")
      // Send the current logged in user npub
      intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
      context.startActivity(intent)
    • result:

      • If the user approved intent it will return the signature and id fields

        val eventJson = intent.data?.getStringExtra("signature")
        // the id you sent
        val id = intent.data?.getStringExtra("id")

Using Content Resolver

To get the result back from Amber you should use contentResolver.query in Kotlin. If you are using another framework check the documentation of your framework or a third party library to get the result.

If the user did not check the remember my choice option, the npub is not in amber or the signer type is not recognized the contentResolver will return null

For the SIGN_EVENT type amber returns two columns "signature" and "event". The column event is the signed event json

For the other types amber returns the column "signature"

If the user chose to always reject the event Amber will return the column "rejected" and you should not open Amber

Methods

  • get_public_key

    • params:

      val result = context.contentResolver.query(
          Uri.parse("content://com.greenart7c3.nostrsigner.GET_PUBLIC_KEY"),
          listOf("login"),
          "1",
          null,
          null
      )
    • result:

      • Will return the npub in the signature column

          if (result == null) return
        
          if (result.moveToFirst()) {
              val index = it.getColumnIndex("signature")
              if (index < 0) return
              val npub = it.getString(index)
          }
  • sign_event

    • params:

      val result = context.contentResolver.query(
          Uri.parse("content://com.greenart7c3.nostrsigner.SIGN_EVENT"),
          listOf("$eventJson", "", "${logged_in_user_npub}"),
          "1",
          null,
          null
      )
    • result:

      • Will return the signature and the event columns

          if (result == null) return
        
          if (result.moveToFirst()) {
              val index = it.getColumnIndex("signature")
              val indexJson = it.getColumnIndex("event")
              val signature = it.getString(index)
              val eventJson = it.getString(indexJson)
          }
  • nip04_encrypt

    • params:

      val result = context.contentResolver.query(
          Uri.parse("content://com.greenart7c3.nostrsigner.NIP04_ENCRYPT"),
          listOf("$plainText", "${hex_pub_key}", "${logged_in_user_npub}"),
          "1",
          null,
          null
      )
    • result:

      • Will return the signature column

          if (result == null) return
        
          if (result.moveToFirst()) {
              val index = it.getColumnIndex("signature")
              val encryptedText = it.getString(index)
          }
  • nip44_encrypt

    • params:

      val result = context.contentResolver.query(
          Uri.parse("content://com.greenart7c3.nostrsigner.NIP44_ENCRYPT"),
          listOf("$plainText", "${hex_pub_key}", "${logged_in_user_npub}"),
          "1",
          null,
          null
      )
    • result:

      • Will return the signature column

          if (result == null) return
        
          if (result.moveToFirst()) {
              val index = it.getColumnIndex("signature")
              val encryptedText = it.getString(index)
          }
  • nip04_decrypt

    • params:

      val result = context.contentResolver.query(
          Uri.parse("content://com.greenart7c3.nostrsigner.NIP04_DECRYPT"),
          listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_npub}"),
          "1",
          null,
          null
      )
    • result:

      • Will return the signature column

          if (result == null) return
        
          if (result.moveToFirst()) {
              val index = it.getColumnIndex("signature")
              val encryptedText = it.getString(index)
          }
  • nip44_decrypt

    • params:

      val result = context.contentResolver.query(
          Uri.parse("content://com.greenart7c3.nostrsigner.NIP44_DECRYPT"),
          listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_npub}"),
          "1",
          null,
          null
      )
    • result:

      • Will return the signature column

          if (result == null) return
        
          if (result.moveToFirst()) {
              val index = it.getColumnIndex("signature")
              val encryptedText = it.getString(index)
          }
  • decrypt_zap_event

    • params:

      val result = context.contentResolver.query(
          Uri.parse("content://com.greenart7c3.nostrsigner.DECRYPT_ZAP_EVENT"),
          listOf("$eventJson", "", "${logged_in_user_npub}"),
          "1",
          null,
          null
      )
    • result:

      • Will return the signature column

          if (result == null) return
        
          if (result.moveToFirst()) {
              val index = it.getColumnIndex("signature")
              val eventJson = it.getString(index)
          }