🌅
This commit is contained in:
commit
872c00b53c
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.*.swp
|
||||||
|
!.gitignore
|
||||||
|
TODO
|
||||||
|
__pycache__
|
||||||
|
*.egg-info/
|
||||||
|
/build/
|
||||||
|
/dist/
|
||||||
9
.gitlab-ci.yml
Normal file
9
.gitlab-ci.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
variables:
|
||||||
|
TUTOR_PLUGIN: android
|
||||||
|
TUTOR_IMAGES: android
|
||||||
|
TUTOR_PYPI_PACKAGE: tutor-android
|
||||||
|
OPENEDX_RELEASE: lilac
|
||||||
|
|
||||||
|
include:
|
||||||
|
- project: 'community/tutor-ci'
|
||||||
|
file: 'plugin-gitlab-ci.yml'
|
||||||
2
MANIFEST.in
Normal file
2
MANIFEST.in
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
recursive-include tutorandroid/patches *
|
||||||
|
recursive-include tutorandroid/templates *
|
||||||
22
README.rst
Normal file
22
README.rst
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
android plugin for `Tutor <https://docs.tutor.overhang.io>`__
|
||||||
|
===================================================================================
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
pip install git+https://github.com/overhangio/tutor-android
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
tutor plugins enable android
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
This software is licensed under the terms of the AGPLv3.
|
||||||
61
setup.py
Normal file
61
setup.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import io
|
||||||
|
import os
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def load_readme():
|
||||||
|
with io.open(os.path.join(HERE, "README.rst"), "rt", encoding="utf8") as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def load_about():
|
||||||
|
about = {}
|
||||||
|
with io.open(
|
||||||
|
os.path.join(HERE, "tutorandroid", "__about__.py"),
|
||||||
|
"rt",
|
||||||
|
encoding="utf-8",
|
||||||
|
) as f:
|
||||||
|
exec(f.read(), about) # pylint: disable=exec-used
|
||||||
|
return about
|
||||||
|
|
||||||
|
|
||||||
|
ABOUT = load_about()
|
||||||
|
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="tutor-android",
|
||||||
|
version=ABOUT["__version__"],
|
||||||
|
url="https://github.com/overhangio/tutor-android",
|
||||||
|
project_urls={
|
||||||
|
"Code": "https://github.com/overhangio/tutor-android",
|
||||||
|
"Issue tracker": "https://github.com/overhangio/tutor-android/issues",
|
||||||
|
},
|
||||||
|
license="AGPLv3",
|
||||||
|
author="Overhang.IO",
|
||||||
|
description="android plugin for Tutor",
|
||||||
|
long_description=load_readme(),
|
||||||
|
packages=find_packages(exclude=["tests*"]),
|
||||||
|
include_package_data=True,
|
||||||
|
python_requires=">=3.5",
|
||||||
|
install_requires=["tutor-openedx>=12.0.0,<13.0.0"],
|
||||||
|
entry_points={
|
||||||
|
"tutor.plugin.v0": [
|
||||||
|
"android = tutorandroid.plugin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
classifiers=[
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: GNU Affero General Public License v3",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3.5",
|
||||||
|
"Programming Language :: Python :: 3.6",
|
||||||
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
],
|
||||||
|
)
|
||||||
1
tutorandroid/__about__.py
Normal file
1
tutorandroid/__about__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__version__ = "12.0.0"
|
||||||
0
tutorandroid/__init__.py
Normal file
0
tutorandroid/__init__.py
Normal file
52
tutorandroid/cli.py
Normal file
52
tutorandroid/cli.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import click
|
||||||
|
|
||||||
|
from tutor.commands.compose import ComposeJobRunner
|
||||||
|
from tutor.commands.context import Context
|
||||||
|
from tutor.commands.local import docker_compose as local_docker_compose
|
||||||
|
from tutor import config as tutor_config
|
||||||
|
from tutor import env as tutor_env
|
||||||
|
from tutor import fmt
|
||||||
|
from tutor.types import Config
|
||||||
|
|
||||||
|
|
||||||
|
@click.group(help="Build an Android app for your Open edX platform")
|
||||||
|
def android() -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(help="Build the application")
|
||||||
|
@click.argument("mode", type=click.Choice(["debug", "release"]))
|
||||||
|
@click.pass_obj
|
||||||
|
def build(context: Context, mode: str) -> None:
|
||||||
|
config = tutor_config.load(context.root)
|
||||||
|
docker_run(context.root, build_command(config, mode))
|
||||||
|
fmt.echo_info(
|
||||||
|
"The {} APK file is available in {}".format(
|
||||||
|
mode, tutor_env.data_path(context.root, "android")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_command(config: Config, target: str) -> str:
|
||||||
|
gradle_target = {
|
||||||
|
"debug": "assembleProdDebuggable",
|
||||||
|
"release": "assembleProdRelease",
|
||||||
|
}[target]
|
||||||
|
apk_folder = {"debug": "debuggable", "release": "release"}[target]
|
||||||
|
|
||||||
|
command = """
|
||||||
|
sed -i "s/APPLICATION_ID = .*/APPLICATION_ID = \\"{{ LMS_HOST|reverse_host|replace("-", "_") }}\\"/g" constants.gradle
|
||||||
|
./gradlew {gradle_target}
|
||||||
|
cp OpenEdXMobile/build/outputs/apk/prod/{apk_folder}/*.apk /openedx/data/"""
|
||||||
|
command = tutor_env.render_str(config, command)
|
||||||
|
command = command.format(gradle_target=gradle_target, apk_folder=apk_folder)
|
||||||
|
return command
|
||||||
|
|
||||||
|
|
||||||
|
def docker_run(root: str, command: str) -> None:
|
||||||
|
config = tutor_config.load(root)
|
||||||
|
runner = ComposeJobRunner(root, config, local_docker_compose)
|
||||||
|
runner.run_job("android", command)
|
||||||
|
|
||||||
|
|
||||||
|
android.add_command(build)
|
||||||
0
tutorandroid/patches/.gitignore
vendored
Normal file
0
tutorandroid/patches/.gitignore
vendored
Normal file
5
tutorandroid/patches/local-docker-compose-jobs-services
Normal file
5
tutorandroid/patches/local-docker-compose-jobs-services
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
android-job:
|
||||||
|
image: {{ ANDROID_DOCKER_IMAGE }}
|
||||||
|
volumes:
|
||||||
|
- "../android/:/openedx/config/"
|
||||||
|
- "../../data/android/:/openedx/data/"
|
||||||
37
tutorandroid/plugin.py
Normal file
37
tutorandroid/plugin.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from glob import glob
|
||||||
|
import os
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
from .__about__ import __version__
|
||||||
|
from .cli import android as android_command
|
||||||
|
|
||||||
|
|
||||||
|
templates = pkg_resources.resource_filename("tutorandroid", "templates")
|
||||||
|
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"add": {"OAUTH2_SECRET": "{{ 24|random_string }}"},
|
||||||
|
"defaults": {
|
||||||
|
"VERSION": __version__,
|
||||||
|
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/openedx-android:{{ ANDROID_VERSION }}",
|
||||||
|
"RELEASE_STORE_PASSWORD": "android store password",
|
||||||
|
"RELEASE_KEY_PASSWORD": "android release key password",
|
||||||
|
"RELEASE_KEY_ALIAS": "android release key alias",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks = {"build-image": {"android": "{{ ANDROID_DOCKER_IMAGE }}"}, "init": ["lms"]}
|
||||||
|
|
||||||
|
|
||||||
|
command = android_command
|
||||||
|
|
||||||
|
|
||||||
|
def patches():
|
||||||
|
all_patches = {}
|
||||||
|
patches_dir = pkg_resources.resource_filename("tutorandroid", "patches")
|
||||||
|
for path in glob(os.path.join(patches_dir, "*")):
|
||||||
|
with open(path) as patch_file:
|
||||||
|
name = os.path.basename(path)
|
||||||
|
content = patch_file.read()
|
||||||
|
all_patches[name] = content
|
||||||
|
return all_patches
|
||||||
0
tutorandroid/templates/android/apps/.gitignore
vendored
Normal file
0
tutorandroid/templates/android/apps/.gitignore
vendored
Normal file
3
tutorandroid/templates/android/apps/edx.properties
Normal file
3
tutorandroid/templates/android/apps/edx.properties
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
edx.android {
|
||||||
|
configFiles = ['tutor.yaml']
|
||||||
|
}
|
||||||
4
tutorandroid/templates/android/apps/gradle.properties
Normal file
4
tutorandroid/templates/android/apps/gradle.properties
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
RELEASE_STORE_FILE=/openedx/config/app.keystore
|
||||||
|
RELEASE_STORE_PASSWORD={{ ANDROID_RELEASE_STORE_PASSWORD }}
|
||||||
|
RELEASE_KEY_PASSWORD={{ ANDROID_RELEASE_KEY_PASSWORD }}
|
||||||
|
RELEASE_KEY_ALIAS={{ ANDROID_RELEASE_KEY_ALIAS }}
|
||||||
18
tutorandroid/templates/android/apps/tutor.yaml
Normal file
18
tutorandroid/templates/android/apps/tutor.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# See docs: https://openedx.atlassian.net/wiki/spaces/LEARNER/pages/48792067/App+Configuration+Flags
|
||||||
|
API_HOST_URL: "{{ "https" if ENABLE_HTTPS else "http" }}://{{ LMS_HOST }}"
|
||||||
|
ENVIRONMENT_DISPLAY_NAME: "tutor"
|
||||||
|
PLATFORM_NAME: "{{ PLATFORM_NAME }}"
|
||||||
|
PLATFORM_DESTINATION_NAME: "{{ LMS_HOST }}"
|
||||||
|
FEEDBACK_EMAIL_ADDRESS: "{{ CONTACT_EMAIL }}"
|
||||||
|
OAUTH_CLIENT_ID: "android"
|
||||||
|
|
||||||
|
COURSE_VIDEOS_ENABLED: true
|
||||||
|
CERTIFICATES_ENABLED: true
|
||||||
|
DISCUSSIONS_ENABLED: true
|
||||||
|
DISCOVERY:
|
||||||
|
COURSE:
|
||||||
|
TYPE: native
|
||||||
|
DOWNLOAD_TO_SD_CARD_ENABLED: true
|
||||||
|
NEW_LOGISTRATION_ENABLED: true
|
||||||
|
USER_PROFILES_ENABLED : true
|
||||||
|
VIDEO_TRANSCRIPT_ENABLED: true
|
||||||
0
tutorandroid/templates/android/build/.gitignore
vendored
Normal file
0
tutorandroid/templates/android/build/.gitignore
vendored
Normal file
40
tutorandroid/templates/android/build/android/Dockerfile
Normal file
40
tutorandroid/templates/android/build/android/Dockerfile
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
FROM docker.io/ubuntu:20.04
|
||||||
|
MAINTAINER Overhang.io <contact@overhang.io>
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt update && \
|
||||||
|
apt upgrade -y && \
|
||||||
|
apt install -y wget unzip git openjdk-8-jre openjdk-8-jdk
|
||||||
|
|
||||||
|
RUN mkdir /openedx
|
||||||
|
|
||||||
|
# Install Android SDK
|
||||||
|
# Inspired from https://github.com/LiveXP/docker-android-sdk/blob/master/Dockerfile
|
||||||
|
ENV ANDROID_SDK_VERSION 6200805
|
||||||
|
ENV ANDROID_SDK_PATH /openedx/android-sdk
|
||||||
|
ENV ANDROID_HOME /openedx/android-sdk
|
||||||
|
RUN mkdir ${ANDROID_HOME}
|
||||||
|
WORKDIR /openedx/android-sdk
|
||||||
|
RUN wget https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_VERSION}_latest.zip && \
|
||||||
|
unzip commandlinetools-linux-${ANDROID_SDK_VERSION}_latest.zip && \
|
||||||
|
rm commandlinetools-linux-${ANDROID_SDK_VERSION}_latest.zip
|
||||||
|
|
||||||
|
# Accept licenses
|
||||||
|
# https://developer.android.com/studio/command-line/sdkmanager
|
||||||
|
ARG ANDROID_API_LEVEL=28
|
||||||
|
RUN yes | /openedx/android-sdk/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install "platforms;android-$ANDROID_API_LEVEL" 1> /dev/null
|
||||||
|
|
||||||
|
# Install android app repo
|
||||||
|
ARG ANDROID_APP_REPOSITORY=https://github.com/edx/edx-app-android
|
||||||
|
ARG ANDROID_APP_VERSION=release/2.23.2
|
||||||
|
RUN git clone $ANDROID_APP_REPOSITORY --branch $ANDROID_APP_VERSION /openedx/edx-app-android
|
||||||
|
WORKDIR /openedx/edx-app-android
|
||||||
|
|
||||||
|
# Install gradle and all dependencies
|
||||||
|
RUN ./gradlew -v
|
||||||
|
RUN ./gradlew tasks
|
||||||
|
|
||||||
|
# User-customized config
|
||||||
|
COPY ./edx.properties ./OpenEdXMobile/edx.properties
|
||||||
|
RUN mkdir /openedx/config
|
||||||
|
RUN ln -s /openedx/config/gradle.properties ./OpenEdXMobile/gradle.properties
|
||||||
@ -0,0 +1 @@
|
|||||||
|
edx.dir = '/openedx/config'
|
||||||
0
tutorandroid/templates/android/hooks/.gitignore
vendored
Normal file
0
tutorandroid/templates/android/hooks/.gitignore
vendored
Normal file
12
tutorandroid/templates/android/hooks/lms/init
Normal file
12
tutorandroid/templates/android/hooks/lms/init
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Delete obsolete credentials for Android application
|
||||||
|
./manage.py lms shell -c 'from oauth2_provider.models import get_application_model
|
||||||
|
get_application_model().objects.filter(name="android").exclude(user__username="login_service_user").delete()'
|
||||||
|
# Create oauth credentials for Android application
|
||||||
|
./manage.py lms create_dot_application \
|
||||||
|
--client-id android \
|
||||||
|
--client-secret {{ ANDROID_OAUTH2_SECRET }} \
|
||||||
|
--grant-type password \
|
||||||
|
--public \
|
||||||
|
--update \
|
||||||
|
android \
|
||||||
|
login_service_user
|
||||||
Loading…
x
Reference in New Issue
Block a user