prepare android project build

This commit is contained in:
Artem Budarin 2018-08-01 13:31:24 +05:00
parent b726e55f94
commit fe73d7bec9
18 changed files with 580 additions and 225 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@ -2,149 +2,9 @@
#include "main_code.h"
//#include "boost/shared_ptr.h"
const float CONST_MAXRIX_WIDTH = 800.f;
const float CONST_MAXRIX_HEIGHT = 480.f;
boost::mutex RenderMutex;
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_Init(JNIEnv * env, jobject obj, jint width, jint height)
JNIEXPORT void JNICALL Java_com_fishrungames_crystalofrhylil_JniWrapper_Init(JNIEnv * env, jobject obj, jint width, jint height)
{
try
{
if (App->Inited)
{
App->OuterDeinit(); //Clean up what is left at previous launch (if applicable)
}
App->OuterInit(width, height, CONST_MAXRIX_WIDTH, CONST_MAXRIX_HEIGHT);
App->Inited = true;
}
catch (ErrorCommon e)
{
throw;
}
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_StopSounds(JNIEnv * env, jobject obj)
{
JniInitApp<TMyApplication>(width, height, width, height);
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_Update(JNIEnv * env, jobject obj, long dt)
{
RenderMutex.lock();
try
{
if (App->Inited)
{
App->OuterDraw();
App->OuterUpdate(dt);
}
}
catch (...)
{
throw;
}
RenderMutex.unlock();
}
JNIEXPORT int JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_IsInited(JNIEnv * env, jobject obj)
{
if (App->Inited)
{
return 1;
}
else
{
return 0;
}
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_Destroy(JNIEnv * env, jobject obj)
{
RenderMutex.lock();
try
{
if (App->Inited)
{
App->Inited = false;
App->OuterDeinit();
}
}
catch (ErrorCommon e)
{
throw;
}
RenderMutex.unlock();
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnTapDown(JNIEnv * env, jobject obj, float x, float y, long time)
{
try
{
App->OuterOnTapDown(vec2(x*CONST_MAXRIX_WIDTH/HalibutRender->GetScreenWidth(), y*CONST_MAXRIX_HEIGHT/HalibutRender->GetScreenHeight()));
}
catch (ErrorCommon e)
{
throw;
}
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnTapUp(JNIEnv * env, jobject obj, float x, float y, long time)
{
try
{
App->OuterOnTapUp(vec2(x*CONST_MAXRIX_WIDTH/HalibutRender->GetScreenWidth(), y*CONST_MAXRIX_HEIGHT/HalibutRender->GetScreenHeight()));
}
catch (ErrorCommon e)
{
throw;
}
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnTapMove(JNIEnv * env, jobject obj, float x, float y, long time)
{
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnFling(JNIEnv * env, jobject obj, jfloat velocityX, jfloat velocityY, long time)
{
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnScroll(JNIEnv * env, jobject obj, jfloat distanceX, jfloat distanceY, long time)
{
try
{
App->OuterOnMove(vec2(distanceX*CONST_MAXRIX_WIDTH/HalibutRender->GetScreenWidth(), distanceY*CONST_MAXRIX_HEIGHT/HalibutRender->GetScreenHeight()));
}
catch (ErrorCommon e)
{
throw;
}
}
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnKeyPress(JNIEnv * env, jobject obj, jint keyCode)
{
try
{
App->OnKeyPress(keyCode);
}
catch (ErrorCommon e)
{
throw;
}
}

View File

@ -12,19 +12,13 @@
#include "main_code.h"
#include "include/Engine.h"
extern "C" {
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_Init(JNIEnv * env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_StopSounds(JNIEnv * env, jobject obj);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_Update(JNIEnv * env, jobject obj, long dt);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_Destroy(JNIEnv * env, jobject obj);
JNIEXPORT int JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_IsInited(JNIEnv * env, jobject obj);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnTapDown(JNIEnv * env, jobject obj, jfloat x, jfloat y, long time);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnTapUp(JNIEnv * env, jobject obj, jfloat x, jfloat y, long time);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnTapMove(JNIEnv * env, jobject obj, jfloat x, jfloat y, long time);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnFling(JNIEnv * env, jobject obj, jfloat velocityX, jfloat velocityY, long time);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnScroll(JNIEnv * env, jobject obj, jfloat distanceX, jfloat distanceY, long time);
JNIEXPORT void JNICALL Java_fishrungames_crystalofrhylil_JniWrapper_OnKeyPress(JNIEnv * env, jobject obj, jint keyCode);
using namespace SE;
extern "C"
{
JNIEXPORT void JNICALL Java_com_fishrungames_crystalofrhylil_JniWrapper_Init(JNIEnv * env, jobject obj, jint width, jint height);
};

BIN
proj.android-studio/.idea/caches/build_file_checksums.ser Executable file → Normal file

Binary file not shown.

0
proj.android-studio/.idea/codeStyles/Project.xml Executable file → Normal file
View File

0
proj.android-studio/.idea/gradle.xml Executable file → Normal file
View File

2
proj.android-studio/.idea/misc.xml Executable file → Normal file
View File

@ -25,7 +25,7 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

0
proj.android-studio/.idea/runConfigurations.xml Executable file → Normal file
View File

View File

@ -1,26 +1,84 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.
add_definitions(-DTARGET_ANDROID)
set(JNI_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../jni)
set(BOOST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../boost_1_67_0)
set(BOOST_GIL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/boost-gil-extension)
set(ZIP_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/julienr-libzip-android/jni)
set(LIBPNG_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/libpng_1.4.1_android)
set(LIBJPEG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/jpeg-9")
set(EIGEN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../eigen)
set(SOL2_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../sol2)
set(LUA_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/lua-5.3.4/src)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../tes-engine)
include_directories(${JNI_PATH})
include_directories(${JNI_PATH}/match3)
include_directories(${BOOST_PATH})
include_directories(${EIGEN_PATH})
include_directories(${SOL2_PATH})
include_directories(${LUA_PATH})
include_directories(${LIBPNG_PATH})
include_directories(${LIBJPEG_PATH})
include_directories(${ZIP_PATH})
include_directories(${BOOST_GIL_PATH})
add_library( # Sets the name of the library.
native-lib
CrystalOfRhylil
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
# Associated headers in the same location as their source
# file are automatically included.
${JNI_PATH}/main_code.cpp
${JNI_PATH}/match3/match3field.cpp
${JNI_PATH}/android_api.cpp
)
add_library( engine
SHARED
IMPORTED )
set_target_properties( # Specifies the target library.
engine
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
${CMAKE_CURRENT_SOURCE_DIR}/../../../tes-engine/SalmonEngineAndroid/app/build/intermediates/cmake/debug/obj/${ANDROID_ABI}/libengine.so
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
@ -32,13 +90,21 @@ find_library( # Sets the name of the path variable.
# you want CMake to locate.
log )
find_library( # Sets the name of the path variable.
GLESv2-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
GLESv2 )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
CrystalOfRhylil
engine
# Links the target library to the log library
# included in the NDK.
${log-lib} )
${log-lib} ${GLESv2-lib} )

View File

@ -5,7 +5,7 @@ android {
buildToolsVersion "28.0.0"
defaultConfig {
applicationId "com.fishrungames.crystalofrhylil"
minSdkVersion 15
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
@ -13,11 +13,14 @@ android {
externalNativeBuild {
cmake {
abiFilters "armeabi-v7a", "x86"
abiFilters "armeabi-v7a"
arguments "-DANDROID_STL=c++_shared"
cppFlags "-std=c++17 -frtti -fexceptions -fsigned-char -Wno-c++11-narrowing"
cFlags "-DTARGET_ANDROID",
"-DTARGET_HALIBUT"
}
}
}

View File

@ -1,21 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fishrungames.crystalofrhylil">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
android:icon="@drawable/ic_menu_template" android:label="Crystal of Rhylil">
<activity android:name="MainActivity"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-feature android:glEsVersion="0x00020000"/>
</manifest>

View File

@ -0,0 +1,142 @@
package com.fishrungames.crystalofrhylil;
import java.util.Calendar;
import android.content.Context;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import fishrungames.salmonengineandroid.GLViewAncestor;
import fishrungames.salmonengineandroid.EngineWrapper;
class GLView extends GLViewAncestor
{
static long lastTimeStamp;
static boolean gameIsInited = false;
public GLView(Context context)
{
//Change this method? Don't forget to change method below!
super(context);
init(false, 0, 0);
}
public GLView(Context context, boolean translucent, int depth, int stencil)
{
//Change this method? Don't forget to change method above!
super(context);
init(translucent, depth, stencil);
}
public void init(boolean translucent, int depth, int stencil)
{
super.init(translucent, depth, stencil);
setRenderer(new Renderer());
Calendar c = Calendar.getInstance();
lastTimeStamp = c.getTimeInMillis();
gameIsInited = true;
}
private static class Renderer implements GLSurfaceView.Renderer
{
public void onDrawFrame(GL10 gl)
{
if (gameIsInited)
{
Calendar c = Calendar.getInstance();
long currentTimeStamp = c.getTimeInMillis();
EngineWrapper.Update(currentTimeStamp - lastTimeStamp);
lastTimeStamp = currentTimeStamp;
}
}
public void onSurfaceChanged(GL10 gl, int width, int height)
{
JniWrapper.Init(width,height);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
//Do nothing.
}
}
}
//package com.fishrungames.crystalofrhylil;
//
//
//import java.util.Calendar;
//
//import android.content.Context;
//import android.opengl.GLSurfaceView;
//
//import javax.microedition.khronos.egl.EGLConfig;
//import javax.microedition.khronos.opengles.GL10;
//
//import fishrungames.salmonengineandroid.GLViewAncestor;
//
//
//class GLView extends GLViewAncestor
//{
// static long lastTimeStamp;
// static boolean gameIsInited = false;
//
// public GLView(Context context)
// {
// //Change this method? Don't forget to change method below!
// super(context);
// init(false, 0, 0);
// }
//
// public GLView(Context context, boolean translucent, int depth, int stencil)
// {
// //Change this method? Don't forget to change method above!
// super(context);
// init(translucent, depth, stencil);
// }
//
// public void init(boolean translucent, int depth, int stencil)
// {
// super.init(translucent, depth, stencil);
// setRenderer(new Renderer());
// Calendar c = Calendar.getInstance();
// lastTimeStamp = c.getTimeInMillis();
// gameIsInited = true;
// }
//
// private static class Renderer implements GLSurfaceView.Renderer
// {
// public void onDrawFrame(GL10 gl)
// {
// if (gameIsInited)
// {
// Calendar c = Calendar.getInstance();
//
// long currentTimeStamp = c.getTimeInMillis();
//
// JniWrapper.Update(currentTimeStamp - lastTimeStamp);
//
// lastTimeStamp = currentTimeStamp;
// }
// }
//
// public void onSurfaceChanged(GL10 gl, int width, int height)
// {
//
//
// //JniWrapper.Destroy();
//
// JniWrapper.Init(width,height);
// }
//
// public void onSurfaceCreated(GL10 gl, EGLConfig config)
// {
// //Do nothing.
// }
// }
//}

View File

@ -0,0 +1,38 @@
package com.fishrungames.crystalofrhylil;
public class JniWrapper
{
static {
System.loadLibrary("CrystalOfRhylil");
}
public static native void Init(int width, int height);
}
//package com.fishrungames.crystalofrhylil;
//
//public class JniWrapper
//{
// static {
// //System.loadLibrary("gnustl_shared");
// //System.loadLibrary("HalibutEngine");
// System.loadLibrary("CrystalOfRhylilLib");
// }
//
//
// public static native void Init(int width, int height);
// public static native void Update(long dt);
// public static native void StopSounds();
// public static native void Destroy();
// public static native int IsInited();
// public static native void OnTapDown(float x, float y, long time);
// public static native void OnTapUp(float x, float y, long time);
// public static native void OnTapMove(float x, float y, long time);
//
// public static native void OnFling(float velocityX, float velocityY, long time);
// public static native void OnScroll(float distanceX, float distanceY, long time);
//
// public static native void OnKeyPress(int keyCode);
//}

View File

@ -1,26 +1,280 @@
package com.fishrungames.crystalofrhylil;
import fishrungames.salmonengineandroid.EngineWrapper;
//Deprecated
//import fishrungames.doublehitballs.R;
import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.widget.TextView;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
public class MainActivity extends Activity {
//Deprecated
//import java.lang.reflect.Field;
public class MainActivity extends Activity
{
GLView mView;
@Override
protected void onCreate(Bundle icicle)
{
super.onCreate(icicle);
EngineWrapper.LoadSalmonEngineLibrary();
EngineWrapper.SetActivityInstance(this);
EngineWrapper.SetupEnviroment();
String apkFilePath = null;
ApplicationInfo appInfo = null;
PackageManager packMgmr = this.getPackageManager();
try {
appInfo = packMgmr.getApplicationInfo("com.fishrungames.crystalofrhylil", 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Unable to locate assets, aborting...");
}
apkFilePath = appInfo.sourceDir;
EngineWrapper.SetupApkFilePath(apkFilePath);
mView = new GLView(getApplication());
setContentView(mView);
EngineWrapper.SetView(mView);
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
protected void onPause()
{
EngineWrapper.CallDestroy();
super.onPause();
mView.onPause();
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
@Override
protected void onResume()
{
super.onResume();
mView.onResume();
}
@Override
protected void onStop()
{
super.onStop();
}
public boolean onTouchEvent (MotionEvent event)
{
EngineWrapper.ProcessTouchEvent(event);
return true;
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
EngineWrapper.ProcessKeyDown(keyCode, event);
return super.onKeyDown(keyCode, event);
}
}
//package com.fishrungames.crystalofrhylil;
//
//
//
////Deprecated
////import fishrungames.crystalofrhylil.R;
//
//import android.app.Activity;
//import android.content.pm.ApplicationInfo;
//import android.content.pm.PackageManager;
//import android.content.pm.PackageManager.NameNotFoundException;
//import android.os.Bundle;
//
//import android.view.GestureDetector;
//import android.view.GestureDetector.SimpleOnGestureListener;
//import android.view.KeyEvent;
//import android.view.MotionEvent;
//
//import fishrungames.salmonengineandroid.EngineWrapper;
//
//
////Deprecated
////import java.lang.reflect.Field;
//
//
//public class MainActivity extends Activity
//{
//
// GLView mView;
//
// boolean IsScrolling = false;
//
// private GestureDetector gestureDetector;
//
// @Override
// protected void onCreate(Bundle icicle)
// {
// super.onCreate(icicle);
//
// gestureDetector = new GestureDetector(new MyGestureListener());
//
// EngineWrapper.LoadSalmonEngineLibrary();
// EngineWrapper.SetActivityInstance(this);
// EngineWrapper.SetupEnviroment();
///*
// * Deprecated
// *
// try
// {
// for (Field f : R.raw.class.getFields())
// {
// FileWrapper.AddToFileMap(f.getName(), f.getInt(null));
// }
//
//
// } catch (IllegalArgumentException e)
// {
// FileWrapper.ConsoleOut("IllegalArgumentException\n");
// onStop();
// } catch (IllegalAccessException e)
// {
// FileWrapper.ConsoleOut("IllegalAccessException\n");
// onStop();
// }
//*/
// mView = new GLView(getApplication());
//
// setContentView(mView);
//
// String apkFilePath = null;
// ApplicationInfo appInfo = null;
// PackageManager packMgmr = this.getPackageManager();
// try {
// appInfo = packMgmr.getApplicationInfo("com.fishrungames.crystalofrhylil", 0);
// } catch (NameNotFoundException e) {
//
// e.printStackTrace();
// throw new RuntimeException("Unable to locate assets, aborting...");
// }
// apkFilePath = appInfo.sourceDir;
//
// EngineWrapper.SetupApkFilePath(apkFilePath);
// //FileWrapper.ConsoleOut("Out of java\n");
//
// }
//
// @Override
// protected void onPause()
// {
// JniWrapper.Destroy();
// super.onPause();
// mView.onPause();
// }
//
// @Override
// protected void onResume()
// {
// //Don't write anything here!
// super.onResume();
// mView.onResume();
// }
//
// @Override
// protected void onStop()
// {
// //Don't write anything here!
// super.onStop();
// }
//
//
// public boolean onKeyDown(int keyCode, KeyEvent event)
// {
// int ascii_keycode = keyCode;
//
// if (keyCode == KeyEvent.KEYCODE_DEL)
// {
// ascii_keycode = 8; //Hack - getUnicodeChar does not recognize backspace
// }
// else
// {
// ascii_keycode = event.getUnicodeChar();
// }
//
// JniWrapper.OnKeyPress(ascii_keycode);
// return super.onKeyDown(keyCode, event);
// }
//
// public boolean onKeyUp(int keyCode, KeyEvent event)
// {
// return true;
// }
//
// public boolean onTouchEvent(MotionEvent event)
// {
// if (gestureDetector.onTouchEvent(event))
// {
// return true;
// }
//
// if (event.getAction() == MotionEvent.ACTION_UP)
// {
// float x = event.getX();
// float y = (float) mView.getHeight() - event.getY();
//
// if (IsScrolling)
// {
// IsScrolling = false;
// }
//
// JniWrapper.OnTapUp(x, y, event.getEventTime());
//
// }
// return true;
// }
//
// class MyGestureListener extends SimpleOnGestureListener
// {
//
// @Override
// public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
// float velocityY)
// {
// JniWrapper.OnFling(velocityX, velocityY, e2.getEventTime());
// return true;
// }
//
// public boolean onScroll(MotionEvent e1, MotionEvent e2,
// float distanceX, float distanceY)
// {
// JniWrapper.OnScroll(distanceX, distanceY, e2.getEventTime());
// IsScrolling = true;
// return true;
// }
//
// public boolean onDown(MotionEvent event)
// {
//
// float x = event.getX();
// float y = (float) mView.getHeight() - event.getY();
//
// JniWrapper.OnTapDown(x, y, event.getEventTime());
//
// return true;
// }
//
// }
//
//}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.android.tools.build:gradle:3.1.3'
// NOTE: Do not place your application dependencies here; they belong