ll-hax-docs/sif/sif-android/index.html
2025-02-23 20:27:29 -06:00

867 lines
No EOL
23 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://ll.hax.sif.moe/sif/sif-android/">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.39">
<title>Sif android - LL Hax Docs</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.8c3ca2c6.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../../style/better.css">
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="pink" data-md-color-accent="deep-purple">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#setup_for_android" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="LL Hax Docs" class="md-header__button md-logo" aria-label="LL Hax Docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
LL Hax Docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Sif android
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="pink" data-md-color-accent="deep-purple" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="pink" data-md-color-accent="deep-purple" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="LL Hax Docs" class="md-nav__button md-logo" aria-label="LL Hax Docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
LL Hax Docs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../.." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../pugu/" class="md-nav__link">
<span class="md-ellipsis">
Puchiguru
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
SIF
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
SIF
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../" class="md-nav__link">
<span class="md-ellipsis">
SIF - Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../private-servers/" class="md-nav__link">
<span class="md-ellipsis">
Private (self hostable) servers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../apk-patching/" class="md-nav__link">
<span class="md-ellipsis">
Patching the apk
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ipa-patching/" class="md-nav__link">
<span class="md-ellipsis">
Patching the ipa
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../sifac/" class="md-nav__link">
<span class="md-ellipsis">
SIFAC
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
SIFAS
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
SIFAS
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../sifas/" class="md-nav__link">
<span class="md-ellipsis">
SIFAS - Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../sifas/private-server/" class="md-nav__link">
<span class="md-ellipsis">
Private (self hostable) servers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../sifas/easy-install/" class="md-nav__link">
<span class="md-ellipsis">
Easy install
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../sifas/apk-patching/" class="md-nav__link">
<span class="md-ellipsis">
Patching the apk
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
SIF2
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
SIF2
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../sif2/" class="md-nav__link">
<span class="md-ellipsis">
SIF2 - Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../sif2/private-servers/" class="md-nav__link">
<span class="md-ellipsis">
Private (self hostable) servers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../sif2/easy-install/" class="md-nav__link">
<span class="md-ellipsis">
Easy install
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../contributing/" class="md-nav__link">
<span class="md-ellipsis">
Contributing
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#setup_for_android" class="md-nav__link">
<span class="md-ellipsis">
Setup for Android
</span>
</a>
<nav class="md-nav" aria-label="Setup for Android">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#download_the_apk_android_package" class="md-nav__link">
<span class="md-ellipsis">
Download the APK (Android Package)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#modifying_the_app_to_point_to_your_pc" class="md-nav__link">
<span class="md-ellipsis">
Modifying the app to point to your PC
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#seting_up_the_private_server" class="md-nav__link">
<span class="md-ellipsis">
Seting up the private server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#setting_up_llsifhome" class="md-nav__link">
<span class="md-ellipsis">
Setting up LLSIF@Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#setting_up_npps4" class="md-nav__link">
<span class="md-ellipsis">
Setting up NPPS4
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1>Sif android</h1>
<h2 id="setup_for_android">Setup for Android<a class="headerlink" href="#setup_for_android" title="Permanent link">&para;</a></h2>
<h3 id="download_the_apk_android_package">Download the APK (Android Package)<a class="headerlink" href="#download_the_apk_android_package" title="Permanent link">&para;</a></h3>
<p>Retrieve the APK file. There are many locations for this, but the main requirement is that it's patched to work with the server we'll be setting up. Try getting it at the locations below:</p>
<ul>
<li><a href="https://cdn.sif.moe/lovelive-community.apk">https://cdn.sif.moe/lovelive-community.apk</a></li>
<li><a href="https://ethanthesleepy.one/public/lovelive/sif/lovelive-community.apk">https://ethanthesleepy.one/public/lovelive/sif/lovelive-community.apk</a></li>
</ul>
<p>The apk has been modified to do the following:</p>
<ul>
<li>Automatic in-game language selection between English and Japanese based on system language or Android 13 per-app language setting.</li>
<li>Runs natively in Android emulator. All binaries supported by Android, including x86-64, is available.</li>
<li>Activates debug mode which show a little bit more information in-game.</li>
<li>Backtrace, AppsFlyer, and Google Play is neutralized.</li>
<li>Backtrace error is printed to logcat.</li>
<li>Uses RSA private key from tungnotpunk/LLSIF@Home which should be compatible with LLSIF@Home and NPPS4.</li>
<li>AppAssets.zip is patched to load from localhost:51376. This means it's compatible with LLSIF@Home and NPPS4.</li>
</ul>
<p>This apk is signed with the following cert hash. This can be verified with an app like appverifier.
<code>07:31:46:BE:D1:B2:13:E6:00:57:DA:4C:05:4F:A1:9C:41:AA:99:77:E2:A8:E8:26:93:CB:84:54:E6:C1:8E:71</code></p>
<p>Note: It does NOT contain patch to neutralize X-Message-Sign check. If you can't get XMS verification working, you need to patch it yourself. You should make your private server generate the correct XMS, though.
Note2: It's recommended to launch the game in English for the first time. Otherwise, when you launch the game in Japanese for the first time, switching to English will erase all your game data (excluding your account). This logic is in the Lua script of the game. Help on neutralizing this behavior is welcome.</p>
<p>How to generate X-Message-Sign:
- <a href="https://github.com/DarkEnergyProcessor/NPPS4/blob/b24b4e2a71be3c268c069a49bd3fae2bb25d7feb/npps4/util.py#L37-L42">Python</a>
- <a href="https://codeberg.org/dic1911/LLSIF.local/src/commit/e7e780258dca86c2f1a77577897fad23298fe9c7/handler/util.js#L18-L34">NodeJS</a>
- <a href="https://github.com/ethanaobrien/sif-server/blob/4dbd8d837ebb1d497420359c340541e8c8c69316/src/router/global.rs#L73-L92">Rust</a></p>
<p>After the APK is retrieved and installed, then you should install the private server.</p>
<h3 id="modifying_the_app_to_point_to_your_pc">Modifying the app to point to your PC<a class="headerlink" href="#modifying_the_app_to_point_to_your_pc" title="Permanent link">&para;</a></h3>
<p>Please see <a href="../apk-patching/">APK patching</a>.</p>
<h3 id="seting_up_the_private_server">Seting up the private server<a class="headerlink" href="#seting_up_the_private_server" title="Permanent link">&para;</a></h3>
<p>There are currently 2 recommended private servers for SIF:</p>
<ul>
<li>NPPS4: Written in Python. This server implements progression and attempts to emulate the official server as closely as possible. Gacha works.</li>
<li>LLSIF@Home: Written in JavaScript using NodeJS. This server gives you all cards, and all songs are unlocked. There is no progression, and gacha does not work. <strong>This method is recommended for those that are less-techsavvy.</strong></li>
</ul>
<h3 id="setting_up_llsifhome">Setting up LLSIF@Home<a class="headerlink" href="#setting_up_llsifhome" title="Permanent link">&para;</a></h3>
<ol>
<li>Install Termux</li>
<li>Run this command(s) inside of <code>Termux</code>:</li>
</ol>
<pre><code>curl http://ll.sif.moe/android | bash
</code></pre>
<p><strong><em>OR</em></strong> (if the command above fails do the commands below)</p>
<pre><code>wget http://ll.sif.moe/android
bash android
</code></pre>
<p>(curl is broken currently, this will be one command if curl is fixed)
3. After it is done and it shows you the link to the discord/matrix server. <strong>Enter <code>exit</code> and re-launch termux.</strong>
4. You can run <code>runserver</code> to start the private server.
4. After this is done, you should be able to launch the game and it should just work. Message in the discord or matrix if help is needed.</p>
<h3 id="setting_up_npps4">Setting up NPPS4<a class="headerlink" href="#setting_up_npps4" title="Permanent link">&para;</a></h3>
<ul>
<li>Please refer to <a href="https://gist.github.com/MikuAuahDark/eabf54e9db3f5004e3ccd9a72f0d79d5">this guide</a></li>
</ul>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../../assets/javascripts/bundle.525ec568.min.js"></script>
</body>
</html>