open source
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>LayaBox</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
@@ -0,0 +1,42 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.layabox.conch6"
|
||||
android:versionCode="1"
|
||||
android:versionName="2.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="28" />
|
||||
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<application
|
||||
android:usesCleartextTraffic="true"
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
|
||||
android:label="@string/app_name">
|
||||
<activity
|
||||
android:name="demo.MainActivity"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:windowSoftInputMode="stateHidden|adjustPan"
|
||||
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
IsHandleUpdateAPK=0
|
||||
ApkUpdateUrl=https://www.layabox.com/layanative2.0/apk/update/conch-layaair/version.xml
|
||||
UpdateDownloadPath=mnt/sdcard
|
||||
UpdateAPKFileName=autoupdate.apk
|
||||
CheckNetwork=0
|
||||
ThreadMode=1
|
||||
JSDebugPort=5959
|
||||
JSDebugMode=0
|
||||
Binary file not shown.
@@ -0,0 +1,115 @@
|
||||
class loadingView
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
this.sOS = conchConfig.getOS();
|
||||
if (this.sOS == "Conch-ios")
|
||||
{
|
||||
this.bridge = PlatformClass.createClass("JSBridge");
|
||||
}
|
||||
else if (this.sOS == "Conch-android")
|
||||
{
|
||||
this.bridge = PlatformClass.createClass("demo.JSBridge");
|
||||
}
|
||||
}
|
||||
set loadingAutoClose(value)
|
||||
{
|
||||
this._loadingAutoClose = value;
|
||||
}
|
||||
get loadingAutoClose()
|
||||
{
|
||||
return this._loadingAutoClose;
|
||||
}
|
||||
set showTextInfo(value)
|
||||
{
|
||||
this._showTextInfo = value;
|
||||
if(this.bridge)
|
||||
{
|
||||
if (this.sOS == "Conch-ios")
|
||||
{
|
||||
this.bridge.call("showTextInfo:",value);
|
||||
}
|
||||
else if(this.sOS == "Conch-android")
|
||||
{
|
||||
this.bridge.call("showTextInfo",value);
|
||||
}
|
||||
}
|
||||
}
|
||||
get showTextInfo()
|
||||
{
|
||||
return this._showTextInfo;
|
||||
}
|
||||
bgColor(value)
|
||||
{
|
||||
if(this.bridge)
|
||||
{
|
||||
if (this.sOS == "Conch-ios")
|
||||
{
|
||||
this.bridge.call("bgColor:",value);
|
||||
}
|
||||
else if(this.sOS == "Conch-android")
|
||||
{
|
||||
this.bridge.call("bgColor",value);
|
||||
}
|
||||
}
|
||||
}
|
||||
setFontColor(value)
|
||||
{
|
||||
if(this.bridge)
|
||||
{
|
||||
if (this.sOS == "Conch-ios")
|
||||
{
|
||||
this.bridge.call("setFontColor:",value);
|
||||
}
|
||||
else if(this.sOS == "Conch-android")
|
||||
{
|
||||
this.bridge.call("setFontColor",value);
|
||||
}
|
||||
}
|
||||
}
|
||||
setTips(value)
|
||||
{
|
||||
if(this.bridge)
|
||||
{
|
||||
if (this.sOS == "Conch-ios")
|
||||
{
|
||||
this.bridge.call("setTips:",value);
|
||||
}
|
||||
else if(this.sOS == "Conch-android")
|
||||
{
|
||||
this.bridge.call("setTips",value);
|
||||
}
|
||||
}
|
||||
}
|
||||
loading(value)
|
||||
{
|
||||
if(this.bridge)
|
||||
{
|
||||
if (this.sOS == "Conch-ios")
|
||||
{
|
||||
this.bridge.call("loading:",value);
|
||||
}
|
||||
else if(this.sOS == "Conch-android")
|
||||
{
|
||||
this.bridge.call("loading",value);
|
||||
}
|
||||
}
|
||||
}
|
||||
hideLoadingView()
|
||||
{
|
||||
this.bridge.call("hideSplash");
|
||||
}
|
||||
}
|
||||
window.loadingView = new loadingView();
|
||||
if(window.loadingView)
|
||||
{
|
||||
window.loadingView.loadingAutoClose=true;//true代表当动画播放完毕,自动进入游戏。false为开发者手动控制
|
||||
window.loadingView.bgColor("#000000");//设置背景颜色
|
||||
window.loadingView.setFontColor("#ffffff");//设置字体颜色
|
||||
window.loadingView.setTips(["新世界的大门即将打开","敌军还有30秒抵达战场","妈妈说,心急吃不了热豆腐"]);//设置tips数组,会随机出现
|
||||
}
|
||||
window.onLayaInitError=function(e)
|
||||
{
|
||||
console.log("onLayaInitError error=" + e);
|
||||
alert("加载游戏失败,可能由于您的网络不稳定,请退出重进");
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"template": {
|
||||
"name": "LayaBox",
|
||||
"replace":[
|
||||
".project"
|
||||
],
|
||||
"rename":[
|
||||
],
|
||||
"display":"res/values/strings.xml"
|
||||
},
|
||||
"package": {
|
||||
"name": "com.layabox.conch6",
|
||||
"replace": [
|
||||
"AndroidManifest.xml",
|
||||
"src/demo/SplashDialog.java",
|
||||
"src/layaair/game/Market/GameEngine.java"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"src": "mPlugin.game_plugin_set_option\\s*\\(\\s*\"gameUrl\".*\\)\\s*;",
|
||||
"des":"mPlugin.game_plugin_set_option(\"gameUrl\", \"${url}\");",
|
||||
"replace": [
|
||||
"src/demo/MainActivity.java"
|
||||
]
|
||||
},
|
||||
"localize":{
|
||||
"src":"mPlugin.game_plugin_set_option\\(\"localize\".*",
|
||||
"des":"mPlugin.game_plugin_set_option(\"localize\",\"true\");",
|
||||
"replace":[
|
||||
"src/demo/MainActivity.java"
|
||||
]
|
||||
},
|
||||
"res": {
|
||||
"path": "assets/cache"
|
||||
},
|
||||
"platform":"android_eclipse",
|
||||
"version":"2.0.4"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@@ -0,0 +1,14 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-19
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_opengame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="104dp"
|
||||
android:layout_y="164dp"
|
||||
android:text="打开游戏" />
|
||||
|
||||
</AbsoluteLayout>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/logoView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxHeight="200dp"
|
||||
android:maxWidth="200dp"
|
||||
android:src="@drawable/layabox"
|
||||
tools:scaleType="fitCenter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tipsView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="68dp"
|
||||
android:text="" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 11+. This theme completely replaces
|
||||
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||
<!-- API 11 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,12 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme for API 14+. This theme completely replaces
|
||||
AppBaseTheme from BOTH res/values/styles.xml and
|
||||
res/values-v11/styles.xml on API 14+ devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
|
||||
<!-- API 14 theme customizations can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">LayaBox</string>
|
||||
<string name="on_back_pressed">再次点击后退键退出游戏!</string>
|
||||
<string name="alert_dialog_title">提示</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,25 @@
|
||||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
<style name="Splash" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowFrame">@null</item>
|
||||
<item name="android:windowIsTranslucent">false</item>
|
||||
<item name="android:backgroundDimEnabled">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,78 @@
|
||||
package demo;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
|
||||
public class JSBridge {
|
||||
public static Handler m_Handler = new Handler(Looper.getMainLooper());
|
||||
public static Activity mMainActivity = null;
|
||||
|
||||
public static void hideSplash() {
|
||||
m_Handler.post(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
MainActivity.mSplashDialog.dismissSplash();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setFontColor(final String color) {
|
||||
m_Handler.post(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
MainActivity.mSplashDialog.setFontColor(Color.parseColor(color));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setTips(final JSONArray tips) {
|
||||
m_Handler.post(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
String[] tipsArray = new String[tips.length()];
|
||||
for (int i = 0; i < tips.length(); i++) {
|
||||
tipsArray[i] = tips.getString(i);
|
||||
}
|
||||
MainActivity.mSplashDialog.setTips(tipsArray);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void bgColor(final String color) {
|
||||
m_Handler.post(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
MainActivity.mSplashDialog.setBackgroundColor(Color.parseColor(color));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void loading(final double percent) {
|
||||
m_Handler.post(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
MainActivity.mSplashDialog.setPercent((int)percent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void showTextInfo(final boolean show) {
|
||||
m_Handler.post(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
MainActivity.mSplashDialog.showTextInfo(show);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package demo;
|
||||
import java.io.InputStream;
|
||||
import layaair.autoupdateversion.AutoUpdateAPK;
|
||||
import layaair.game.IMarket.IPlugin;
|
||||
import layaair.game.IMarket.IPluginRuntimeProxy;
|
||||
import layaair.game.Market.GameEngine;
|
||||
import layaair.game.config.config;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
|
||||
public class MainActivity extends Activity{
|
||||
public static final int AR_CHECK_UPDATE = 1;
|
||||
private IPlugin mPlugin = null;
|
||||
private IPluginRuntimeProxy mProxy = null;
|
||||
boolean isLoad=false;
|
||||
boolean isExit=false;
|
||||
public static SplashDialog mSplashDialog;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
JSBridge.mMainActivity = this;
|
||||
mSplashDialog = new SplashDialog(this);
|
||||
mSplashDialog.showSplash();
|
||||
/*
|
||||
* 如果不想使用更新流程,可以屏蔽checkApkUpdate函数,直接打开initEngine函数
|
||||
*/
|
||||
checkApkUpdate(this);
|
||||
//initEngine();
|
||||
}
|
||||
public void initEngine()
|
||||
{
|
||||
mProxy = new RuntimeProxy(this);
|
||||
mPlugin = new GameEngine(this);
|
||||
mPlugin.game_plugin_set_runtime_proxy(mProxy);
|
||||
mPlugin.game_plugin_set_option("localize","false");
|
||||
mPlugin.game_plugin_set_option("gameUrl", "http://nativetest.layabox.com/layaplayer2.0.1/index.js");
|
||||
mPlugin.game_plugin_init(3);
|
||||
View gameView = mPlugin.game_plugin_get_view();
|
||||
this.setContentView(gameView);
|
||||
isLoad=true;
|
||||
}
|
||||
public boolean isOpenNetwork(Context context)
|
||||
{
|
||||
if (!config.GetInstance().m_bCheckNetwork)
|
||||
return true;
|
||||
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
return connManager.getActiveNetworkInfo() != null && (connManager.getActiveNetworkInfo().isAvailable() && connManager.getActiveNetworkInfo().isConnected());
|
||||
}
|
||||
public void settingNetwork(final Context context, final int p_nType)
|
||||
{
|
||||
AlertDialog.Builder pBuilder = new AlertDialog.Builder(context);
|
||||
pBuilder.setTitle("连接失败,请检查网络或与开发商联系").setMessage("是否对网络进行设置?");
|
||||
// 退出按钮
|
||||
pBuilder.setPositiveButton("是", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface p_pDialog, int arg1) {
|
||||
Intent intent;
|
||||
try {
|
||||
String sdkVersion = android.os.Build.VERSION.SDK;
|
||||
if (Integer.valueOf(sdkVersion) > 10) {
|
||||
intent = new Intent(
|
||||
android.provider.Settings.ACTION_WIRELESS_SETTINGS);
|
||||
} else {
|
||||
intent = new Intent();
|
||||
ComponentName comp = new ComponentName(
|
||||
"com.android.settings",
|
||||
"com.android.settings.WirelessSettings");
|
||||
intent.setComponent(comp);
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
}
|
||||
((Activity)context).startActivityForResult(intent, p_nType);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
pBuilder.setNegativeButton("否", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
((Activity)context).finish();
|
||||
}
|
||||
});
|
||||
AlertDialog alertdlg = pBuilder.create();
|
||||
alertdlg.setCanceledOnTouchOutside(false);
|
||||
alertdlg.show();
|
||||
}
|
||||
public void checkApkUpdate( Context context,final ValueCallback<Integer> callback)
|
||||
{
|
||||
if (isOpenNetwork(context)) {
|
||||
// 自动版本更新
|
||||
if ( "0".equals(config.GetInstance().getProperty("IsHandleUpdateAPK","0")) == false ) {
|
||||
Log.e("0", "==============Java流程 checkApkUpdate");
|
||||
new AutoUpdateAPK(context, new ValueCallback<Integer>() {
|
||||
@Override
|
||||
public void onReceiveValue(Integer integer) {
|
||||
Log.e("",">>>>>>>>>>>>>>>>>>");
|
||||
callback.onReceiveValue(integer);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.e("0", "==============Java流程 checkApkUpdate 不许要自己管理update");
|
||||
callback.onReceiveValue(1);
|
||||
}
|
||||
} else {
|
||||
settingNetwork(context,AR_CHECK_UPDATE);
|
||||
}
|
||||
}
|
||||
public void checkApkUpdate(Context context) {
|
||||
InputStream inputStream = getClass().getResourceAsStream("/assets/config.ini");
|
||||
config.GetInstance().init(inputStream);
|
||||
checkApkUpdate(context,new ValueCallback<Integer>() {
|
||||
@Override
|
||||
public void onReceiveValue(Integer integer) {
|
||||
if (integer.intValue() == 1) {
|
||||
initEngine();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public void onActivityResult(int requestCode, int resultCode,Intent intent) {
|
||||
if (requestCode == AR_CHECK_UPDATE) {
|
||||
checkApkUpdate(this);
|
||||
}
|
||||
}
|
||||
protected void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if(isLoad)mPlugin.game_plugin_onPause();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
if(isLoad)mPlugin.game_plugin_onResume();
|
||||
|
||||
}
|
||||
|
||||
protected void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
if(isLoad)mPlugin.game_plugin_onDestory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package demo;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.webkit.ValueCallback;
|
||||
import layaair.game.IMarket.IPluginRuntimeProxy;
|
||||
|
||||
public class RuntimeProxy implements IPluginRuntimeProxy {
|
||||
|
||||
private String TAG = "RuntimeProxy";
|
||||
private Activity mActivity = null;
|
||||
public RuntimeProxy(Activity mainActivity) {
|
||||
mActivity = mainActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean laya_set_value(String key, Object value) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
public String getCacheDir()
|
||||
{
|
||||
String sCache = mActivity.getCacheDir().toString();
|
||||
String []vString = sCache.split("/");
|
||||
String sNewCache="";
|
||||
for( int i = 0; i < vString.length-1; i++ )
|
||||
{
|
||||
sNewCache += vString[i];
|
||||
sNewCache += "/";
|
||||
}
|
||||
return sNewCache;
|
||||
}
|
||||
public String getExpansionMainPath()
|
||||
{
|
||||
//TODO CP自行定制
|
||||
return "";
|
||||
}
|
||||
public String getExpansionPatchPath()
|
||||
{
|
||||
//TODO CP自行定制
|
||||
return "";
|
||||
}
|
||||
@Override
|
||||
public Object laya_get_value(String key) {
|
||||
Log.d(TAG, "laya_get_value key=" + key);
|
||||
String str = null;
|
||||
if (key.equalsIgnoreCase("CacheDir")) {
|
||||
return getCacheDir();
|
||||
}
|
||||
else if(key.equalsIgnoreCase("ExpansionMainPath")) {
|
||||
return getExpansionMainPath();
|
||||
}
|
||||
else if(key.equalsIgnoreCase("ExpansionPatchPath")) {
|
||||
return getExpansionPatchPath();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laya_stop_game_engine() {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Login laya_stop_game_engine.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object laya_invoke_Method(String method, Bundle param) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Login(JSONObject jsonObj, ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Login info = "+jsonObj.toString());
|
||||
try {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("status", 0);
|
||||
result.put("unionUserID", "1123fff4");
|
||||
result.put("nickName", "中南海");
|
||||
result.put("photo", "http://www.xxx.com/xxx.jpg");
|
||||
result.put("sptoken", "33ffffh54444dddd");
|
||||
result.put("msg", "success");
|
||||
callback.onReceiveValue(result);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Logout(JSONObject jsonObj, ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Logout info = "+jsonObj.toString());
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("status", 0);
|
||||
result.put("msg", "success");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onReceiveValue(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Pay(JSONObject jsonObj, ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Logout Pay = "+jsonObj.toString());
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("status", 0);
|
||||
result.put("msg", "success");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onReceiveValue(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void PushIcon(JSONObject jsonObj, ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Logout PushIcon = "+jsonObj.toString());
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("status", 0);
|
||||
result.put("msg", "success");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onReceiveValue(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Share(JSONObject jsonObj, ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Logout Share = "+jsonObj.toString());
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("status", 0);
|
||||
result.put("msg", "success");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onReceiveValue(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OpenBBS(JSONObject jsonObj, ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Logout OpenBBS = "+jsonObj.toString());
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("status", 0);
|
||||
result.put("msg", "success");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onReceiveValue(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void GetFriendsList(JSONObject jsonObj,
|
||||
ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Logout GetFriendsList = "+jsonObj.toString());
|
||||
JSONObject result = new JSONObject();
|
||||
JSONArray array = new JSONArray();
|
||||
try {
|
||||
|
||||
JSONObject p1 = new JSONObject();
|
||||
p1.put("userId", "1111111");
|
||||
p1.put("nickName", "xiaoming");
|
||||
p1.put("photo", "http://xxx.com/xxx.jpg");
|
||||
p1.put("sex", "0");
|
||||
|
||||
JSONObject p2 = new JSONObject();
|
||||
p2.put("userId", "1111111");
|
||||
p2.put("nickName", "xiaoming");
|
||||
p2.put("photo", "http://xxx.com/xxx.jpg");
|
||||
p2.put("sex", "0");
|
||||
array.put(p1);
|
||||
array.put(p2);
|
||||
|
||||
result.put("status", 0);
|
||||
result.put("msg", "success");
|
||||
result.put("friends", array);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onReceiveValue(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void SendMessageToPlatform(JSONObject jsonObj,
|
||||
ValueCallback<JSONObject> callback) {
|
||||
// TODO Auto-generated method stub
|
||||
Log.d(TAG, "Logout SendMessageToPlatform = "+jsonObj.toString());
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
result.put("status", 0);
|
||||
result.put("msg", "success");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onReceiveValue(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package demo;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import com.layabox.conch6.R;
|
||||
|
||||
|
||||
public class SplashDialog extends Dialog {
|
||||
private Context mContext;
|
||||
private long mStartTime;
|
||||
private long mleastShowTime = 2;
|
||||
private TextView mTipsView;
|
||||
private String[] mTips = {};
|
||||
private int mFontColor;
|
||||
private int mIndex = 0;
|
||||
private int mPercent = 0;
|
||||
private View mLayout;
|
||||
Handler mSplashHandler = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
super.handleMessage(message);
|
||||
switch(message.what) {
|
||||
case 0:
|
||||
int length = mTips.length;
|
||||
mSplashHandler.removeMessages(0);
|
||||
if (length > 0) {
|
||||
if (mIndex >= length) {
|
||||
mIndex = 0;
|
||||
}
|
||||
mTipsView.setText(mTips[mIndex] + "(" + mPercent + "%)");
|
||||
mIndex++;
|
||||
}
|
||||
mSplashHandler.sendEmptyMessageDelayed(0, 1000);
|
||||
break;
|
||||
case 1:
|
||||
mSplashHandler.removeMessages(0);
|
||||
mSplashHandler.removeMessages(1);
|
||||
SplashDialog.this.dismiss();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public SplashDialog(Context context) {
|
||||
super(context, R.style.Splash);
|
||||
mContext = context;
|
||||
}
|
||||
public void setTips(String[] tips) {
|
||||
mTips = tips;
|
||||
}
|
||||
public void setPercent(int percent) {
|
||||
mPercent = percent;
|
||||
if (mPercent > 100) {
|
||||
mPercent = 100;
|
||||
}
|
||||
if (mPercent < 0) {
|
||||
mPercent = 0;
|
||||
}
|
||||
int length = mTips.length;
|
||||
if (length > 0) {
|
||||
if (mIndex >= mTips.length) {
|
||||
mIndex = 0;
|
||||
}
|
||||
mTipsView.setText(mTips[mIndex] + "(" + mPercent + "%)");
|
||||
}
|
||||
if (mPercent == 100) {
|
||||
dismissSplash();
|
||||
}
|
||||
}
|
||||
public void setFontColor(int color) {
|
||||
mTipsView.setTextColor(color);
|
||||
}
|
||||
public void setBackgroundColor(int color) {
|
||||
mLayout.setBackgroundColor(color);
|
||||
}
|
||||
public void showTextInfo(boolean show) {
|
||||
if (show) {
|
||||
mTipsView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else {
|
||||
mTipsView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
public void showSplash() {
|
||||
this.show();
|
||||
mStartTime = System.currentTimeMillis();
|
||||
mSplashHandler.sendEmptyMessage(0);
|
||||
}
|
||||
public void dismissSplash() {
|
||||
long showTime = System.currentTimeMillis() - mStartTime;
|
||||
if (showTime >= mleastShowTime * 1000) {
|
||||
mSplashHandler.sendEmptyMessage(1);
|
||||
}
|
||||
else {
|
||||
mSplashHandler.sendEmptyMessageDelayed(1, (long) (this.mleastShowTime * 1000 - showTime));
|
||||
}
|
||||
}
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.splash_dialog);
|
||||
mTipsView = (TextView)findViewById(R.id.tipsView);
|
||||
mLayout = findViewById(R.id.layout);
|
||||
}
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK){
|
||||
return true;
|
||||
}else {
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
package layaair.autoupdateversion;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.webkit.ValueCallback;
|
||||
import layaair.autoupdateversion.data.VersionData;
|
||||
import layaair.game.config.config;
|
||||
|
||||
public class AutoUpdateAPK {
|
||||
//static public final String CHECK_VERSION_URL = "http://localhost:80/setuptest_update.xml";
|
||||
//static public final String APK_DOWNLOAD_PATH = "mnt/sdcard/";
|
||||
//static public final String DOWNLOAD_APK_NAME = "autoupdate.apk";
|
||||
|
||||
static private final int UPDATE_CHECKCOMPLETED = 1;
|
||||
static private final int UPDATE_DOWNLOADING = 2;
|
||||
static private final int UPDATE_DOWNLOAD_ERROR = 3;
|
||||
static private final int UPDATE_DOWNLOAD_COMPLETED = 4;
|
||||
static private final int UPDATE_DOWNLOAD_CANCELED = 5;
|
||||
|
||||
static private AutoUpdateAPK s_instance;
|
||||
|
||||
private layaair.autoupdateversion.IUpdateCallback m_callback;
|
||||
private String m_szDownloadAPKName;// = DOWNLOAD_APK_NAME;
|
||||
private String m_szDownloadPath;
|
||||
private int m_iVersionCode = 0;
|
||||
private int m_iProgressValue = 0;
|
||||
private Context m_context = null;
|
||||
private VersionData m_versionData = new VersionData();
|
||||
private boolean m_hasNewVersion = false;
|
||||
private boolean m_hasCanceled = false;
|
||||
private ValueCallback<Integer> m_pCallback;
|
||||
|
||||
public AutoUpdateAPK(Context p_context,ValueCallback<Integer> callback)
|
||||
{
|
||||
m_pCallback=callback;
|
||||
s_instance = this;
|
||||
m_callback = new UpdateCallback();
|
||||
m_context = p_context;
|
||||
this.m_szDownloadAPKName = config.GetInstance().getProperty("UpdateAPKFileName");
|
||||
this.m_szDownloadPath = config.GetInstance().getProperty("UpdateDownloadPath");
|
||||
setVersionCode(p_context);
|
||||
downloadVersionXML(config.GetInstance().getProperty("ApkUpdateUrl"));
|
||||
}
|
||||
public static void DelInstance()
|
||||
{
|
||||
s_instance=null;
|
||||
}
|
||||
|
||||
static public AutoUpdateAPK getInstance() {
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
public void cancelDownload() {
|
||||
m_hasCanceled = true;
|
||||
}
|
||||
|
||||
private static class UpdateHandle extends Handler
|
||||
{
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
AutoUpdateAPK that=AutoUpdateAPK.getInstance();
|
||||
switch (msg.what) {
|
||||
case UPDATE_CHECKCOMPLETED:
|
||||
that.m_callback.checkUpdateCompleted(that.getHasNewVersion(),
|
||||
that.m_versionData.getName() +that.m_versionData.getVersion());
|
||||
break;
|
||||
case UPDATE_DOWNLOADING:
|
||||
that.m_callback.downloadProgressChanged(that.m_iProgressValue);
|
||||
break;
|
||||
case UPDATE_DOWNLOAD_ERROR:
|
||||
onUpdateEnd(1);
|
||||
that.m_callback.downloadCompleted(false, msg.obj.toString());
|
||||
break;
|
||||
case UPDATE_DOWNLOAD_COMPLETED:
|
||||
onUpdateEnd(0);
|
||||
that.m_callback.downloadCompleted(true, "");
|
||||
break;
|
||||
case UPDATE_DOWNLOAD_CANCELED:
|
||||
that.m_callback.downloadCanceled();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void onUpdateEnd(int ecode)
|
||||
{
|
||||
if (ecode == 2 || ecode == 3) {
|
||||
s_instance.m_pCallback.onReceiveValue(1);
|
||||
} else {
|
||||
s_instance.m_pCallback.onReceiveValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
Handler updateHandler = new UpdateHandle();
|
||||
|
||||
public void updateAPK() {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
|
||||
intent.setDataAndType(
|
||||
Uri.fromFile(new File(m_szDownloadPath, m_szDownloadAPKName)),
|
||||
"application/vnd.android.package-archive");
|
||||
m_context.startActivity(intent);
|
||||
}
|
||||
|
||||
public void downloadAPK() {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
URL url = new URL(m_versionData.getDownloasURL());
|
||||
Log.i("","update apk url:"+url.toString());
|
||||
HttpURLConnection conn = (HttpURLConnection) url
|
||||
.openConnection();
|
||||
conn .setRequestProperty("Accept-Encoding", "identity");
|
||||
conn.setConnectTimeout(6 * 1000);
|
||||
conn.connect();
|
||||
// if (conn.getResponseCode() != 200)
|
||||
// throw new RuntimeException("请求url失败");
|
||||
|
||||
int length = conn.getContentLength();
|
||||
InputStream is = conn.getInputStream();
|
||||
|
||||
File fileAPK = new File(m_szDownloadPath,
|
||||
m_szDownloadAPKName);
|
||||
|
||||
if (fileAPK.exists()) {
|
||||
if(fileAPK.delete())
|
||||
{
|
||||
Log.i("","删除apk成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e("","删除apk失败");
|
||||
}
|
||||
}
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(fileAPK);
|
||||
|
||||
int count = 0;
|
||||
byte buf[] = new byte[512];
|
||||
|
||||
int nLastProg=0;
|
||||
do {
|
||||
|
||||
int numread = is.read(buf);
|
||||
count += numread;
|
||||
m_iProgressValue = (int) (((float) count / length) * 100);
|
||||
if(m_iProgressValue!=nLastProg)
|
||||
{
|
||||
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOADING));
|
||||
nLastProg = m_iProgressValue;
|
||||
}
|
||||
if (numread <= 0) {
|
||||
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_COMPLETED);
|
||||
break;
|
||||
}
|
||||
fos.write(buf, 0, numread);
|
||||
} while (!m_hasCanceled);
|
||||
if (m_hasCanceled) {
|
||||
updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_CANCELED);
|
||||
}
|
||||
fos.close();
|
||||
is.close();
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR, e.getMessage()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR, e.getMessage()));
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public void setVersionCode(Context p_context) {
|
||||
try {
|
||||
m_iVersionCode = p_context.getPackageManager().getPackageInfo(
|
||||
p_context.getPackageName(), 0).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadVersionXML(final String p_szURL) {
|
||||
this.setHasNewVersion(false);
|
||||
new Thread() {
|
||||
// ***************************************************************
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Random rnd;
|
||||
rnd = new Random();
|
||||
String url=p_szURL+"?r="+rnd.nextInt();
|
||||
Log.i("","update url="+url);
|
||||
String verjson = NetHelper
|
||||
.httpStringGet(url);
|
||||
parseVersionXMLFromString(verjson);
|
||||
if (m_versionData.getVersionCode() > m_iVersionCode) {
|
||||
setHasNewVersion(true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("","自动更新失败,应该是无法连接到"+p_szURL);
|
||||
}
|
||||
updateHandler.sendEmptyMessage(UPDATE_CHECKCOMPLETED);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public boolean parseVersionXMLFromString(String p_szContent) {
|
||||
DocumentBuilder db = null;
|
||||
Document document = null;
|
||||
try {
|
||||
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
InputStream in = new ByteArrayInputStream(p_szContent.getBytes());
|
||||
assert db != null;
|
||||
document = db.parse(in);
|
||||
} catch (SAXException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Element root = null;
|
||||
if (document != null) {
|
||||
root = document.getDocumentElement();
|
||||
}
|
||||
// System.out.println("根节点名称:"+root.getTagName()); //根节点名称
|
||||
return doParseVersionXML(root);
|
||||
}
|
||||
|
||||
@SuppressLint({ "NewApi", "NewApi", "NewApi", "NewApi", "NewApi" })
|
||||
private boolean doParseVersionXML(Element p_root) {
|
||||
if(p_root==null)return false;
|
||||
NodeList __ls = p_root.getChildNodes();
|
||||
Node node;
|
||||
for (int i = 0; i < __ls.getLength(); i++) {
|
||||
node = __ls.item(i);
|
||||
if (node.getNodeName().toLowerCase(Locale.ENGLISH).equals("versioncode")) {
|
||||
m_versionData.setVersionCode(Integer.parseInt(node
|
||||
.getTextContent()));
|
||||
continue;
|
||||
}
|
||||
if (node.getNodeName().toLowerCase(Locale.ENGLISH).equals("version")) {
|
||||
m_versionData.setVersion(node.getTextContent());
|
||||
continue;
|
||||
}
|
||||
if (node.getNodeName().toLowerCase(Locale.ENGLISH).equals("name")) {
|
||||
m_versionData.setName(node.getTextContent());
|
||||
continue;
|
||||
}
|
||||
if (node.getNodeName().toLowerCase(Locale.ENGLISH).equals("url")) {
|
||||
m_versionData.setDownloasURL(node.getTextContent());
|
||||
}
|
||||
}
|
||||
//给apk地址加个参数,防止服务器的缓存
|
||||
m_versionData.setDownloasURL(m_versionData.getDownloasURL()+"?vc="+m_versionData.getVersionCode());
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getHasNewVersion() {
|
||||
return m_hasNewVersion;
|
||||
}
|
||||
|
||||
public void setHasNewVersion(boolean m_hasNewVersion) {
|
||||
this.m_hasNewVersion = m_hasNewVersion;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return this.m_context;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package layaair.autoupdateversion;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
|
||||
public class DialogHelper {
|
||||
|
||||
public static void Confirm(Context ctx, CharSequence title, CharSequence message,
|
||||
CharSequence okText, OnClickListener oklistener, CharSequence cancelText,
|
||||
OnClickListener cancellistener) {
|
||||
AlertDialog.Builder builder = createDialog(ctx, title, message);
|
||||
builder.setPositiveButton(okText, oklistener);
|
||||
builder.setNegativeButton(cancelText, cancellistener);
|
||||
AlertDialog dlg = builder.create();
|
||||
dlg.setCanceledOnTouchOutside(false); //防止点到外面自动关掉对话框。
|
||||
dlg.show();
|
||||
}
|
||||
|
||||
private static AlertDialog.Builder createDialog(Context ctx, CharSequence title,
|
||||
CharSequence message) {
|
||||
AlertDialog.Builder builder = new Builder(ctx);
|
||||
builder.setMessage(message);
|
||||
if(title!=null)
|
||||
{
|
||||
builder.setTitle(title);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static AlertDialog.Builder createDialog(Context ctx,int titleId, int messageId) {
|
||||
AlertDialog.Builder builder = new Builder(ctx);
|
||||
builder.setMessage(messageId);
|
||||
builder.setTitle(titleId);
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package layaair.autoupdateversion;
|
||||
|
||||
public interface IUpdateCallback {
|
||||
void checkUpdateCompleted(Boolean hasUpdate,
|
||||
CharSequence updateInfo);
|
||||
|
||||
void downloadProgressChanged(int progress);
|
||||
void downloadCanceled();
|
||||
void downloadCompleted(Boolean sucess, CharSequence errorMsg);
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package layaair.autoupdateversion;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
|
||||
public class NetHelper {
|
||||
|
||||
public static String httpStringGet(String url) throws Exception {
|
||||
return httpStringGet(url, "utf-8");
|
||||
}
|
||||
|
||||
public static String httpStringGet(String url, String enc) throws Exception {
|
||||
HttpURLConnection connection = null;
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
URL u = new URL( url );
|
||||
connection = (HttpURLConnection) u.openConnection();
|
||||
connection.setRequestMethod( "GET" );
|
||||
connection.setConnectTimeout( 5000 );
|
||||
connection.setReadTimeout( 5000 );
|
||||
InputStream in = connection.getInputStream();
|
||||
reader = new BufferedReader( new InputStreamReader( in ) );
|
||||
StringBuilder result = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
result.append( line );
|
||||
}
|
||||
return String.valueOf( result );
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ProtocolException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package layaair.autoupdateversion;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.util.Log;
|
||||
|
||||
public class UpdateCallback implements IUpdateCallback {
|
||||
|
||||
static private final String DIALOG_DOWNLOAD_ERROR_TITLE = "下载失败";
|
||||
static private final String DIALOG_DOWNLOAD_ERROR_MSG = "下载更新文件失败";
|
||||
static private final String DIALOG_DOWNLOAD_BUTTON_TRY = "重试";
|
||||
static private final String DIALOG_DOWNLOAD_BUTTON_CANCEL= "取消";
|
||||
|
||||
static private final String DIALOG_UPDATE_TITLE = "更新";
|
||||
static private final String DIALOG_UPDATE_MSG = "立刻更新[";
|
||||
static private final String DIALOG_UPDATE_MSGEND = "]吗?";
|
||||
static private final String DIALOG_UPDATE_PROGRESS= "更新进度";
|
||||
static private final String DIALOG_UPDATE_BUTTON_TRY = "开始更新";
|
||||
static private final String DIALOG_UPDATE_BUTTON_CANCEL= "取消更新";
|
||||
|
||||
ProgressDialog updateProgressDialog = null;
|
||||
public void downloadProgressChanged(int progress) {
|
||||
if (updateProgressDialog != null
|
||||
&& updateProgressDialog.isShowing()) {
|
||||
updateProgressDialog.setProgress(progress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void downloadCompleted(Boolean sucess, CharSequence errorMsg) {
|
||||
if (updateProgressDialog != null
|
||||
&& updateProgressDialog.isShowing()) {
|
||||
updateProgressDialog.dismiss();
|
||||
}
|
||||
if (sucess) {
|
||||
if (AutoUpdateAPK.getInstance() != null)
|
||||
AutoUpdateAPK.getInstance().updateAPK();
|
||||
} else {
|
||||
if (AutoUpdateAPK.getInstance() == null)
|
||||
return ;
|
||||
DialogHelper.Confirm(AutoUpdateAPK.getInstance().getContext(),
|
||||
DIALOG_DOWNLOAD_ERROR_TITLE,
|
||||
DIALOG_DOWNLOAD_ERROR_MSG,
|
||||
DIALOG_DOWNLOAD_BUTTON_TRY,
|
||||
new DialogInterface.OnClickListener() {
|
||||
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
AutoUpdateAPK.getInstance().downloadAPK();
|
||||
|
||||
}
|
||||
}, DIALOG_DOWNLOAD_BUTTON_CANCEL, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadCanceled() {
|
||||
Log.i("", "download canceled");
|
||||
}
|
||||
|
||||
public void checkUpdateCompleted(Boolean hasUpdate, CharSequence updateInfo) {
|
||||
if (AutoUpdateAPK.getInstance() == null)
|
||||
return ;
|
||||
if (hasUpdate)
|
||||
{
|
||||
DialogHelper.Confirm(
|
||||
AutoUpdateAPK.getInstance().getContext(),
|
||||
DIALOG_UPDATE_TITLE,
|
||||
DIALOG_UPDATE_MSG + updateInfo+ DIALOG_UPDATE_MSGEND,DIALOG_UPDATE_BUTTON_TRY,
|
||||
new DialogInterface.OnClickListener() {
|
||||
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
updateProgressDialog = new ProgressDialog(AutoUpdateAPK.getInstance().getContext());
|
||||
updateProgressDialog.setMessage(DIALOG_UPDATE_PROGRESS);
|
||||
updateProgressDialog.setIndeterminate(false);
|
||||
updateProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
updateProgressDialog.setMax(100);
|
||||
updateProgressDialog.setProgress(0);
|
||||
updateProgressDialog.setCancelable(false);
|
||||
updateProgressDialog.setCanceledOnTouchOutside(false);
|
||||
updateProgressDialog.show();
|
||||
|
||||
AutoUpdateAPK.getInstance().downloadAPK();
|
||||
}
|
||||
}, DIALOG_UPDATE_BUTTON_CANCEL,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
AutoUpdateAPK.onUpdateEnd(3);
|
||||
}
|
||||
}
|
||||
);
|
||||
}else{
|
||||
AutoUpdateAPK.onUpdateEnd(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package layaair.autoupdateversion.data;
|
||||
|
||||
public class VersionData {
|
||||
private int m_iVersionCode;
|
||||
private String m_szName;
|
||||
private String m_szVersion;
|
||||
private String m_szDownloasURL;
|
||||
|
||||
public int getVersionCode() {
|
||||
return m_iVersionCode;
|
||||
}
|
||||
|
||||
public void setVersionCode(int p_iVersionCode) {
|
||||
this.m_iVersionCode = p_iVersionCode;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return m_szName;
|
||||
}
|
||||
|
||||
public void setName(String p_szName) {
|
||||
this.m_szName = p_szName;
|
||||
}
|
||||
|
||||
public String getDownloasURL() {
|
||||
return m_szDownloasURL;
|
||||
}
|
||||
|
||||
public void setDownloasURL(String p_szDownloasURL) {
|
||||
this.m_szDownloasURL = p_szDownloasURL;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return m_szVersion;
|
||||
}
|
||||
|
||||
public void setVersion(String m_szVersion) {
|
||||
this.m_szVersion = m_szVersion;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package layaair.game.IMarket;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
public abstract interface IPlugin {
|
||||
// 获取游戏引擎端的变量
|
||||
public abstract Object game_plugin_get_value(String key);
|
||||
// 获取要显示的view
|
||||
public abstract View game_plugin_get_view();
|
||||
// 游戏引擎初始化
|
||||
public abstract void game_plugin_init(int nDownloadThreadNum);
|
||||
// 拦截keycode
|
||||
public abstract boolean game_plugin_intercept_key(int keycode);
|
||||
// 调用游戏引擎的方法
|
||||
public abstract Object game_plugin_invoke_method(String method, Bundle param);
|
||||
// 进入后台时调用
|
||||
public abstract void game_plugin_onPause();
|
||||
// 恢复前台时调用
|
||||
public abstract void game_plugin_onResume();
|
||||
// 退出游戏时调用
|
||||
public abstract void game_plugin_onStop();
|
||||
// 退出游戏时 销毁
|
||||
public abstract void game_plugin_onDestory();
|
||||
// 向游戏引擎传递参数
|
||||
public abstract void game_plugin_set_option(String key, String value);
|
||||
// 设置代理对象
|
||||
public abstract void game_plugin_set_runtime_proxy(IPluginRuntimeProxy paramIGameEngineRuntimeProxy);
|
||||
// 游戏页面发生改变时触发(分辨率,横竖屏...)
|
||||
public abstract void game_plugin_configonChanged(Configuration newConfig);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package layaair.game.IMarket;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
public abstract interface IPluginRuntimeProxy {
|
||||
//设置插件管理器key对应的值
|
||||
public abstract boolean laya_set_value(String key, Object value);
|
||||
//获取插件管理器key对应的值
|
||||
public abstract Object laya_get_value(String key);
|
||||
//游戏引擎请求终止游戏
|
||||
public abstract void laya_stop_game_engine();
|
||||
//调用方法
|
||||
public abstract Object laya_invoke_Method(String method, Bundle param);
|
||||
//登录
|
||||
public abstract void Login(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
//注销登录
|
||||
public abstract void Logout(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
//支付
|
||||
public abstract void Pay(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
//发送桌面快捷方式
|
||||
public abstract void PushIcon(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
//分享
|
||||
public abstract void Share(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
//打开BBS
|
||||
public abstract void OpenBBS(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
//获取好友列表
|
||||
public abstract void GetFriendsList(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
//给host发送消息
|
||||
public abstract void SendMessageToPlatform(JSONObject jsonObj, ValueCallback<JSONObject> callback);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package layaair.game.Market;
|
||||
|
||||
import layaair.game.IMarket.IPlugin;
|
||||
import layaair.game.IMarket.IPluginRuntimeProxy;
|
||||
import layaair.game.conch.ILayaEventListener;
|
||||
import layaair.game.conch.ILayaGameEgine;
|
||||
import layaair.game.conch.LayaConch5;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import com.layabox.conch6.R;
|
||||
|
||||
public class GameEngine implements IPlugin {
|
||||
private static final String TAG = "LayaGameEngine";
|
||||
public ILayaGameEgine mLayaGameEngine = null;
|
||||
private String mGameUrl = "";
|
||||
private Context mContext = null;
|
||||
private IPluginRuntimeProxy mGameEngineProxy = null;
|
||||
public static GameEngine _instance = null;
|
||||
|
||||
public GameEngine(Context _ctx){
|
||||
mContext = _ctx;
|
||||
mLayaGameEngine = new LayaConch5(_ctx);
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
public static GameEngine getInstance(){
|
||||
return _instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object game_plugin_get_value(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View game_plugin_get_view() {
|
||||
Log.e(TAG,"game_plugin_get_view");
|
||||
return mLayaGameEngine.getAbsLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void game_plugin_init(int nDownloadThreadNum) {
|
||||
Log.d(TAG,"game_plugin_init url ="+mGameUrl);
|
||||
if( mGameUrl == null || mGameUrl.length() <2 ){
|
||||
Log.e("","引擎初始化失败,没有游戏地址 gameUrl = "+mGameUrl);
|
||||
return;
|
||||
}
|
||||
String gameUrl = mGameUrl;
|
||||
mLayaGameEngine.setIsPlugin(false);
|
||||
mLayaGameEngine.setGameUrl(gameUrl);
|
||||
Log.d(TAG,"url="+gameUrl);
|
||||
String _path = (String) mGameEngineProxy.laya_get_value("CacheDirInSdcard");
|
||||
if(_path==null)
|
||||
_path = (String) mGameEngineProxy.laya_get_value("CacheDir");
|
||||
mLayaGameEngine.setAlertTitle(mContext.getString( R.string.alert_dialog_title ));
|
||||
mLayaGameEngine.setStringOnBackPressed(mContext.getString( R.string.on_back_pressed ));
|
||||
mLayaGameEngine.setDownloadThreadNum(nDownloadThreadNum);
|
||||
mLayaGameEngine.setAppCacheDir(_path);
|
||||
mLayaGameEngine.setExpansionZipDir( (String)mGameEngineProxy.laya_get_value("ExpansionMainPath"),(String)mGameEngineProxy.laya_get_value("ExpansionPatchPath"));
|
||||
AssetManager am = mContext.getAssets();
|
||||
mLayaGameEngine.setAssetInfo(am);
|
||||
//_path = (String) mGameEngineProxy.laya_get_value("LibDir");
|
||||
//mLayaGameEngine.setSoPath(_path);
|
||||
//mLayaGameEngine.setJarFile(_path+"LayaBoxPlayer.jar");
|
||||
//mLayaGameEngine.setSoFile("liblaya.so");
|
||||
layaGameListener listener=new layaGameListener();
|
||||
listener.activity=(Activity)mContext;
|
||||
mLayaGameEngine.setLayaEventListener(listener);
|
||||
mLayaGameEngine.setInterceptKey(true);
|
||||
mLayaGameEngine.onCreate();
|
||||
LayaConch5 tmp = (LayaConch5)mLayaGameEngine;
|
||||
Log.e(TAG,"game_plugin_init soPath="+tmp.getSoPath()+" jarfile="+tmp.getJarFile()+" appcache="+tmp.getAppCacheDir());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean game_plugin_intercept_key(int keycode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object game_plugin_invoke_method(String method, Bundle param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void game_plugin_onPause() {
|
||||
mLayaGameEngine.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void game_plugin_onResume() {
|
||||
mLayaGameEngine.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void game_plugin_onStop() {
|
||||
mLayaGameEngine.onStop();
|
||||
}
|
||||
@Override
|
||||
public void game_plugin_onDestory() {
|
||||
mLayaGameEngine.onDestroy();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void game_plugin_set_option(String key, String value) {
|
||||
Log.e(TAG,"game_plugin_set_option key="+key+" value="+value);
|
||||
if( key.equalsIgnoreCase("gameUrl") )
|
||||
mGameUrl = value;
|
||||
else if(key.equalsIgnoreCase("localize")){
|
||||
boolean l = value.equalsIgnoreCase("true");
|
||||
mLayaGameEngine.setLocalizable(l);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void game_plugin_configonChanged(Configuration newConfig) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void game_plugin_set_runtime_proxy(
|
||||
IPluginRuntimeProxy paramIGameEngineRuntimeProxy) {
|
||||
mGameEngineProxy = paramIGameEngineRuntimeProxy;
|
||||
}
|
||||
|
||||
public IPluginRuntimeProxy getRuntimeProxy(){
|
||||
return mGameEngineProxy;
|
||||
}
|
||||
static class layaGameListener implements ILayaEventListener {
|
||||
public Activity activity;
|
||||
@Override
|
||||
public void ExitGame() {
|
||||
Log.i("=======", "======exit");
|
||||
activity.finish();
|
||||
activity=null;
|
||||
//mLayaEngine.onDestroy();
|
||||
System.exit(0);
|
||||
}
|
||||
@Override
|
||||
public void destory() {
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user