mirror of https://github.com/lukechilds/docs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1234 lines
71 KiB
1234 lines
71 KiB
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<!-- Begin Jekyll SEO tag v2.5.0 -->
|
|
<title>Android SDK Tutorial (Pre-release) | Blockstack</title>
|
|
<meta name="generator" content="Jekyll v3.8.3" />
|
|
<meta property="og:title" content="Android SDK Tutorial (Pre-release)" />
|
|
<meta name="author" content="Blockstack" />
|
|
<meta property="og:locale" content="en_US" />
|
|
<meta name="description" content="Android SDK Tutorial (Pre-release)" />
|
|
<meta property="og:description" content="Android SDK Tutorial (Pre-release)" />
|
|
<link rel="canonical" href="https://zbabystack.netlify.com/android/tutorial.html" />
|
|
<meta property="og:url" content="https://zbabystack.netlify.com/android/tutorial.html" />
|
|
<meta property="og:site_name" content="Blockstack" />
|
|
<meta property="og:type" content="article" />
|
|
<meta property="article:published_time" content="2018-09-12T18:20:57-07:00" />
|
|
<script type="application/ld+json">
|
|
{"description":"Android SDK Tutorial (Pre-release)","author":{"@type":"Person","name":"Blockstack"},"@type":"BlogPosting","url":"https://zbabystack.netlify.com/android/tutorial.html","headline":"Android SDK Tutorial (Pre-release)","dateModified":"2018-09-12T18:20:57-07:00","datePublished":"2018-09-12T18:20:57-07:00","mainEntityOfPage":{"@type":"WebPage","@id":"https://zbabystack.netlify.com/android/tutorial.html"},"@context":"http://schema.org"}</script>
|
|
<!-- End Jekyll SEO tag -->
|
|
|
|
<!-- <meta property="og:image" content="https://zbabystack.netlify.com/assets/posts/logo.png"/> -->
|
|
<meta property="og:image" content="/assets/posts/logo.png"/>
|
|
<link rel="stylesheet" href="/assets/css/main.css">
|
|
<link rel="shortcut icon" type="image/png" href="/assets/img/touch-icon.png" >
|
|
<link rel="alternate" type="application/rss+xml" title="Blockstack" href="/feed.xml">
|
|
<script src="/assets/js/main.js"></script>
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
<header class="uk-background-secondary">
|
|
<div data-uk-sticky="sel-target: .uk-navbar-container; cls-active: uk-navbar-sticky" class="uk-sticky uk-sticky-fixed" style="position: fixed; top: 0px; width: 1904px;">
|
|
<nav class="uk-navbar-container">
|
|
<div class="uk-container">
|
|
<div data-uk-navbar>
|
|
<div class="uk-navbar-left">
|
|
|
|
<!-- <a class="uk-navbar-item uk-logo" href="/"><img src="https://zbabystack.netlify.com/assets/posts/logo.png" alt="Docs"></a> -->
|
|
<a class="uk-navbar-item uk-logo" href="/"><img src="/assets/posts/logo.png" alt="Docs">
|
|
|
|
|
|
<svg style="width:141.602;height:11.487px" viewBox="0 0 141.602 11.487" enable-background="new 0 0 141.602 11.487"><path fill="#000000" d="M5.471,7.791c0,0.511-0.16,0.875-0.488,1.111C4.631,9.158,4.097,9.287,3.398,9.287H2.387V6.456h1.011 C5.256,6.456,5.471,7.219,5.471,7.791z M4.554,4.223C4.29,4.448,3.82,4.562,3.16,4.562H2.387V2.2h0.821 c0.611,0,1.066,0.094,1.352,0.279C4.81,2.641,4.933,2.907,4.933,3.292C4.933,3.704,4.809,4.008,4.554,4.223z M6.004,5.338 c0.325-0.181,0.59-0.418,0.79-0.709c0.327-0.476,0.493-1.001,0.493-1.562c0-0.53-0.105-0.989-0.313-1.362 c-0.208-0.374-0.5-0.677-0.867-0.9C5.754,0.59,5.333,0.432,4.855,0.335C4.391,0.24,3.879,0.192,3.334,0.192h-3.06 C0.123,0.192,0,0.317,0,0.471v10.545c0,0.154,0.123,0.278,0.274,0.278h3.315c0.591,0,1.143-0.065,1.645-0.194 c0.513-0.132,0.966-0.339,1.345-0.615c0.388-0.283,0.694-0.641,0.91-1.067C7.702,8.992,7.811,8.488,7.811,7.92 c0-0.78-0.226-1.413-0.672-1.879C6.847,5.737,6.467,5.502,6.004,5.338z M22.197,9.158h-4.595V0.471c0-0.153-0.123-0.278-0.274-0.278 h-1.824c-0.151,0-0.273,0.125-0.273,0.278v10.545c0,0.154,0.122,0.278,0.273,0.278h6.693c0.151,0,0.274-0.124,0.274-0.278v-1.58 C22.47,9.282,22.348,9.158,22.197,9.158z M35.076,5.695c0,0.567-0.051,1.086-0.151,1.543c-0.1,0.45-0.24,0.836-0.416,1.149 c-0.167,0.299-0.37,0.53-0.603,0.688c-0.461,0.312-1.061,0.3-1.505-0.001c-0.233-0.157-0.436-0.389-0.604-0.688 c-0.175-0.313-0.312-0.699-0.407-1.146c-0.096-0.458-0.144-0.978-0.144-1.546c0-1.126,0.187-2.013,0.556-2.638 c0.346-0.587,0.791-0.873,1.36-0.873c0.568,0,1.012,0.285,1.359,0.873C34.889,3.682,35.076,4.569,35.076,5.695z M36.319,1.541 c-0.378-0.494-0.844-0.879-1.381-1.144c-1.076-0.529-2.477-0.529-3.553,0c-0.538,0.265-1.003,0.65-1.381,1.144 c-0.373,0.487-0.669,1.09-0.879,1.792c-0.208,0.696-0.313,1.49-0.313,2.362c0,0.882,0.105,1.685,0.313,2.386 c0.21,0.706,0.504,1.318,0.876,1.821c0.378,0.511,0.844,0.908,1.382,1.179c0.538,0.27,1.136,0.407,1.779,0.407 c0.642,0,1.24-0.137,1.778-0.408c0.538-0.27,1.003-0.667,1.382-1.178c0.372-0.503,0.667-1.115,0.876-1.821 c0.208-0.7,0.314-1.502,0.314-2.386c0-0.873-0.105-1.667-0.314-2.363C36.988,2.631,36.692,2.028,36.319,1.541z M51.29,8.346 c-0.052-0.058-0.125-0.092-0.203-0.092c-0.077,0-0.151,0.033-0.203,0.092c-0.273,0.308-0.566,0.549-0.871,0.715 c-0.602,0.33-1.469,0.308-2.099,0.002c-0.326-0.159-0.608-0.387-0.841-0.681c-0.236-0.299-0.423-0.675-0.554-1.116 c-0.134-0.45-0.203-0.968-0.203-1.539c0-0.56,0.068-1.07,0.203-1.515c0.132-0.437,0.316-0.81,0.548-1.111 c0.227-0.293,0.504-0.522,0.825-0.68c0.614-0.302,1.45-0.317,2.02-0.032c0.283,0.142,0.543,0.333,0.775,0.568 c0.054,0.054,0.147,0.088,0.2,0.081c0.075-0.002,0.146-0.036,0.196-0.092l1.03-1.161c0.098-0.11,0.094-0.278-0.01-0.383 c-0.355-0.361-0.799-0.687-1.317-0.968c-1.105-0.597-2.643-0.547-3.841-0.044c-0.621,0.262-1.165,0.648-1.618,1.149 c-0.451,0.498-0.809,1.113-1.064,1.827c-0.253,0.71-0.381,1.521-0.381,2.408c0,0.899,0.128,1.712,0.381,2.417 c0.255,0.709,0.614,1.317,1.066,1.805c0.454,0.489,0.993,0.865,1.603,1.115c0.607,0.249,1.268,0.374,1.966,0.374 c0.695,0,1.333-0.142,1.897-0.423c0.559-0.279,1.068-0.684,1.513-1.204c0.09-0.106,0.089-0.264-0.004-0.368L51.29,8.346z M64.109,4.608l3.075-3.966c0.065-0.083,0.077-0.198,0.031-0.293c-0.045-0.096-0.141-0.157-0.245-0.157h-2.046 c-0.084,0-0.163,0.039-0.215,0.106l-3.254,4.218V0.47c0-0.153-0.123-0.277-0.274-0.277h-1.855c-0.151,0-0.274,0.124-0.274,0.277 v10.546c0,0.153,0.122,0.278,0.274,0.278h1.855c0.151,0,0.274-0.125,0.274-0.278V8.034l1.185-1.483l2.392,4.594 c0.048,0.091,0.141,0.148,0.242,0.148h2.046c0.097,0,0.186-0.052,0.236-0.138c0.049-0.085,0.05-0.19,0.003-0.276L64.109,4.608z M81.006,6.088c-0.218-0.244-0.478-0.462-0.773-0.647c-0.286-0.179-0.606-0.339-0.94-0.47l-1.368-0.598 c-0.235-0.097-0.461-0.189-0.679-0.276c-0.196-0.079-0.371-0.169-0.516-0.27c-0.134-0.092-0.24-0.197-0.315-0.311 c-0.065-0.099-0.097-0.22-0.097-0.369c0-0.297,0.112-0.514,0.351-0.683c0.263-0.187,0.64-0.281,1.12-0.281 c0.437,0,0.833,0.074,1.179,0.22c0.355,0.151,0.702,0.36,1.03,0.623c0.116,0.094,0.287,0.074,0.381-0.044l0.952-1.193 c0.091-0.114,0.079-0.279-0.026-0.38c-0.456-0.429-0.993-0.775-1.597-1.028c-1.114-0.467-2.435-0.495-3.459-0.144 c-0.469,0.161-0.88,0.389-1.221,0.678c-0.345,0.292-0.618,0.638-0.815,1.031c-0.199,0.398-0.299,0.834-0.299,1.296 c0,0.422,0.072,0.806,0.213,1.141c0.139,0.33,0.328,0.623,0.561,0.873c0.228,0.243,0.488,0.454,0.771,0.626 c0.277,0.169,0.564,0.312,0.841,0.42l1.425,0.634c0.249,0.095,0.479,0.19,0.692,0.285c0.198,0.088,0.367,0.184,0.504,0.285 c0.122,0.09,0.216,0.193,0.281,0.308c0.06,0.107,0.091,0.246,0.091,0.411c0,0.322-0.121,0.563-0.381,0.76 c-0.278,0.21-0.709,0.316-1.28,0.316c-0.467,0-0.934-0.103-1.388-0.307C75.78,8.788,75.358,8.514,74.99,8.18 c-0.056-0.05-0.127-0.077-0.201-0.07c-0.073,0.005-0.141,0.039-0.189,0.096l-1.078,1.274c-0.095,0.113-0.087,0.283,0.02,0.385 c0.541,0.516,1.167,0.92,1.862,1.2c0.695,0.281,1.434,0.423,2.195,0.423c0.63,0,1.205-0.09,1.707-0.265 c0.506-0.178,0.942-0.422,1.294-0.729c0.355-0.309,0.632-0.673,0.823-1.085c0.191-0.412,0.288-0.858,0.288-1.328 c0-0.419-0.062-0.797-0.185-1.123C81.404,6.632,81.229,6.339,81.006,6.088z M96.557,0.192h-8.374c-0.151,0-0.273,0.124-0.273,0.278 v1.58c0,0.154,0.122,0.278,0.273,0.278h2.994v8.687c0,0.154,0.122,0.278,0.274,0.278h1.84c0.151,0,0.273-0.124,0.273-0.278V2.328 h2.994c0.151,0,0.274-0.124,0.274-0.278v-1.58C96.831,0.317,96.708,0.192,96.557,0.192z M107.143,2.902 c0.074,0.282,0.149,0.566,0.226,0.851l0.725,2.664h-1.906l0.265-0.934c0.159-0.561,0.315-1.135,0.469-1.723 C106.996,3.473,107.071,3.188,107.143,2.902z M108.512,0.384c-0.037-0.114-0.142-0.192-0.261-0.192h-2.157 c-0.118,0-0.223,0.077-0.26,0.192l-3.362,10.546c-0.027,0.085-0.012,0.177,0.04,0.249c0.051,0.072,0.134,0.115,0.221,0.115h1.871 c0.122,0,0.229-0.082,0.263-0.201l0.752-2.653h3.044l0.736,2.651c0.034,0.12,0.141,0.203,0.263,0.203h1.951 c0.088,0,0.17-0.043,0.221-0.115c0.052-0.071,0.066-0.164,0.039-0.249L108.512,0.384z M125.302,8.346 c-0.104-0.117-0.302-0.117-0.406,0c-0.273,0.308-0.566,0.548-0.87,0.715c-0.603,0.329-1.469,0.308-2.1,0.002 c-0.326-0.159-0.608-0.387-0.841-0.681c-0.236-0.299-0.422-0.675-0.554-1.116c-0.134-0.449-0.202-0.966-0.202-1.539 c0-0.561,0.068-1.071,0.202-1.515c0.132-0.437,0.316-0.811,0.549-1.111c0.226-0.293,0.503-0.522,0.823-0.68 c0.614-0.302,1.45-0.317,2.02-0.032c0.283,0.142,0.544,0.332,0.775,0.567c0.053,0.055,0.131,0.089,0.2,0.082 c0.075-0.002,0.146-0.035,0.196-0.092l1.031-1.161c0.098-0.11,0.093-0.278-0.01-0.383c-0.355-0.361-0.8-0.687-1.318-0.968 c-1.105-0.597-2.644-0.547-3.841-0.044c-0.621,0.262-1.165,0.648-1.618,1.149c-0.451,0.498-0.809,1.113-1.063,1.827 c-0.254,0.71-0.382,1.521-0.382,2.409c0,0.899,0.128,1.712,0.382,2.417c0.254,0.709,0.612,1.317,1.065,1.805 c0.453,0.489,0.993,0.864,1.604,1.115c0.606,0.249,1.268,0.374,1.965,0.374c0.695,0,1.333-0.142,1.897-0.423 c0.559-0.279,1.067-0.684,1.514-1.204c0.09-0.106,0.089-0.264-0.004-0.368L125.302,8.346z M141.567,10.88l-3.448-6.272l3.075-3.966 c0.065-0.083,0.077-0.198,0.031-0.293c-0.045-0.096-0.141-0.157-0.246-0.157h-2.045c-0.084,0-0.164,0.039-0.215,0.106l-3.254,4.217 V0.47c0-0.153-0.122-0.277-0.274-0.277h-1.856c-0.151,0-0.274,0.124-0.274,0.277v10.546c0,0.153,0.123,0.278,0.274,0.278h1.856 c0.151,0,0.274-0.125,0.274-0.278V8.035l1.185-1.484l2.392,4.594c0.047,0.091,0.141,0.148,0.242,0.148h2.045 c0.097,0,0.187-0.052,0.236-0.138C141.614,11.071,141.615,10.966,141.567,10.88z"></path></svg>
|
|
</a>
|
|
</div>
|
|
<div class="uk-navbar-right">
|
|
<ul class="uk-navbar-nav uk-visible@m">
|
|
|
|
|
|
|
|
|
|
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li>
|
|
|
|
|
|
|
|
|
|
|
|
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li>
|
|
|
|
|
|
|
|
|
|
|
|
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li>
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
<div>
|
|
<a class="uk-navbar-toggle" uk-search-icon href="#"></a>
|
|
<div class="uk-drop uk-background-default uk-border-rounded" uk-drop="mode: click; pos: left-center; offset: 0">
|
|
<form class="uk-search uk-search-navbar uk-width-1-1" onsubmit="return false;">
|
|
<input id="searchBox" class="uk-search-input" type="search" placeholder="Search..." autofocus>
|
|
</form>
|
|
<ul id="searchBox-results" class="uk-position-absolute uk-width-1-1 uk-list"></ul>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<a class="uk-navbar-toggle uk-hidden@m" href="#offcanvas" data-uk-navbar-toggle-icon data-uk-toggle></a>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<div class="uk-section">
|
|
<div class="uk-container">
|
|
<div class="uk-grid-large" data-uk-grid>
|
|
|
|
<div class="sidebar-fixed-width uk-visible@m">
|
|
<div class="sidebar-docs uk-position-fixed">
|
|
<!-- -->
|
|
|
|
|
|
<h5>Try a tutorial</h5>
|
|
|
|
<ul class="uk-nav uk-nav-default doc-nav">
|
|
|
|
|
|
<!-- -->
|
|
|
|
<li class=""><a href="/browser/hello-blockstack.html">Hello, Blockstack Tutorial</a></li>
|
|
|
|
|
|
<!-- -->
|
|
|
|
<li class=""><a href="/browser/blockstack_storage.html">Blockstack Storage Tutorial</a></li>
|
|
|
|
</ul>
|
|
|
|
|
|
<h5>Work with an SDK</h5>
|
|
|
|
<ul class="uk-nav uk-nav-default doc-nav">
|
|
|
|
|
|
<!-- -->
|
|
|
|
<li class="uk-active"><a href="/android/tutorial.html">Android SDK Tutorial (Pre-release)</a></li>
|
|
|
|
|
|
<!-- -->
|
|
|
|
<li class=""><a href="/ios/tutorial.html">iOS SDK Tutorial (Pre-release)</a></li>
|
|
|
|
</ul>
|
|
|
|
|
|
<h5>Reference</h5>
|
|
|
|
<ul class="uk-nav uk-nav-default doc-nav">
|
|
|
|
|
|
<!-- -->
|
|
|
|
<li class=""><a href="/core/faq_developer.html">Developer FAQs</a></li>
|
|
|
|
|
|
<!-- -->
|
|
|
|
<li class=""><a href="/common/javascript_ref.html">Blockstack Javascript Reference</a></li>
|
|
|
|
</ul>
|
|
|
|
<!-- -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="uk-width-1-1 uk-width-expand@m">
|
|
|
|
<article markdown="span" class="uk-article">
|
|
|
|
<h1 class="uk-article-title">Android SDK Tutorial (Pre-release)</h1>
|
|
|
|
|
|
|
|
|
|
<div class="uk-article-meta uk-margin-top uk-margin-medium-bottom">
|
|
|
|
|
|
|
|
<!-- <img class="avatar avatar-small" alt="Blockstack" width="32" height="32" data-proofer-ignore="true" src="https://avatars2.githubusercontent.com/Blockstack?v=3&s=32" srcset="https://avatars2.githubusercontent.com/Blockstack?v=3&s=32 1x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=64 2x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=96 3x, https://avatars2.githubusercontent.com/Blockstack?v=3&s=128 4x" /> -->
|
|
|
|
|
|
|
|
<!-- Written by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Blockstack</span></span><br> -->
|
|
|
|
|
|
<time datetime="2018-09-12T18:20:57-07:00" itemprop="datePublished">
|
|
|
|
|
|
|
|
<a "target="_blank" href="https://github.com/blockstack/blockstack-android/blob/master/docs/tutorial.md" class="btn btn-default githubEditButton" role="button">
|
|
<span data-uk-icon="icon: pencil; ratio: 1.2"></span> Edit this page on Github</a>
|
|
<span style="font-family:Wingdings">w</span> Sep 12, 2018
|
|
</time>
|
|
|
|
</div>
|
|
|
|
<div markdown="span" class="article-content">
|
|
|
|
<p class="no_toc">This tutorial is written for readers who are new to either or both Blockstack
|
|
and Android to create a decentralized application. It contains the following
|
|
content:</p>
|
|
|
|
<ul id="markdown-toc">
|
|
<li><a href="#understand-the-sample-application-flow" id="markdown-toc-understand-the-sample-application-flow">Understand the sample application flow</a></li>
|
|
<li><a href="#set-up-your-environment" id="markdown-toc-set-up-your-environment">Set up your environment</a> <ul>
|
|
<li><a href="#install-android-studio" id="markdown-toc-install-android-studio">Install Android Studio</a></li>
|
|
<li><a href="#do-you-have-npm" id="markdown-toc-do-you-have-npm">Do you have npm?</a></li>
|
|
<li><a href="#install-the-blockstack-test-rig" id="markdown-toc-install-the-blockstack-test-rig">Install the Blockstack test rig</a></li>
|
|
<li><a href="#use-npm-to-install-yeoman-and-the-blockstack-app-generator" id="markdown-toc-use-npm-to-install-yeoman-and-the-blockstack-app-generator">Use npm to install Yeoman and the Blockstack App Generator</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#build-the-blockstack-hello-world" id="markdown-toc-build-the-blockstack-hello-world">Build the Blockstack hello-world</a> <ul>
|
|
<li><a href="#generate-and-launch-your-hello-blockstack-application" id="markdown-toc-generate-and-launch-your-hello-blockstack-application">Generate and launch your hello-blockstack application</a></li>
|
|
<li><a href="#add-a-redirect-end-point-to-your-application" id="markdown-toc-add-a-redirect-end-point-to-your-application">Add a redirect end point to your application</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#create-the-hello-android-project" id="markdown-toc-create-the-hello-android-project">Create the hello-android project</a> <ul>
|
|
<li><a href="#create-a-simple-project" id="markdown-toc-create-a-simple-project">Create a simple project</a></li>
|
|
<li><a href="#run-the-app-in-an-emulator" id="markdown-toc-run-the-app-in-an-emulator">Run the app in an emulator</a></li>
|
|
<li><a href="#configure-your-application-with-the-blockstack-sdk" id="markdown-toc-configure-your-application-with-the-blockstack-sdk">Configure your application with the Blockstack SDK</a></li>
|
|
<li><a href="#add-a-simple-interface" id="markdown-toc-add-a-simple-interface">Add a simple interface</a></li>
|
|
<li><a href="#add-session--authentication-code" id="markdown-toc-add-session--authentication-code">Add session & authentication code</a></li>
|
|
<li><a href="#run-the-final-app-in-the-emulator" id="markdown-toc-run-the-final-app-in-the-emulator">Run the final app in the emulator</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#where-to-go-next" id="markdown-toc-where-to-go-next">Where to go next</a></li>
|
|
</ul>
|
|
|
|
<p>This tutorial was extensively tested using Android Studio 3.1 on a MacBook Air
|
|
running High Sierra 10.13.4. If your environment is different, you may encounter
|
|
slight or even major discrepancies when performing the procedures in this
|
|
tutorial. Please <a href="https://slofile.com/slack/blockstack">join the Blockstack community
|
|
Slack</a> and post questions or comments to
|
|
the <code class="highlighter-rouge">#support</code> channel.</p>
|
|
|
|
<p>Finally, this tutorial is written for all levels from the beginner to the most
|
|
experienced. For best results, beginners should follow the guide as written. It
|
|
is expected that the fast or furiously brilliant will skip ahead and improvise
|
|
on this material at will. Fair journey one and all.</p>
|
|
|
|
<p>If you prefer, you can skip working through the tutorial all together. Instead,
|
|
you can <a href="images/helloandroid.zip">download the final project code</a> and import it
|
|
into Android Studio to review it.</p>
|
|
|
|
<h2 id="understand-the-sample-application-flow">Understand the sample application flow</h2>
|
|
|
|
<p>When complete, the sample application is a simple <code class="highlighter-rouge">hello-world</code> display. It is
|
|
intended for user on an Android phone.</p>
|
|
|
|
<p><img src="images/final-app.png" alt="" /></p>
|
|
|
|
<p>Only users with an existing <code class="highlighter-rouge">blockstack.id</code> can run your
|
|
final sample application. When complete, users interact with the sample
|
|
application by doing the following:</p>
|
|
|
|
<p><img src="images/app-flow.png" alt="" /></p>
|
|
|
|
<h2 id="set-up-your-environment">Set up your environment</h2>
|
|
|
|
<p>This sample application has two code bases, a Blockstack <code class="highlighter-rouge">hello-blockstack</code>
|
|
application and a <code class="highlighter-rouge">hello-andriod</code> Android application. Before you start
|
|
developing the sample, there are a few elements you need in your environment.</p>
|
|
|
|
<h3 id="install-android-studio">Install Android Studio</h3>
|
|
|
|
<p>If you are an experienced Android developer and already have an Android
|
|
development environment on your workstation, you can use that and skip this
|
|
step. However, you will need to adjust the remaining instructions for your
|
|
environment.</p>
|
|
|
|
<p>Follow the installation instructions to download and <a href="https://developer.android.com/studio/install">Android Studio
|
|
3.1</a> for your operating system.
|
|
Depending on your network connection, this can take between 15-30 minutes.</p>
|
|
|
|
<p><img src="images/studio-download.png" alt="" /></p>
|
|
|
|
<h3 id="do-you-have-npm">Do you have npm?</h3>
|
|
|
|
<p>The Blockstack code in this tutorial relies on the <code class="highlighter-rouge">npm</code> dependency manager.
|
|
Before you begin, verify you have installed <code class="highlighter-rouge">npm</code> using the <code class="highlighter-rouge">which</code> command to
|
|
verify.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>which npm
|
|
/usr/local/bin/npm
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>If you don’t find <code class="highlighter-rouge">npm</code> in your system, <a href="https://www.npmjs.com/get-npm">install
|
|
it</a>.</p>
|
|
|
|
<h3 id="install-the-blockstack-test-rig">Install the Blockstack test rig</h3>
|
|
|
|
<p>Users interact with Blockstack-enabled applications through a web browser. You
|
|
can Blockstack in test mode, on <code class="highlighter-rouge">localhost</code> or you can interact with completed
|
|
apps through the Blockstack webapp which is available at
|
|
[https://browser.blockstack.org/].</p>
|
|
|
|
<p>If you have already installed Blockstack for testing locally and have an
|
|
existing Blockstack ID, skip this section. Otherwise, continue onto install
|
|
Blockstack.</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<p>Go to <a href="https://blockstack.org/install">Blockstack</a></p>
|
|
|
|
<p><img src="images/blockstack-install.png" alt="" /></p>
|
|
</li>
|
|
<li>
|
|
<p>Install the version appropriate for your operating system.</p>
|
|
</li>
|
|
</ol>
|
|
|
|
<h3 id="use-npm-to-install-yeoman-and-the-blockstack-app-generator">Use npm to install Yeoman and the Blockstack App Generator</h3>
|
|
|
|
<p>You use <code class="highlighter-rouge">npm</code> to install Yeoman. Yeoman is a generic scaffolding system that
|
|
helps users rapidly start new projects and streamline the maintenance of
|
|
existing projects.</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<p>Install Yeoman.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> npm install -g yo
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Install the Blockstack application generator.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> npm install -g generator-blockstack
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
|
|
<h2 id="build-the-blockstack-hello-world">Build the Blockstack hello-world</h2>
|
|
|
|
<p>In this section, you build a Blockstack <code class="highlighter-rouge">hello-world</code> application. Then, you
|
|
modify the <code class="highlighter-rouge">hello-world</code> to interact with the Android app via a redirect.</p>
|
|
|
|
<h3 id="generate-and-launch-your-hello-blockstack-application">Generate and launch your hello-blockstack application</h3>
|
|
|
|
<p>In this section, you build an initial React.js application called
|
|
<code class="highlighter-rouge">hello-blockstack</code>.</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<p>Create a <code class="highlighter-rouge">hello-blockstack</code> directory.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> mkdir hello-blockstack
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Change into your new directory.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> <span class="nb">cd </span>hello-blockstack
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Use Yeoman and the Blockstack application generator to create your initial <code class="highlighter-rouge">hello-blockstack</code> application.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> yo blockstack:react
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>You should see several interactive prompts.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> <span class="nv">$ </span>yo blockstack:react
|
|
<span class="o">==========================================================================</span>
|
|
We are constantly looking <span class="k">for </span>ways to make yo better!
|
|
May we anonymously report usage statistics to improve the tool over <span class="nb">time</span>?
|
|
More info: https://github.com/yeoman/insight & http://yeoman.io
|
|
<span class="o">==========================================================================</span> No
|
|
|
|
_-----_ ╭──────────────────────────╮
|
|
| | │ Welcome to the │
|
|
|--<span class="o">(</span>o<span class="o">)</span>--| │ Blockstack app │
|
|
--------- │ generator! │
|
|
<span class="o">(</span> _U_ <span class="o">)</span> ╰──────────────────────────╯
|
|
/___A___<span class="se">\ </span> /
|
|
| ~ |
|
|
__<span class="s1">'.___.'</span>__
|
|
|° Y
|
|
|
|
? Are you ready to build a Blockstack app <span class="k">in </span>React? <span class="o">(</span>Y/n<span class="o">)</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Respond to the prompts to populate the initial app.</p>
|
|
|
|
<p>After the process completes successfully, you see a prompt similar to the following:</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> <span class="o">[</span>fsevents] Success:
|
|
<span class="s2">"/Users/theuser/repos/hello-blockstack/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node"</span>
|
|
is installed via remote npm notice created a lockfile as package-lock.json.
|
|
You should commit this file. added 1060 packages <span class="k">in </span>26.901s
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Run the initial application.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> <span class="nv">$ </span>npm start
|
|
|
|
> hello-blockstack@0.0.0 start /Users/moxiegirl/repos/hello-blockstack
|
|
> webpack-dev-server
|
|
|
|
Project is running at http://localhost:8080/
|
|
webpack output is served from /
|
|
404s will fallback to /index.html
|
|
Hash: 4d2312ba236a4b95dc3a
|
|
Version: webpack 2.7.0
|
|
Time: 2969ms
|
|
Asset Size Chunks Chunk Names
|
|
....
|
|
Child html-webpack-plugin <span class="k">for</span> <span class="s2">"index.html"</span>:
|
|
chunk <span class="o">{</span>0<span class="o">}</span> index.html 541 kB <span class="o">[</span>entry] <span class="o">[</span>rendered]
|
|
<span class="o">[</span>0] ./~/lodash/lodash.js 540 kB <span class="o">{</span>0<span class="o">}</span> <span class="o">[</span>built]
|
|
<span class="o">[</span>1] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 533 bytes <span class="o">{</span>0<span class="o">}</span> <span class="o">[</span>built]
|
|
<span class="o">[</span>2] <span class="o">(</span>webpack<span class="o">)</span>/buildin/global.js 509 bytes <span class="o">{</span>0<span class="o">}</span> <span class="o">[</span>built]
|
|
<span class="o">[</span>3] <span class="o">(</span>webpack<span class="o">)</span>/buildin/module.js 517 bytes <span class="o">{</span>0<span class="o">}</span> <span class="o">[</span>built]
|
|
webpack: Compiled successfully.
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>The system opens a browser displaying your running application.</p>
|
|
|
|
<p><img src="images/blockstack-signin.png" alt="" /></p>
|
|
|
|
<p>At this point, the browser is running a Blockstack server on your local host.
|
|
This is for testing your applications only.</p>
|
|
</li>
|
|
<li>
|
|
<p>Choose <strong>Sign in with Blockstack</strong></p>
|
|
|
|
<p>The system displays a prompt allowing you to create a new Blockstack ID or restore an existing one.</p>
|
|
|
|
<p><img src="images/create-restore.png" alt="" /></p>
|
|
</li>
|
|
<li>
|
|
<p>Follow the prompts appropriate to your situation.</p>
|
|
|
|
<p>If you are restoring an existing ID, you may see a prompt about your user
|
|
being nameless, ignore it. At this point you have only a single application
|
|
on your test server. So, you should see this single application, with your
|
|
own <code class="highlighter-rouge">blockstack.id</code> display name, once you are signed in:</p>
|
|
|
|
<p><img src="images/running-app.png" alt="" /></p>
|
|
</li>
|
|
</ol>
|
|
|
|
<h3 id="add-a-redirect-end-point-to-your-application">Add a redirect end point to your application</h3>
|
|
|
|
<p>When a user opens the webapp from the Blockstack browser on an Android phone,
|
|
you want the web app to redirect the user to your Android application. The work
|
|
you do here will allow it.</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<p>From the terminal command line, change directory to the root of your sample
|
|
application directory.</p>
|
|
</li>
|
|
<li>
|
|
<p>Use the <code class="highlighter-rouge">touch</code> command to add a redirect endpoint to your application.</p>
|
|
|
|
<p>This endpoint on the web version of your app will redirect Android users back
|
|
to your mobile app.</p>
|
|
|
|
<div class="language-bash highlighter-rouge"><pre class="highlight"><code> <span class="nv">$ </span>touch public/redirect.html
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Open <code class="highlighter-rouge">redirect.html</code> and add code to the endpoint.</p>
|
|
|
|
<div class="language-html highlighter-rouge"><pre class="highlight"><code> <span class="cp"><!DOCTYPE html></span>
|
|
<span class="nt"><html></span>
|
|
<span class="nt"><head></span>
|
|
<span class="nt"><title></span>Hello, Blockstack!<span class="nt"></title></span>
|
|
<span class="nt"><script></span>
|
|
<span class="kd">function</span> <span class="nx">getParameterByName</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">match</span> <span class="o">=</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s1">'[?&]'</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="s1">'=([^&]*)'</span><span class="p">).</span><span class="nx">exec</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">search</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">match</span> <span class="o">&&</span> <span class="nb">decodeURIComponent</span><span class="p">(</span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\+</span><span class="sr">/g</span><span class="p">,</span> <span class="s1">' '</span><span class="p">));</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">authResponse</span> <span class="o">=</span> <span class="nx">getParameterByName</span><span class="p">(</span><span class="s1">'authResponse'</span><span class="p">)</span>
|
|
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="o">=</span><span class="s2">"myblockstackapp:"</span> <span class="o">+</span> <span class="nx">authResponse</span>
|
|
<span class="nt"></script></span>
|
|
<span class="nt"><body></span>
|
|
<span class="nt"></body></span>
|
|
<span class="nt"></html></span>
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>Blockstack apps are identified by their domain names. The endpoint will
|
|
receive a get request with the query parameter <code class="highlighter-rouge">authResponse=XXXX</code> and
|
|
should redirect the browser to <code class="highlighter-rouge">myblockstackapp:XXXX</code>.</p>
|
|
|
|
<p><code class="highlighter-rouge">myblockstackapp:</code> is custom protocol handler. The handler should be unique
|
|
to your application. Your app’s web-based authentication uses this handler
|
|
to redirect the user back to your Android app. Later, you’ll add a reference
|
|
to this handler in your Android application.</p>
|
|
</li>
|
|
<li>Close and save the <code class="highlighter-rouge">redirect.html</code> file.</li>
|
|
<li>Ensure your Blockstack compiles successfully.</li>
|
|
</ol>
|
|
|
|
<h2 id="create-the-hello-android-project">Create the hello-android project</h2>
|
|
|
|
<p>In this section, you’ll create an Android application in Android Studio. You’ll
|
|
run the application in the emulator to test it.</p>
|
|
|
|
<h3 id="create-a-simple-project">Create a simple project</h3>
|
|
|
|
<p>In this section, you create an inital project. You’ll validate the application’s
|
|
iniatial state by creating an emulator to run it in. Open Android Studio and do the following:</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<p>Open Android Studio and choose <strong>Start a new Andriod Studio project</strong>.</p>
|
|
|
|
<p>If studio is already started, choose <strong>File > New > New Project</strong>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Enter these fields in the <strong>Create Android Project</strong> page.</p>
|
|
|
|
<table>
|
|
<tr>
|
|
<th>Application Name</th>
|
|
<td><code>hello-android</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Company domain</th>
|
|
<td><code><i>USERNAME</i>.example.com</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Project location</th>
|
|
<td><code>/Users/<i>USERNAME</i>/AndroidStudioProjects/helloandroid</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th>Include Kotlin support</th>
|
|
<td>Set (checked)</td>
|
|
</tr>
|
|
</table>
|
|
</li>
|
|
<li>Press <strong>Next</strong> to display <strong>Target Android Devices</strong>.</li>
|
|
<li>Check <strong>Phone and Tablet</strong>.</li>
|
|
<li>Choose API 27: Andriod 8.1 (Oreo) for the target version.</li>
|
|
<li>Press <strong>Next</strong>.</li>
|
|
<li>Choose <strong>Empty Activity</strong> and press <strong>Next</strong>.</li>
|
|
<li>
|
|
<p>Leave the <strong>Configure Activity</strong> dialog with its defaults.</p>
|
|
|
|
<p><img src="images/configure-activity.png" alt="" /></p>
|
|
</li>
|
|
<li>
|
|
<p>Press <strong>Finish</strong>.</p>
|
|
|
|
<p>Android studio builds your initial project. This can take a bit the first time you do it.</p>
|
|
|
|
<p><img src="images/initial-build.png" alt="" /></p>
|
|
</li>
|
|
</ol>
|
|
|
|
<h3 id="run-the-app-in-an-emulator">Run the app in an emulator</h3>
|
|
|
|
<p>In this section, you run the appliation and create an emulator when prompted.</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<p>Once the project is imported into studio, click the <code class="highlighter-rouge">app</code> module in the <strong>Project</strong> window.</p>
|
|
</li>
|
|
<li>
|
|
<p>Then, select <strong>Run > Run</strong> (or click the green arrow in the toolbar).</p>
|
|
|
|
<p>Studio prompts you to <strong>Select Deployment Target</strong>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Choose <strong>Create New Virtual Device</strong> and press <strong>OK</strong>.</p>
|
|
|
|
<p>Studio prompts you to <strong>Select Hardware</strong>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Choose a Phone running Pixel XL.</p>
|
|
|
|
<p><img src="images/select-hdw.png" alt="" /></p>
|
|
|
|
<p>Studio prompts you for a system image.</p>
|
|
</li>
|
|
<li>
|
|
<p>Choose <strong>Oreo</strong> which is API level 27 and press <strong>Next</strong>.</p>
|
|
|
|
<p><img src="images/oreo-api.png" alt="" /></p>
|
|
|
|
<p>Studio asks you to verify your new emulator configuration.</p>
|
|
</li>
|
|
<li>
|
|
<p>Press <strong>Finish</strong>.</p>
|
|
|
|
<p>The emulation takes a moment to build. Then, studio launches the emulation and opens your application.</p>
|
|
|
|
<p><img src="images/hello-andriod-1.png" alt="" /></p>
|
|
</li>
|
|
</ol>
|
|
|
|
<h3 id="configure-your-application-with-the-blockstack-sdk">Configure your application with the Blockstack SDK</h3>
|
|
|
|
<p>Now that you have created your initial project and verified it running in an emulator, you are ready to begin configuring the application for use with Blockstack.</p>
|
|
|
|
<ol>
|
|
<li>In studio, open the <code class="highlighter-rouge">AndroidManifest.xml</code> file.</li>
|
|
<li>
|
|
<p>Add the a <code class="highlighter-rouge">launchMode</code> to the <code class="highlighter-rouge">.MainActivity</code> definition.</p>
|
|
|
|
<pre><code class="language-XML"> <activity android:name=".MainActivity" android:launchMode="singleTask">
|
|
</code></pre>
|
|
|
|
<p>Blockstack requires that the activity that starts the sign-in process also
|
|
handles the auth reponse token. This means that the activity needs to run in
|
|
<code class="highlighter-rouge">singleTask</code> launch mode.</p>
|
|
</li>
|
|
<li>
|
|
<p>Add an <code class="highlighter-rouge"><intent-filter></code> with the custom handler for Blockstack.</p>
|
|
|
|
<pre><code class="language-XML"> <intent-filter>
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data android:scheme="myblockstackapp" />
|
|
</intent-filter>
|
|
</code></pre>
|
|
</li>
|
|
<li>Open the Project’s <code class="highlighter-rouge">build.gradle</code> file.</li>
|
|
<li>
|
|
<p>Add the Jitpack repository <code class="highlighter-rouge">maven { url 'https://jitpack.io' }</code> to the <code class="highlighter-rouge">repositories</code> section.</p>
|
|
|
|
<p>When you finish, that section looks like this:</p>
|
|
|
|
<pre><code class="language-JS"> allprojects {
|
|
repositories {
|
|
google()
|
|
jcenter()
|
|
maven { url 'https://jitpack.io' }
|
|
}
|
|
}
|
|
</code></pre>
|
|
</li>
|
|
<li>Open the Module <code class="highlighter-rouge">build.gradle</code> file.</li>
|
|
<li>
|
|
<p>Set the <code class="highlighter-rouge">defaultConfig minSdkVersion</code> to <code class="highlighter-rouge">19</code>.</p>
|
|
|
|
<p>When you are done, you should see (within your own username not <code class="highlighter-rouge">moxiegirl</code>):</p>
|
|
|
|
<pre><code class="language-JS">android {
|
|
compileSdkVersion 27
|
|
defaultConfig {
|
|
applicationId "com.example.moxiegirl.hello_android"
|
|
minSdkVersion 19
|
|
targetSdkVersion 27
|
|
versionCode 1
|
|
versionName "1.0"
|
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
|
}
|
|
...
|
|
}
|
|
</code></pre>
|
|
</li>
|
|
<li>
|
|
<p>Below this, add the Blockstack Android SDK dependency to your project’s <code class="highlighter-rouge">dependencies</code> list:</p>
|
|
|
|
<p>When you are done you should see:</p>
|
|
|
|
<pre><code class="language-JS"> dependencies {
|
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
|
implementation 'com.android.support:appcompat-v7:27.1.0'
|
|
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
|
testImplementation 'junit:junit:4.12'
|
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
|
implementation 'com.github.blockstack:blockstack-android:0.3.0'
|
|
}
|
|
|
|
</code></pre>
|
|
|
|
<p><strong>NOTE</strong>: Ignore the warning on the appcompat` dependencies.</p>
|
|
</li>
|
|
<li>
|
|
<p>Sync your project.</p>
|
|
|
|
<p><img src="images/sync-project.png" alt="" /></p>
|
|
|
|
<p>Be sure to check the sync completed successfully.</p>
|
|
|
|
<p><img src="images/sync-success.png" alt="" /></p>
|
|
</li>
|
|
<li>
|
|
<p>Run your app in the emulator.</p>
|
|
|
|
<p>You’ve made a lot of changes, make sure the emulator is still running
|
|
correctly.</p>
|
|
</li>
|
|
</ol>
|
|
|
|
<h3 id="add-a-simple-interface">Add a simple interface</h3>
|
|
|
|
<ol>
|
|
<li>
|
|
<p>Open the <code class="highlighter-rouge">app/res/layout/activity_main.xml</code> file.</p>
|
|
|
|
<p>The <code class="highlighter-rouge">activity_main.xml</code> file defines the graphical elements. Some elements are required before you can functionality to your <code class="highlighter-rouge">MainActivity.kt</code> code.</p>
|
|
</li>
|
|
<li>
|
|
<p>Replace the entire content of the file with the following code:</p>
|
|
|
|
<p>The new interface includes a <code class="highlighter-rouge">BlockstackSignInButton</code> which is provided by
|
|
the SDK. This SDK includes a themed “Sign in with Blockstack” button
|
|
(<code class="highlighter-rouge">BlockstackSignInButton</code>). You use this button in your here with the
|
|
<code class="highlighter-rouge">org.blockstack.android.sdk.ui.BlockstackSignInButton</code> class.</p>
|
|
|
|
<pre><code class="language-XML"> <?xml version="1.0" encoding="utf-8"?>
|
|
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
xmlns:tools="http://schemas.android.com/tools"
|
|
android:layout_width="match_parent"
|
|
android:layout_height="match_parent"
|
|
tools:context=".MainActivity">
|
|
|
|
<org.blockstack.android.sdk.ui.BlockstackSignInButton
|
|
android:id="@+id/signInButton"
|
|
android:layout_width="307dp"
|
|
android:layout_height="45dp"
|
|
android:layout_margin="4dp"
|
|
android:layout_marginEnd="185dp"
|
|
android:layout_marginStart="39dp"
|
|
app:layout_constraintEnd_toEndOf="parent"
|
|
app:layout_constraintStart_toStartOf="parent"
|
|
tools:layout_editor_absoluteY="16dp" />
|
|
|
|
<TextView
|
|
android:id="@+id/userDataTextView"
|
|
android:layout_width="370dp"
|
|
android:layout_height="27dp"
|
|
tools:layout_editor_absoluteX="6dp"
|
|
tools:layout_editor_absoluteY="70dp" />
|
|
|
|
</android
|
|
</code></pre>
|
|
|
|
<p>This codes adds a button and some text to your application.</p>
|
|
</li>
|
|
<li>
|
|
<p>Choose <strong>Run > Apply changes</strong>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Choose <strong>Run > Run app</strong> in the emulator.</p>
|
|
|
|
<p>The emulator now contains a new interface with a button:</p>
|
|
|
|
<p><img src="images/new-interface.png" alt="" /></p>
|
|
</li>
|
|
</ol>
|
|
|
|
<h3 id="add-session--authentication-code">Add session & authentication code</h3>
|
|
|
|
<ol>
|
|
<li>Open the <code class="highlighter-rouge">MainActivity.kt</code> file.</li>
|
|
<li>
|
|
<p>Add some additional imports to the top below the <code class="highlighter-rouge">android.os.Bundle</code> import.</p>
|
|
|
|
<p>When you are done, your imports should appear as follows:</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code>
|
|
<span class="k">import</span> <span class="nn">android.support.v7.app.AppCompatActivity</span>
|
|
<span class="k">import</span> <span class="nn">android.os.Bundle</span>
|
|
|
|
<span class="k">import</span> <span class="nn">android.support.v7.app.AppCompatActivity</span>
|
|
<span class="k">import</span> <span class="nn">android.view.View</span>
|
|
<span class="k">import</span> <span class="nn">kotlinx.android.synthetic.main.activity_main.*</span>
|
|
<span class="k">import</span> <span class="nn">org.blockstack.android.sdk.BlockstackSession</span>
|
|
<span class="k">import</span> <span class="nn">org.blockstack.android.sdk.Scope</span>
|
|
<span class="k">import</span> <span class="nn">org.blockstack.android.sdk.UserData</span>
|
|
<span class="k">import</span> <span class="nn">java.net.URI</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Add a variable for the Blockstack session before <code class="highlighter-rouge">onCreate</code>.</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">AppCompatActivity</span><span class="p">()</span> <span class="p">{</span>
|
|
|
|
<span class="k">private</span> <span class="kd">var</span> <span class="py">_blockstackSession</span><span class="p">:</span> <span class="n">BlockstackSession</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
|
|
|
|
|
|
<span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
|
|
<span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
|
|
<span class="n">setContentView</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Replace the existing the <code class="highlighter-rouge">onCreate</code> function with the following:</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code> <span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
|
|
<span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
|
|
<span class="n">setContentView</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
|
|
|
|
<span class="n">signInButton</span><span class="p">.</span><span class="n">isEnabled</span> <span class="p">=</span> <span class="k">false</span>
|
|
|
|
<span class="kd">val</span> <span class="py">appDomain</span> <span class="p">=</span> <span class="n">URI</span><span class="p">(</span><span class="s">"https://flamboyant-darwin-d11c17.netlify.com"</span><span class="p">)</span>
|
|
<span class="kd">val</span> <span class="py">redirectURI</span> <span class="p">=</span> <span class="n">URI</span><span class="p">(</span><span class="s">"${appDomain}/redirect"</span><span class="p">)</span>
|
|
<span class="kd">val</span> <span class="py">manifestURI</span> <span class="p">=</span> <span class="n">URI</span><span class="p">(</span><span class="s">"${appDomain}/manifest.json"</span><span class="p">)</span>
|
|
<span class="kd">val</span> <span class="py">scopes</span> <span class="p">=</span> <span class="n">arrayOf</span><span class="p">(</span><span class="n">Scope</span><span class="p">.</span><span class="n">StoreWrite</span><span class="p">)</span>
|
|
|
|
<span class="kd">val</span> <span class="py">config</span> <span class="p">=</span> <span class="n">java</span><span class="p">.</span><span class="n">net</span><span class="p">.</span><span class="n">URI</span><span class="p">(</span><span class="s">"https://flamboyant-darwin-d11c17.netlify.com"</span><span class="p">).</span><span class="n">run</span> <span class="p">{</span>
|
|
<span class="n">org</span><span class="p">.</span><span class="n">blockstack</span><span class="p">.</span><span class="n">android</span><span class="p">.</span><span class="n">sdk</span><span class="p">.</span><span class="n">BlockstackConfig</span><span class="p">(</span>
|
|
<span class="k">this</span><span class="p">,</span>
|
|
<span class="n">redirectURI</span><span class="p">,</span>
|
|
<span class="n">manifestURI</span><span class="p">,</span>
|
|
<span class="n">scopes</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="n">_blockstackSession</span> <span class="p">=</span> <span class="n">BlockstackSession</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="n">config</span><span class="p">,</span>
|
|
<span class="n">onLoadedCallback</span> <span class="p">=</span> <span class="p">{</span>
|
|
<span class="n">signInButton</span><span class="p">.</span><span class="n">isEnabled</span> <span class="p">=</span> <span class="k">true</span>
|
|
<span class="p">})</span>
|
|
|
|
|
|
<span class="n">signInButton</span><span class="p">.</span><span class="n">setOnClickListener</span> <span class="p">{</span> <span class="n">view</span><span class="p">:</span> <span class="n">View</span> <span class="p">-></span>
|
|
<span class="n">blockstackSession</span><span class="p">().</span><span class="n">redirectUserToSignIn</span> <span class="p">{</span> <span class="n">userData</span> <span class="p">-></span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">userData</span><span class="p">.</span><span class="n">hasValue</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">runOnUiThread</span> <span class="p">{</span>
|
|
<span class="n">onSignIn</span><span class="p">(</span><span class="n">userData</span><span class="p">.</span><span class="n">value</span><span class="o">!!</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">intent</span><span class="o">?.</span><span class="n">action</span> <span class="p">==</span> <span class="n">Intent</span><span class="p">.</span><span class="n">ACTION_VIEW</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="c1">// handle the redirect from sign in
|
|
</span> <span class="n">handleAuthResponse</span><span class="p">(</span><span class="n">intent</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>This new <code class="highlighter-rouge">onCreate</code> does several things:</p>
|
|
|
|
<ul>
|
|
<li>Define the initial state for the <code class="highlighter-rouge">signInButton</code>.</li>
|
|
<li>Supply authentication information for connecting to your Blockstack app: <code class="highlighter-rouge">appDomain</code>, <code class="highlighter-rouge">redirectURI</code>, <code class="highlighter-rouge">manifestURI</code> and <code class="highlighter-rouge">scopes</code></li>
|
|
<li>Add a listener for the button click.</li>
|
|
</ul>
|
|
|
|
<p>Notice that the application in this example is a URI you have not set up.
|
|
Registering and application name takes time, so in time’s interest you’ll
|
|
use an existing app that is identical to the <code class="highlighter-rouge">hello-world</code> you created
|
|
earlier. For a produciton verison, you’ll need to replace <code class="highlighter-rouge">appDomain</code>,
|
|
<code class="highlighter-rouge">redirectURI</code>, <code class="highlighter-rouge">manifestURI</code> and <code class="highlighter-rouge">scopes</code> with values appropriate for your
|
|
app.</p>
|
|
</li>
|
|
<li>
|
|
<p>Add a private function to reflect when a user successfully signs in.</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code> <span class="k">private</span> <span class="k">fun</span> <span class="nf">onSignIn</span><span class="p">(</span><span class="n">userData</span><span class="p">:</span> <span class="n">UserData</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">userDataTextView</span><span class="p">.</span><span class="n">text</span> <span class="p">=</span> <span class="s">"Signed in as ${userData.decentralizedID}"</span>
|
|
|
|
<span class="n">signInButton</span><span class="p">.</span><span class="n">isEnabled</span> <span class="p">=</span> <span class="k">false</span>
|
|
|
|
<span class="p">}</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Handle sign in requests with an <code class="highlighter-rouge">onNewIntent</code> function if the activity was already opened when signing in</p>
|
|
|
|
<p>Retrieve the authentication token from the custom protocol handler call and
|
|
send it to the Blockstack session.</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code> <span class="k">override</span> <span class="k">fun</span> <span class="nf">onNewIntent</span><span class="p">(</span><span class="n">intent</span><span class="p">:</span> <span class="n">Intent</span><span class="p">?)</span> <span class="p">{</span>
|
|
<span class="k">super</span><span class="p">.</span><span class="n">onNewIntent</span><span class="p">(</span><span class="n">intent</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">intent</span><span class="o">?.</span><span class="n">action</span> <span class="p">==</span> <span class="n">Intent</span><span class="p">.</span><span class="n">ACTION_VIEW</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">handleAuthResponse</span><span class="p">(</span><span class="n">intent</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Create a handler for the authentication response.</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code> <span class="k">private</span> <span class="k">fun</span> <span class="nf">handleAuthResponse</span><span class="p">(</span><span class="n">intent</span><span class="p">:</span> <span class="n">Intent</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">response</span> <span class="p">=</span> <span class="n">intent</span><span class="p">.</span><span class="n">dataString</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">response</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">authResponseTokens</span> <span class="p">=</span> <span class="n">response</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="sc">':'</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">authResponseTokens</span><span class="p">.</span><span class="n">size</span> <span class="p">></span> <span class="m">1</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">authResponse</span> <span class="p">=</span> <span class="n">authResponseTokens</span><span class="p">[</span><span class="m">1</span><span class="p">]</span>
|
|
|
|
<span class="n">blockstackSession</span><span class="p">().</span><span class="n">handlePendingSignIn</span><span class="p">(</span><span class="n">authResponse</span><span class="p">,</span> <span class="p">{</span> <span class="n">userData</span> <span class="p">-></span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">userData</span><span class="p">.</span><span class="n">hasValue</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="c1">// The user is now signed in!
|
|
</span> <span class="n">runOnUiThread</span> <span class="p">{</span>
|
|
<span class="n">onSignIn</span><span class="p">(</span><span class="n">userData</span><span class="p">.</span><span class="n">value</span><span class="o">!!</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">})</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Add the convenience method to access the blockstack session.</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code> <span class="k">fun</span> <span class="nf">blockstackSession</span><span class="p">()</span> <span class="p">:</span> <span class="n">BlockstackSession</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">session</span> <span class="p">=</span> <span class="n">_blockstackSession</span>
|
|
<span class="k">if</span><span class="p">(</span><span class="n">session</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="n">session</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">throw</span> <span class="n">IllegalStateException</span><span class="p">(</span><span class="s">"No session."</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Verify your final <code class="highlighter-rouge">MainActivity.kt</code> code looks like this:</p>
|
|
|
|
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code> <span class="kd">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">AppCompatActivity</span><span class="p">()</span> <span class="p">{</span>
|
|
|
|
<span class="k">private</span> <span class="kd">var</span> <span class="py">_blockstackSession</span><span class="p">:</span> <span class="n">BlockstackSession</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
|
|
|
|
|
|
<span class="k">override</span> <span class="k">fun</span> <span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span> <span class="n">Bundle</span><span class="p">?)</span> <span class="p">{</span>
|
|
<span class="k">super</span><span class="p">.</span><span class="n">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
|
|
<span class="n">setContentView</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="n">layout</span><span class="p">.</span><span class="n">activity_main</span><span class="p">)</span>
|
|
|
|
<span class="n">signInButton</span><span class="p">.</span><span class="n">isEnabled</span> <span class="p">=</span> <span class="k">false</span>
|
|
|
|
<span class="kd">val</span> <span class="py">appDomain</span> <span class="p">=</span> <span class="n">URI</span><span class="p">(</span><span class="s">"https://flamboyant-darwin-d11c17.netlify.com"</span><span class="p">)</span>
|
|
<span class="kd">val</span> <span class="py">redirectURI</span> <span class="p">=</span> <span class="n">URI</span><span class="p">(</span><span class="s">"${appDomain}/redirect"</span><span class="p">)</span>
|
|
<span class="kd">val</span> <span class="py">manifestURI</span> <span class="p">=</span> <span class="n">URI</span><span class="p">(</span><span class="s">"${appDomain}/manifest.json"</span><span class="p">)</span>
|
|
<span class="kd">val</span> <span class="py">scopes</span> <span class="p">=</span> <span class="n">arrayOf</span><span class="p">(</span><span class="n">Scope</span><span class="p">.</span><span class="n">StoreWrite</span><span class="p">)</span>
|
|
|
|
<span class="n">_blockstackSession</span> <span class="p">=</span> <span class="n">BlockstackSession</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="n">appDomain</span><span class="p">,</span> <span class="n">redirectURI</span><span class="p">,</span> <span class="n">manifestURI</span><span class="p">,</span> <span class="n">scopes</span><span class="p">,</span>
|
|
<span class="n">onLoadedCallback</span> <span class="p">=</span> <span class="p">{</span><span class="n">signInButton</span><span class="p">.</span><span class="n">isEnabled</span> <span class="p">=</span> <span class="k">true</span>
|
|
<span class="p">})</span>
|
|
|
|
|
|
<span class="n">signInButton</span><span class="p">.</span><span class="n">setOnClickListener</span> <span class="p">{</span> <span class="n">view</span><span class="p">:</span> <span class="n">View</span> <span class="p">-></span>
|
|
<span class="n">blockstackSession</span><span class="p">().</span><span class="n">redirectUserToSignIn</span> <span class="p">{</span> <span class="n">userData</span> <span class="p">-></span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">userData</span><span class="p">.</span><span class="n">hasValue</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">runOnUiThread</span> <span class="p">{</span>
|
|
<span class="n">onSignIn</span><span class="p">(</span><span class="n">userData</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">intent</span><span class="o">?.</span><span class="n">action</span> <span class="p">==</span> <span class="n">Intent</span><span class="p">.</span><span class="n">ACTION_VIEW</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">handleAuthResponse</span><span class="p">(</span><span class="n">intent</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">private</span> <span class="k">fun</span> <span class="nf">onSignIn</span><span class="p">(</span><span class="n">userData</span><span class="p">:</span> <span class="n">UserData</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">userDataTextView</span><span class="p">.</span><span class="n">text</span> <span class="p">=</span> <span class="s">"Signed in as ${userData.decentralizedID}"</span>
|
|
|
|
<span class="n">signInButton</span><span class="p">.</span><span class="n">isEnabled</span> <span class="p">=</span> <span class="k">false</span>
|
|
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">override</span> <span class="k">fun</span> <span class="nf">onNewIntent</span><span class="p">(</span><span class="n">intent</span><span class="p">:</span> <span class="n">Intent</span><span class="p">?)</span> <span class="p">{</span>
|
|
<span class="k">super</span><span class="p">.</span><span class="n">onNewIntent</span><span class="p">(</span><span class="n">intent</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">intent</span><span class="o">?.</span><span class="n">action</span> <span class="p">==</span> <span class="n">Intent</span><span class="p">.</span><span class="n">ACTION_VIEW</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">handleAuthResponse</span><span class="p">(</span><span class="n">intent</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">private</span> <span class="k">fun</span> <span class="nf">handleAuthResponse</span><span class="p">(</span><span class="n">intent</span><span class="p">:</span> <span class="n">Intent</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">response</span> <span class="p">=</span> <span class="n">intent</span><span class="p">.</span><span class="n">dataString</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">response</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">authResponseTokens</span> <span class="p">=</span> <span class="n">response</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="sc">':'</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">authResponseTokens</span><span class="p">.</span><span class="n">size</span> <span class="p">></span> <span class="m">1</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">authResponse</span> <span class="p">=</span> <span class="n">authResponseTokens</span><span class="p">[</span><span class="m">1</span><span class="p">]</span>
|
|
|
|
<span class="n">blockstackSession</span><span class="p">().</span><span class="n">handlePendingSignIn</span><span class="p">(</span><span class="n">authResponse</span><span class="p">,</span> <span class="p">{</span> <span class="n">userData</span> <span class="p">-></span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">userData</span><span class="p">.</span><span class="n">hasValue</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="c1">// The user is now signed in!
|
|
</span> <span class="n">runOnUiThread</span> <span class="p">{</span>
|
|
<span class="n">onSignIn</span><span class="p">(</span><span class="n">userData</span><span class="p">.</span><span class="n">value</span><span class="o">!!</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">})</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">fun</span> <span class="nf">blockstackSession</span><span class="p">()</span> <span class="p">:</span> <span class="n">BlockstackSession</span> <span class="p">{</span>
|
|
<span class="kd">val</span> <span class="py">session</span> <span class="p">=</span> <span class="n">_blockstackSession</span>
|
|
<span class="k">if</span><span class="p">(</span><span class="n">session</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="n">session</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">throw</span> <span class="n">IllegalStateException</span><span class="p">(</span><span class="s">"No session."</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
|
|
<span class="p">}</span>
|
|
</code></pre>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
|
|
<h3 id="run-the-final-app-in-the-emulator">Run the final app in the emulator</h3>
|
|
|
|
<ol>
|
|
<li>Choose <strong>Run > Apply changes</strong>.</li>
|
|
<li>Choose <strong>Run > Run app</strong> in the emulator.</li>
|
|
<li>
|
|
<p>When you see the application open, choose <strong>Sign in with Blockstack</strong>.</p>
|
|
|
|
<p>The system prompts you how to open.</p>
|
|
|
|
<p><img src="images/chrome-prompt.png" alt="" /></p>
|
|
</li>
|
|
<li>Choose <strong>Chrome</strong> and click <strong>ALWAYS</strong>.</li>
|
|
<li>
|
|
<p>Move through the rest of the Chrome prompts.</p>
|
|
|
|
<p>The system presents you with your final application.</p>
|
|
|
|
<p><img src="images/final-app.png" alt="" /></p>
|
|
</li>
|
|
<li>Work through the Blockstack prompts to login.</li>
|
|
</ol>
|
|
|
|
<h2 id="where-to-go-next">Where to go next</h2>
|
|
|
|
<p>Congratulations, you’ve completed your Android app using the new, pre-release
|
|
Blockstack Android SDK. Thank you for trying this pre-release. Please let us
|
|
know about your experience by tweeting to
|
|
<a href="https://twitter.com/blockstack">@blockstack</a>.</p>
|
|
|
|
<p>Learn more about Blockstack by <a href="https://blockstack.org/tutorials">trying another tutorial</a>.</p>
|
|
|
|
<div class="share uk-text-center">
|
|
<a href="https://twitter.com/intent/tweet?text=Android SDK Tutorial (Pre-release)&url=https://zbabystack.netlify.com/android/tutorial.html&via=&related=" rel="nofollow" target="_blank" title="Share on Twitter" onclick="window.open(this.href, 'twitter', 'width=550,height=235');return false;"><span data-uk-icon="icon: twitter; ratio: 1.2"></span></a>
|
|
<a class="uk-margin-small-left" href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fzbabystack.netlify.com%2Fandroid%2Ftutorial.html" rel="nofollow" target="_blank" title="Share on Facebook" onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;"><span data-uk-icon="icon: facebook; ratio: 1.2"></span></a>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<hr class="uk-margin-medium">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- <div class="uk-margin-large-top">
|
|
<h3>Related Articles</h3>
|
|
|
|
|
|
|
|
|
|
|
|
<ul class="uk-list">
|
|
|
|
</ul>
|
|
</div>
|
|
-->
|
|
|
|
</article>
|
|
|
|
<script>
|
|
// Table of contents scroll to
|
|
UIkit.scroll('#markdown-toc a', {
|
|
duration: 400,
|
|
offset: 120
|
|
});
|
|
</script>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="offcanvas" data-uk-offcanvas="flip: true; overlay: true">
|
|
<div class="uk-offcanvas-bar">
|
|
|
|
<button class="uk-offcanvas-close" type="button" data-uk-close></button>
|
|
|
|
<ul class="uk-nav uk-nav-default">
|
|
<!-- <li><a class="uk-logo uk-margin-small-bottom" href="/"><img src="https://zbabystack.netlify.com/assets/posts/logo.png" alt="Docs"></a></li> -->
|
|
<li><a class="uk-logo uk-margin-small-bottom" href="/"><img src="/assets/posts/logo.png" alt="Docs"></a></li>
|
|
|
|
|
|
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li>
|
|
|
|
|
|
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li>
|
|
|
|
|
|
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li>
|
|
|
|
</ul>
|
|
|
|
<div class="uk-margin-small-top uk-text-center uk-text-muted uk-link-muted">
|
|
<div data-uk-grid class="uk-child-width-auto uk-grid-small uk-flex-center uk-grid">
|
|
|
|
<div class="uk-first-column">
|
|
<a href="https://twitter.com/" data-uk-icon="icon: twitter" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
<div>
|
|
<a href="https://www.facebook.com/" data-uk-icon="icon: facebook" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
<a href="https://www.instagram.com/" data-uk-icon="icon: instagram" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
|
<a href="https://vimeo.com/" data-uk-icon="icon: vimeo" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<footer class="uk-section uk-text-center uk-text-muted uk-link-muted">
|
|
<div class="uk-container uk-container-small">
|
|
|
|
<!-- <div>
|
|
<ul class="uk-subnav uk-flex-center">
|
|
|
|
|
|
|
|
|
|
<li><a href="https://blockstack.org" target="_blank" >Blockstack.org</a></li>
|
|
|
|
|
|
|
|
|
|
|
|
<li><a href="https://forum.blockstack.org/" target="_blank" >Forums</a></li>
|
|
|
|
|
|
|
|
|
|
|
|
<li><a href="https://github.com/blockstack" target="_blank" >GitHub</a></li>
|
|
|
|
|
|
</ul>
|
|
</div>
|
|
<div class="uk-margin-medium">
|
|
<div data-uk-grid class="uk-child-width-auto uk-grid-small uk-flex-center uk-grid">
|
|
|
|
<div class="uk-first-column">
|
|
<a href="https://twitter.com/" data-uk-icon="icon: twitter" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
<div>
|
|
<a href="https://www.facebook.com/" data-uk-icon="icon: facebook" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
<a href="https://www.instagram.com/" data-uk-icon="icon: instagram" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
|
<a href="https://vimeo.com/" data-uk-icon="icon: vimeo" class="uk-icon-link uk-icon" target="_blank"></a>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
</div> -->
|
|
<div class="uk-margin-medium uk-text-small copyright">© 2018 Blockstack</div>
|
|
|
|
</div>
|
|
</footer>
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
/* Create a configuration object */
|
|
var ss360Config = {
|
|
/* Your site id */
|
|
siteId: 'blockstack',
|
|
/* A CSS selector that points to your search box */
|
|
searchBox: {selector: '#searchBox'}
|
|
};
|
|
</script>
|
|
<script src="https://cdn.sitesearch360.com/sitesearch360-v11.min.js" async></script>
|
|
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|