Skip to content

Commit

Permalink
Android support
Browse files Browse the repository at this point in the history
  • Loading branch information
GarboMuffin committed Dec 12, 2021
1 parent 26c8e4b commit a2cd95f
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 6 deletions.
5 changes: 4 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"p4": {
"description1": {
"string": "Converts Scratch projects into HTML files, zip archives, or executable programs for Windows, macOS, and Linux."
"string": "Converts Scratch projects into HTML files, zip archives, or executable programs for Windows, macOS, Linux, and Android."
},
"description2": {
"string": "If you just want an easy way to embed a project into your website, you may be interested in {embedding}."
Expand Down Expand Up @@ -363,6 +363,9 @@
"string": "{type} Linux application (64-bit only)",
"context": "type will become something like 'NW.js' or 'Electron'. Do not translate 'Linux'."
},
"application-android": {
"string": "Android app (Highly experimental)"
},
"otherEnvironments": {
"string": "Other environments (Click to open)",
"context": "Text that can be clicked to expand list of environments to include some unrecommended ones."
Expand Down
2 changes: 1 addition & 1 deletion src/p4/P4.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
:global([theme="dark"] .is-not-safari select:hover) {
border-color: #bbb;
}
:global(p), :global(h1), :global(h2), :global(h3) {
:global(p), :global(pre), :global(h1), :global(h2), :global(h3) {
margin: 12px 0;
}
:global(summary) {
Expand Down
133 changes: 130 additions & 3 deletions src/p4/PackagerOptions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,9 @@
font-weight: bold;
background: yellow;
color: black;
padding: 10px;
border-radius: 10px;
padding: 12px;
border-radius: 12px;
margin: 12px 0;
}
</style>

Expand Down Expand Up @@ -609,6 +610,13 @@
</label>
</div>

<div class="group">
<label class="option">
<input type="radio" name="environment" bind:group={$options.target} value="android">
{$_('options.application-android')}
</label>
</div>

<details open={otherEnvironmentsInitiallyOpen}>
<summary>{$_('options.otherEnvironments')}</summary>
<p>{$_('options.otherEnvironmentsHelp')}</p>
Expand Down Expand Up @@ -660,7 +668,8 @@
{#if $options.target.startsWith('zip')}
<h2>Zip</h2>
<p>The zip environment is intended to be used for publishing to a website. Other uses such as sending your project to a friend over a chat app or email should use "Plain HTML" instead as zip will not work.</p>
{:else}
{/if}
{#if !$options.target.startsWith('zip')}
<h2>{$_('options.applicationSettings')}</h2>
<label class="option">
{$_('options.packageName')}
Expand Down Expand Up @@ -715,6 +724,124 @@
<p class="warning">NW.js support is deprecated and may be removed in the future. Use Electron instead if possible.</p>
<p>For further help and steps, see <a href="https://docs.nwjs.io/en/latest/For%20Users/Package%20and%20Distribute/#linux">NW.js Documentation</a>.</p>
{/if}
{:else if $options.target === 'android'}
<h2>Android</h2>

<div class="warning">
Unlike the other environments, Android support is not fully automated. You must manually create an app. This section will try to guide you through the process.
</div>

<p>This section assumes you have complete access to a Windows, macOS, or Linux computer.</p>

<h3>Install Android Studio</h3>
<p><a href="https://developer.android.com/studio/">Install Android Studio.</a></p>
<p>This quite large and may take a while.</p>

<h3>Create a new project</h3>
<p>Create a new project in Android studio.</p>
<ul>
<li>Use the "Empty Activity" template</li>
<li>Set Name to your app's name, for example "<code>{$options.app.windowTitle}</code>"</li>
<li>Set Package name to "<code>org.turbowarp.packager.userland.{$options.app.packageName}</code>"</li>
<li>Choose a save location that you won't forget</li>
<li>Set Language to Kotlin</li>
<li>Set Minimum SDK to "API 21: Android 5.0 (Lollipop)"</li>
</ul>

<h3>Create assets folder</h3>
<p>In the sidebar on the left, right click on "app", then select "New" > "Folder" > "Assets folder". Use the default settings.</p>

<h3>Prepare project</h3>
<p>
<Button on:click={pack} text={'Package the project as a zip'} />
</p>
<p>Extract the zip and drag its files into "assets" folder you created. (You can directly drag and drop files over the assets folder in Android Studio)</p>

<h3>Making the app</h3>
<p>In the sidebar on the left, navigate to app > src > main > MainActivity. This will open a short Kotlin file.</p>
<p>Replace everything after line 2 with the following:</p>
<pre>
{[
'import android.annotation.SuppressLint',
'import androidx.appcompat.app.AppCompatActivity',
'import android.os.Bundle',
'import android.webkit.WebView',
'',
'class MainActivity : AppCompatActivity() {',
' private lateinit var web: WebView',
'',
' @SuppressLint("SetJavaScriptEnabled")',
' override fun onCreate(savedInstanceState: Bundle?) {',
' super.onCreate(savedInstanceState)',
' web = WebView(this)',
' web.settings.javaScriptEnabled = true',
' web.loadUrl("file:///android_asset/index.html")',
' setContentView(web)',
' actionBar?.hide()',
' supportActionBar?.hide()',
' }',
'',
' override fun onDestroy() {',
' super.onDestroy()',
' web.destroy()',
' }',
'}'
].join('\n')}
</pre>
<p>At this point, you now have a fully functional Android app. However, there are still a few more things you should change.</p>

<h3>Fixing screen orientation issues</h3>
<p>In the sidebar on the left, open app > main > AndroidManifest.xml</p>
<p>Find the section that looks like this:</p>
<pre>
{[
' <activity',
' android:name=".MainActivity"',
' android:exported="true">',
].join('\n')}
</pre>
<p>And replace it with this:</p>
<pre>
{[
' <activity',
' android:configChanges="orientation|screenSize"',
' android:screenOrientation="sensor"',
' android:name=".MainActivity"',
' android:exported="true">',
].join('\n')}
</pre>

<h3>Updating colors</h3>
<p>If you ran the app now, it would have a purple color scheme, which may not be what you want. This can be changed.</p>
<p>In the sidebar on the left, open app > main > res > values > color.xml.</p>
<p>You will see these lines:</p>
<pre>
{[
' <color name="purple_200">#FFBB86FC</color>',
' <color name="purple_500">#FF6200EE</color>',
' <color name="purple_700">#FF3700B3</color>',
].join('\n')}
</pre>
<p>Replace those lines with:</p>
<pre>
{[
` <color name="purple_200">#FF${$options.appearance.background.substr(1)}</color>`,
` <color name="purple_500">#FF${$options.appearance.background.substr(1)}</color>`,
` <color name="purple_700">#FF${$options.appearance.background.substr(1)}</color>`,
].join('\n')}
</pre>
<p>Do not change the other lines.</p>
<p>The above snippet will make the status bar match your app's background color. For advanced users, note that these color codes are a bit unusual in that the "alpha" or "transparency" byte goes first instead of last.</p>
<p>Ignore the bits about <code>purple_yyy</code> -- just them as is. While it would be a good idea to these colors, you will be making more work for yourself because you'll have to update some other files to reflect the new names.</p>

<h3>Updating the project</h3>
<p>It's likely that at some point you will want to update the project without redoing this entire guide. Updating is much simpler:</p>
<ol>
<li>Open Android Studio and open the project</li>
<li>Delete everything inside the assets folder</li>
<li>Re-run the packager</li>
<li>Extract the zip and put all of its files into the assets folder</li>
</ol>
{/if}
</div>
</Section>
Expand Down
2 changes: 1 addition & 1 deletion src/p4/template.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<% const {LONG_NAME, WEBSITE} = require('../packager/brand.js'); %>
<title><%= LONG_NAME %></title>
<meta name="description" content="Converts Scratch projects into HTML files, zip archives, or executable programs for Windows, macOS, and Linux.">
<meta name="description" content="Converts Scratch projects into HTML files, zip archives, or executable programs for Windows, macOS, Linux, and Android.">
<% if (process.env.STANDALONE) { %>
<%
const fs = require('fs');
Expand Down
17 changes: 17 additions & 0 deletions src/packager/packager.js
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,23 @@ cd "$(dirname "$0")"
vm.extensionManager.loadExtensionURL(extension);
}
${this.options.target === 'android' ? `
// By default, storage will try to use fetch() in a Worker
// That doesn't work in an Android WebView, but XHR does, so...
scaffolding.storage.addHelper({
load: (assetType, assetId, dataFormat) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = "arraybuffer";
xhr.onerror = () => reject(new Error("Request failed"));
xhr.onload = () => resolve(new scaffolding.storage.Asset(assetType, assetId, dataFormat, new Uint8Array(xhr.response)));
xhr.open("GET", './assets/' + assetId + '.' + dataFormat);
xhr.send();
}),
// Above default tool, below "builtin" tool
priority: 50
});
` : ''}
${this.options.target.startsWith('nwjs-') ? `
if (typeof nw !== 'undefined') {
const win = nw.Window.get();
Expand Down

0 comments on commit a2cd95f

Please sign in to comment.