2020-05-19 23:30:00 +02:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
if [ "$#" -ne 2 ]; then
|
2020-05-20 00:59:58 +02:00
|
|
|
echo "USAGE: $0 APP_NAME DESCRIPTION"
|
2020-05-19 23:30:00 +02:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
PROJECT_HOME=~/AndroidStudioProjects
|
|
|
|
ORG_PATH="$PROJECT_HOME/defaultOrg"
|
|
|
|
KEY_PROPERTIES_PATH="$PROJECT_HOME/defaultKeyProperties"
|
|
|
|
|
2020-05-20 00:59:58 +02:00
|
|
|
appName="$1"
|
2020-05-21 16:33:24 +02:00
|
|
|
packageName=`echo "$appName" | tr ' ' '_' | tr '[:upper:]' '[:lower:]'`
|
2020-05-19 23:30:00 +02:00
|
|
|
description="$2"
|
|
|
|
|
2020-05-20 00:59:58 +02:00
|
|
|
echo "App Name: $appName"
|
2020-05-19 23:30:00 +02:00
|
|
|
echo "Package Name: $packageName"
|
|
|
|
echo "Description: $description"
|
|
|
|
|
|
|
|
|
|
|
|
if [[ -f "$ORG_PATH" ]]; then
|
|
|
|
org=`cat "$PROJECT_HOME/defaultOrg"`
|
|
|
|
else
|
|
|
|
echo "Could not find file with default org in $ORG_PATH"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ -f "$KEY_PROPERTIES_PATH" ]]; then
|
|
|
|
keyProperties=`cat "$PROJECT_HOME/defaultKeyProperties"`
|
|
|
|
else
|
|
|
|
echo "Could not find file with default key properties in $KEY_PROPERTIES_PATH"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2020-05-21 14:52:27 +02:00
|
|
|
flutter create --android-language java --org "$org" "$packageName" || exit 1
|
2020-05-19 23:30:00 +02:00
|
|
|
|
|
|
|
cd "$packageName"
|
|
|
|
|
2020-05-22 14:57:42 +02:00
|
|
|
##########################
|
|
|
|
## append to .gitignore ##
|
|
|
|
##########################
|
2020-05-19 23:30:00 +02:00
|
|
|
|
2020-05-22 14:57:42 +02:00
|
|
|
echo "android/key.properties" >> .gitignore
|
2020-05-19 23:30:00 +02:00
|
|
|
|
|
|
|
git init
|
|
|
|
|
|
|
|
##################################
|
|
|
|
## generate empty launcher icon ##
|
|
|
|
##################################
|
|
|
|
|
2020-05-24 22:00:05 +02:00
|
|
|
convert -size 2048x2048 xc:white launcherIcon.png
|
2020-05-19 23:30:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
############################
|
|
|
|
## overwrite pubspec.yaml ##
|
|
|
|
############################
|
|
|
|
|
|
|
|
cat > pubspec.yaml <<EOF
|
|
|
|
name: $packageName
|
|
|
|
description: $description
|
|
|
|
|
|
|
|
version: 1.0.0+1
|
|
|
|
|
|
|
|
environment:
|
|
|
|
sdk: ">=2.2.2 <3.0.0"
|
|
|
|
|
|
|
|
dependencies:
|
|
|
|
flutter:
|
|
|
|
sdk: flutter
|
|
|
|
intl: ^0.15.7
|
|
|
|
shared_preferences: ^0.5.4+8
|
|
|
|
cupertino_icons: ^0.1.2
|
|
|
|
|
|
|
|
dev_dependencies:
|
|
|
|
flutter_test:
|
|
|
|
sdk: flutter
|
|
|
|
flutter_launcher_icons: "^0.7.3"
|
|
|
|
|
|
|
|
flutter_icons:
|
2020-05-24 22:00:05 +02:00
|
|
|
image_path: "launcherIcon.png"
|
2020-05-19 23:30:00 +02:00
|
|
|
android: true
|
|
|
|
ios: true
|
|
|
|
|
|
|
|
flutter:
|
|
|
|
uses-material-design: true
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#########################################
|
|
|
|
## generate key.properties for signing ##
|
|
|
|
#########################################
|
|
|
|
|
|
|
|
cat > android/key.properties <<EOF
|
|
|
|
$keyProperties
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
############################
|
|
|
|
## overwrite build.gradle ##
|
|
|
|
############################
|
|
|
|
|
|
|
|
cat > android/app/build.gradle <<EOF
|
|
|
|
def localProperties = new Properties()
|
|
|
|
def localPropertiesFile = rootProject.file('local.properties')
|
|
|
|
if (localPropertiesFile.exists()) {
|
|
|
|
localPropertiesFile.withReader('UTF-8') { reader ->
|
|
|
|
localProperties.load(reader)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
|
|
|
if (flutterRoot == null) {
|
|
|
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
|
|
|
}
|
|
|
|
|
|
|
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
|
|
|
if (flutterVersionCode == null) {
|
|
|
|
flutterVersionCode = '1'
|
|
|
|
}
|
|
|
|
|
|
|
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
|
|
|
if (flutterVersionName == null) {
|
|
|
|
flutterVersionName = '1.0'
|
|
|
|
}
|
|
|
|
|
|
|
|
apply plugin: 'com.android.application'
|
|
|
|
apply from: "\$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
|
|
|
|
|
|
|
def keystoreProperties = new Properties()
|
|
|
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
|
|
|
if (keystorePropertiesFile.exists()) {
|
|
|
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
android {
|
2020-10-13 14:39:57 +02:00
|
|
|
compileSdkVersion 29
|
2020-05-19 23:30:00 +02:00
|
|
|
|
|
|
|
lintOptions {
|
|
|
|
disable 'InvalidPackage'
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultConfig {
|
|
|
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
|
|
|
applicationId "$org.$packageName"
|
|
|
|
minSdkVersion 16
|
2020-10-13 14:39:57 +02:00
|
|
|
targetSdkVersion 29
|
2020-05-19 23:30:00 +02:00
|
|
|
versionCode flutterVersionCode.toInteger()
|
|
|
|
versionName flutterVersionName
|
|
|
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
|
|
|
}
|
|
|
|
|
|
|
|
signingConfigs {
|
|
|
|
release {
|
|
|
|
keyAlias keystoreProperties['keyAlias']
|
|
|
|
keyPassword keystoreProperties['keyPassword']
|
|
|
|
storeFile file(keystoreProperties['storeFile'])
|
|
|
|
storePassword keystoreProperties['storePassword']
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buildTypes {
|
|
|
|
release {
|
|
|
|
signingConfig signingConfigs.release
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
flutter {
|
|
|
|
source '../..'
|
|
|
|
}
|
|
|
|
|
|
|
|
dependencies {
|
|
|
|
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'
|
|
|
|
}
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
2020-05-20 00:59:58 +02:00
|
|
|
#######################
|
|
|
|
## set android label ##
|
|
|
|
#######################
|
|
|
|
|
|
|
|
sed -i "s/android:label=\"$packageName\"/android:label=\"$appName\"/" android/app/src/main/AndroidManifest.xml
|
|
|
|
|
2020-05-19 23:30:00 +02:00
|
|
|
#####################
|
|
|
|
## empty README.md ##
|
|
|
|
#####################
|
|
|
|
cat > README.md <<EOF
|
2020-05-20 00:59:58 +02:00
|
|
|
# $appName
|
2020-05-19 23:30:00 +02:00
|
|
|
|
|
|
|
$description
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
2020-05-21 16:18:49 +02:00
|
|
|
#########################
|
|
|
|
## overwrite main.dart ##
|
|
|
|
#########################
|
|
|
|
cat > lib/main.dart <<EOF
|
|
|
|
import 'package:flutter/material.dart';
|
2020-05-22 15:13:11 +02:00
|
|
|
import 'screens/loading.dart';
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
runApp(MaterialApp(
|
2020-05-24 18:36:50 +02:00
|
|
|
debugShowCheckedModeBanner: false,
|
2020-05-22 15:13:11 +02:00
|
|
|
theme: ThemeData(
|
|
|
|
primarySwatch: Colors.blue,
|
|
|
|
),
|
|
|
|
home: Loading(),
|
|
|
|
));
|
|
|
|
}
|
2020-05-21 16:18:49 +02:00
|
|
|
|
2020-05-22 15:13:11 +02:00
|
|
|
EOF
|
2020-05-21 16:18:49 +02:00
|
|
|
|
2020-05-22 15:13:11 +02:00
|
|
|
####################################
|
|
|
|
## create loading and home screen ##
|
|
|
|
####################################
|
2020-05-21 16:18:49 +02:00
|
|
|
|
2020-05-22 15:13:11 +02:00
|
|
|
mkdir lib/screens
|
|
|
|
|
|
|
|
cat > lib/screens/home.dart <<EOF
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
|
|
class Home extends StatefulWidget {
|
|
|
|
Home({Key key}) : super(key: key);
|
|
|
|
static const title = '$appName';
|
2020-05-21 16:18:49 +02:00
|
|
|
|
2020-05-22 19:32:17 +02:00
|
|
|
static void loadInitial(BuildContext context) async {
|
|
|
|
await Future.delayed(Duration.zero, () {});
|
|
|
|
// load some stuff here and await results
|
|
|
|
Navigator.pushReplacement(context,
|
|
|
|
MaterialPageRoute(builder: (context) => Home()));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void save(BuildContext context) async {
|
|
|
|
showDialog(context: context, barrierDismissible: false,
|
|
|
|
builder: (BuildContext context) { return AlertDialog(content: Text("Saving...")); });
|
|
|
|
await Future.delayed(Duration.zero, () {});
|
|
|
|
Navigator.of(context, rootNavigator: true).pop();
|
|
|
|
}
|
|
|
|
|
2020-05-21 16:18:49 +02:00
|
|
|
@override
|
2020-05-22 15:13:11 +02:00
|
|
|
_HomeState createState() => _HomeState();
|
2020-05-21 16:18:49 +02:00
|
|
|
}
|
|
|
|
|
2020-05-22 15:13:11 +02:00
|
|
|
class _HomeState extends State<Home> {
|
2020-05-21 16:18:49 +02:00
|
|
|
int state = 1;
|
2020-05-22 15:13:11 +02:00
|
|
|
|
2020-05-21 16:18:49 +02:00
|
|
|
void _changeState(int s) {
|
|
|
|
setState(() {
|
|
|
|
state = s;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
List<String> popupMenuItems = ["About"];
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
|
|
|
appBar: AppBar(
|
2020-05-22 15:13:11 +02:00
|
|
|
title: Text(Home.title),
|
2020-05-21 16:18:49 +02:00
|
|
|
actions: <Widget>[
|
|
|
|
PopupMenuButton<String>(
|
|
|
|
onSelected: (String value) => handleClick(context, value),
|
|
|
|
itemBuilder: (BuildContext context) {
|
|
|
|
return popupMenuItems.map((String choice) {
|
|
|
|
return PopupMenuItem<String>(
|
|
|
|
value: choice,
|
|
|
|
child: Text(choice),
|
|
|
|
);
|
|
|
|
}).toList();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
body: Padding(
|
|
|
|
padding: const EdgeInsets.all(8.0),
|
|
|
|
child: ListView(children: [
|
|
|
|
Text("Lorem ipsum dolor sit amet"),
|
|
|
|
]),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleClick(BuildContext context, String value) {
|
|
|
|
switch (value) {
|
|
|
|
case 'About':
|
2020-05-22 15:13:11 +02:00
|
|
|
showLicensePage(context: context, applicationName: Home.title);
|
2020-05-21 16:18:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-22 15:13:11 +02:00
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
cat > lib/screens/loading.dart <<EOF
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import 'home.dart';
|
|
|
|
|
|
|
|
class Loading extends StatefulWidget {
|
|
|
|
@override
|
|
|
|
_LoadingState createState() => _LoadingState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _LoadingState extends State<Loading> {
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
2020-05-22 19:32:17 +02:00
|
|
|
Home.loadInitial(context);
|
2020-05-22 15:13:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
2020-05-23 08:56:25 +02:00
|
|
|
body: Container(
|
2020-05-22 15:13:11 +02:00
|
|
|
child: Text("Loading..."),
|
2020-05-23 08:56:25 +02:00
|
|
|
alignment: Alignment.center,
|
2020-05-22 15:13:11 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-21 16:18:49 +02:00
|
|
|
EOF
|
|
|
|
|
|
|
|
|
2020-05-19 23:30:00 +02:00
|
|
|
#####################
|
|
|
|
## create Makefile ##
|
|
|
|
#####################
|
|
|
|
|
|
|
|
cat > Makefile <<EOF
|
|
|
|
.PHONY: clean all launcherIcon
|
|
|
|
|
|
|
|
all: launcherIcon
|
|
|
|
flutter pub get
|
|
|
|
flutter build appbundle
|
|
|
|
|
|
|
|
clean:
|
|
|
|
flutter clean
|
|
|
|
|
|
|
|
launcherIcon:
|
|
|
|
flutter pub get
|
|
|
|
flutter pub run "flutter_launcher_icons:main"
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
################
|
|
|
|
## test build ##
|
|
|
|
################
|
|
|
|
|
|
|
|
make clean launcherIcon all
|
|
|
|
make clean
|