diff options
| author | Alex Gleason <alex@alexgleason.me> | 2026-04-10 13:31:37 -0500 |
|---|---|---|
| committer | Alex Gleason <alex@alexgleason.me> | 2026-04-10 13:31:37 -0500 |
| commit | 5e1e24766910fc07cb61a049aed2623987458ec2 (patch) | |
| tree | b7588f61fddf9374268d5cd6f4e3f2655d7c840a /55.md | |
| parent | b8782df594b4e7e8f088869134908eed58be6078 (diff) | |
| parent | 3465f540e3eaedccb5309711b502f0febf56b52f (diff) | |
Merge nip44-big-payloads into bigger-nip44bigger-nip44
Diffstat (limited to '55.md')
| -rw-r--r-- | 55.md | 58 |
1 files changed, 20 insertions, 38 deletions
| @@ -8,7 +8,7 @@ Android Signer Application | |||
| 8 | 8 | ||
| 9 | This NIP describes a method for 2-way communication between an Android signer and any Nostr client on Android. The Android signer is an Android Application and the client can be a web client or an Android application. | 9 | This NIP describes a method for 2-way communication between an Android signer and any Nostr client on Android. The Android signer is an Android Application and the client can be a web client or an Android application. |
| 10 | 10 | ||
| 11 | # Usage for Android applications | 11 | ## Usage for Android applications |
| 12 | 12 | ||
| 13 | The Android signer uses Intents (to accept/reject permissions manually) and Content Resolvers (to accept/reject permissions automatically in background if the user allowed it) to communicate between applications. | 13 | The Android signer uses Intents (to accept/reject permissions manually) and Content Resolvers (to accept/reject permissions automatically in background if the user allowed it) to communicate between applications. |
| 14 | 14 | ||
| @@ -38,7 +38,7 @@ fun isExternalSignerInstalled(context: Context): Boolean { | |||
| 38 | } | 38 | } |
| 39 | ``` | 39 | ``` |
| 40 | 40 | ||
| 41 | ## Using Intents | 41 | ### Using Intents |
| 42 | 42 | ||
| 43 | To get the result back from the Signer Application 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. | 43 | To get the result back from the Signer Application 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. |
| 44 | 44 | ||
| @@ -91,7 +91,7 @@ Signer MUST answer multiple permissions with an array of results | |||
| 91 | val results = listOf( | 91 | val results = listOf( |
| 92 | Result( | 92 | Result( |
| 93 | package = signerPackageName, | 93 | package = signerPackageName, |
| 94 | result = eventSignture, | 94 | result = eventSignature, |
| 95 | id = intentId | 95 | id = intentId |
| 96 | ) | 96 | ) |
| 97 | ) | 97 | ) |
| @@ -107,7 +107,14 @@ Send the Intent: | |||
| 107 | launcher.launch(intent) | 107 | launcher.launch(intent) |
| 108 | ``` | 108 | ``` |
| 109 | 109 | ||
| 110 | ### Methods | 110 | ### Initiating a connection |
| 111 | |||
| 112 | - Client send a get_public_key `Intent` | ||
| 113 | - Signer responds with the user `pubkey` and it's `packageName` | ||
| 114 | - Client saves the `pubkey` and `packageName` somewhere and NEVER calls `get_public_key` again | ||
| 115 | - Client now can send `content resolvers` and `Intents` for the other methods | ||
| 116 | |||
| 117 | #### Methods | ||
| 111 | 118 | ||
| 112 | - **get_public_key** | 119 | - **get_public_key** |
| 113 | - params: | 120 | - params: |
| @@ -203,10 +210,10 @@ launcher.launch(intent) | |||
| 203 | context.startActivity(intent) | 210 | context.startActivity(intent) |
| 204 | ``` | 211 | ``` |
| 205 | - result: | 212 | - result: |
| 206 | - If the user approved intent it will return the **signature** and **id** fields | 213 | - If the user approved intent it will return the **result** and **id** fields |
| 207 | 214 | ||
| 208 | ```kotlin | 215 | ```kotlin |
| 209 | val encryptedText = intent.data?.getStringExtra("signature") | 216 | val encryptedText = intent.data?.getStringExtra("result") |
| 210 | // the id you sent | 217 | // the id you sent |
| 211 | val id = intent.data?.getStringExtra("id") | 218 | val id = intent.data?.getStringExtra("id") |
| 212 | ``` | 219 | ``` |
| @@ -242,7 +249,7 @@ launcher.launch(intent) | |||
| 242 | ```kotlin | 249 | ```kotlin |
| 243 | val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$encryptedText")) | 250 | val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$encryptedText")) |
| 244 | intent.`package` = "com.example.signer" | 251 | intent.`package` = "com.example.signer" |
| 245 | intent.putExtra("type", "nip04_decrypt") | 252 | intent.putExtra("type", "nip44_decrypt") |
| 246 | // to control the result in your application in case you are not waiting the result before sending another intent | 253 | // to control the result in your application in case you are not waiting the result before sending another intent |
| 247 | intent.putExtra("id", "some_id") | 254 | intent.putExtra("id", "some_id") |
| 248 | // Send the current logged in user pubkey | 255 | // Send the current logged in user pubkey |
| @@ -283,7 +290,7 @@ launcher.launch(intent) | |||
| 283 | val id = intent.data?.getStringExtra("id") | 290 | val id = intent.data?.getStringExtra("id") |
| 284 | ``` | 291 | ``` |
| 285 | 292 | ||
| 286 | ## Using Content Resolver | 293 | ### Using Content Resolver |
| 287 | 294 | ||
| 288 | To get the result back from Signer Application 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. | 295 | To get the result back from Signer Application 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. |
| 289 | 296 | ||
| @@ -295,34 +302,9 @@ For the other types Signer Application returns the column "result" | |||
| 295 | 302 | ||
| 296 | If the user chose to always reject the event, signer application will return the column "rejected" and you should not open signer application | 303 | If the user chose to always reject the event, signer application will return the column "rejected" and you should not open signer application |
| 297 | 304 | ||
| 298 | ### Methods | 305 | Clients SHOULD save the user pubkey locally and avoid calling the `get_public_key` after the user is logged in to the Client |
| 299 | 306 | ||
| 300 | - **get_public_key** | 307 | #### Methods |
| 301 | - params: | ||
| 302 | |||
| 303 | ```kotlin | ||
| 304 | val result = context.contentResolver.query( | ||
| 305 | Uri.parse("content://com.example.signer.GET_PUBLIC_KEY"), | ||
| 306 | listOf("login"), | ||
| 307 | null, | ||
| 308 | null, | ||
| 309 | null | ||
| 310 | ) | ||
| 311 | ``` | ||
| 312 | - result: | ||
| 313 | - Will return the **pubkey** in the result column | ||
| 314 | |||
| 315 | ```kotlin | ||
| 316 | if (result == null) return | ||
| 317 | |||
| 318 | if (it.getColumnIndex("rejected") > -1) return | ||
| 319 | |||
| 320 | if (result.moveToFirst()) { | ||
| 321 | val index = it.getColumnIndex("result") | ||
| 322 | if (index < 0) return | ||
| 323 | val pubkey = it.getString(index) | ||
| 324 | } | ||
| 325 | ``` | ||
| 326 | 308 | ||
| 327 | - **sign_event** | 309 | - **sign_event** |
| 328 | - params: | 310 | - params: |
| @@ -482,7 +464,7 @@ If the user chose to always reject the event, signer application will return the | |||
| 482 | } | 464 | } |
| 483 | ``` | 465 | ``` |
| 484 | 466 | ||
| 485 | # Usage for Web Applications | 467 | ## Usage for Web Applications |
| 486 | 468 | ||
| 487 | You should consider using [NIP-46: Nostr Connect](46.md) for a better experience for web applications. When using this approach, the web app can't call the signer in the background, so the user will see a popup for every event you try to sign. | 469 | You should consider using [NIP-46: Nostr Connect](46.md) for a better experience for web applications. When using this approach, the web app can't call the signer in the background, so the user will see a popup for every event you try to sign. |
| 488 | 470 | ||
| @@ -496,7 +478,7 @@ You can configure the `returnType` to be **signature** or **event**. | |||
| 496 | 478 | ||
| 497 | Android intents and browser urls have limitations, so if you are using the `returnType` of **event** consider using the parameter **compressionType=gzip** that will return "Signer1" + Base64 gzip encoded event json | 479 | Android intents and browser urls have limitations, so if you are using the `returnType` of **event** consider using the parameter **compressionType=gzip** that will return "Signer1" + Base64 gzip encoded event json |
| 498 | 480 | ||
| 499 | ## Methods | 481 | ### Methods |
| 500 | 482 | ||
| 501 | - **get_public_key** | 483 | - **get_public_key** |
| 502 | - params: | 484 | - params: |
| @@ -547,7 +529,7 @@ Android intents and browser urls have limitations, so if you are using the `retu | |||
| 547 | window.href = `nostrsigner:${eventJson}?compressionType=none&returnType=signature&type=decrypt_zap_event&callbackUrl=https://example.com/?event=`; | 529 | window.href = `nostrsigner:${eventJson}?compressionType=none&returnType=signature&type=decrypt_zap_event&callbackUrl=https://example.com/?event=`; |
| 548 | ``` | 530 | ``` |
| 549 | 531 | ||
| 550 | ## Example | 532 | ### Example |
| 551 | 533 | ||
| 552 | ```js | 534 | ```js |
| 553 | <!DOCTYPE html> | 535 | <!DOCTYPE html> |