您的位置:首页 > 移动开发 > Unity3D

LOR手游开发过程记录——菜单界面——NFC的Unity接口

2016-01-17 01:12 666 查看
////////////////2015/01/16///////////////////

///////////////by XBW///////////////////////

///////////////unity4.6.1 /eclipse/////////////

首先说一下,这个游戏是参加了MIAC第二届的比赛的一个作品,惨败,获得了优胜奖,在这记录整理一下开发的过程吧。

先来几张截图大体了解一下



个人logo界面





游戏菜单界面



游戏加载界面



游戏主界面



分享至新浪微博界面

大体就分这几个界面,接下来会详细介绍,这篇文章主要讲一下菜单界面,关于这个界面,真是要说很多,自我感觉杂乱无章,这个界面结合了eclipse做的一个NFC接口的SDK,起初对NFC是一点不懂,在图书馆借了本《Android传感器高级编程》的书才略知一二,了解后赶紧写了个NFC的SDK,关于这个SDK,技术不精的我愣是搞了好几天,各种吧bug,愁得要死要活的,不过就中还是实现了NFC的感应控制游戏,不知道为什么这样一个技术应用到游戏中也没有伯乐,市场几乎没有这种技术应用到游戏中的,好可惜,那么,这篇文章就写一下这个SDK吧。

我们用到了eclipse,安卓手游嘛,所以跟做安卓app类似了,先建一个工程吧,注意,这里的工程要求比较苛刻,我们必须保证这个包名跟签名与unity最后打包生成的包名签名一致,否则会出现程序已停止,就是根本无法启动,新建工程后,我需要导入unity的类库,

,至于这个库去哪找,我不多说了,在unity的安装的根目录里,不懂得请百度吧,导入之后,我们就可以写NFC底层了,直接贴代码了,代码中有详细注释

package com.XBW.nfcgame;

import java.io.IOException;

import java.nio.charset.Charset;

import org.json.JSONException;

import org.json.JSONObject;

import cn.sharesdk.framework.ShareSDK;

import cn.sharesdk.onekeyshare.OnekeyShare;

import com.XBW.nfcgame.R;

import com.unity3d.player.UnityPlayer;

import com.unity3d.player.UnityPlayerActivity;

import android.app.AlertDialog;

import android.app.PendingIntent;

import android.content.DialogInterface;

import android.content.Intent;

import android.content.IntentFilter;

import android.content.IntentFilter.MalformedMimeTypeException;

import android.nfc.NdefMessage;

import android.nfc.NdefRecord;

import android.nfc.NfcAdapter;

import android.nfc.Tag;

import android.nfc.tech.Ndef;

import android.nfc.tech.NdefFormatable;

import android.os.Bundle;

import android.os.Parcelable;

import android.view.WindowManager;

import android.widget.Toast;

public class MainActivity extends UnityPlayerActivity

{NfcAdapter mNfcAdapter;

PendingIntent mNfcPendingIntent;

IntentFilter[] mReadTagFilters;

IntentFilter[] mWriteTagFilters;

private boolean mWriteMode = false;

String mName;

String reNFC=”N”;

    @Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

        // 得到一个实例的缓存NfcAdapter

mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

//判断你的设备是否支持NFC功能

if (mNfcAdapter == null)

{

Toast.makeText(this,

“Your device does not support NFC. Cannot run demo.”,

Toast.LENGTH_LONG).show();

finish();

return;

}

//检查NFC是否能用

checkNfcEnabled();

//创建一个 PendingIntent 对象, 这样Android系统就能在一个tag被检测到时定位到这个对象

mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,

getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

//创建意图过滤器来处理NDEF NFC标签检测到在我们的应用程序在“读模式”:

IntentFilter ndefDetected = new IntentFilter(

NfcAdapter.ACTION_NDEF_DISCOVERED);

try

{

ndefDetected.addDataType(“application/xbw.game.playground.nfc”);

} catch (MalformedMimeTypeException e)

{

throw new RuntimeException(“Could not add MIME type.”, e);

}

//创建意图过滤器,以发现任何NFC标记当试图写一个标签在“写模式”

IntentFilter tagDetected = new IntentFilter(

NfcAdapter.ACTION_TAG_DISCOVERED);

        // 创建IntentFilter数组:

mWriteTagFilters = new IntentFilter[] { tagDetected };

mReadTagFilters = new IntentFilter[] { ndefDetected, tagDetected };

}

@Override

protected void onResume()

{

super.onResume();

//检查NFC是否能用

checkNfcEnabled();

if (getIntent().getAction() != null)

{

// 标签收到应用程序不运行时,没有在前台:

if (getIntent().getAction().equals(

NfcAdapter.ACTION_NDEF_DISCOVERED))

{

//NdefMessage[] msgs = getNdefMessagesFromIntent(getIntent());

//NdefRecord record = msgs[0].getRecords()[0];

//byte[] payload = record.getPayload();

//setTextFieldValues(new String(payload));

}

}

//禁用前景分派到给定的活动

mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent,

mReadTagFilters, null);

}

@Override

protected void onPause()

{

super.onPause();

//禁用前景分派到给定的活动

mNfcAdapter.disableForegroundDispatch(this);

}

@Override

protected void onNewIntent(Intent intent)

{

if (!mWriteMode)

{

// 目前在标签阅读模式

if (intent.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED))

{

NdefMessage[] msgs = getNdefMessagesFromIntent(intent);

confirmDisplayedContentOverwrite(msgs[0]);

} else if (intent.getAction().equals(

NfcAdapter.ACTION_TAG_DISCOVERED))

{

Toast.makeText(this,

“This NFC tag currently has no inventory NDEF data.”,

Toast.LENGTH_LONG).show();

}

} else

{

// 目前在标签写入模式

if (intent.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED))

{

Tag detectedTag = intent

.getParcelableExtra(NfcAdapter.EXTRA_TAG);

writeTag(createNdefFromJson(), detectedTag);

}

}

}

   //NFC读取方法

NdefMessage[] getNdefMessagesFromIntent(Intent intent)

{

NdefMessage[] msgs = null;

String action = intent.getAction();

if (action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)

|| action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))

{

Parcelable[] rawMsgs = intent

.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

if (rawMsgs != null)

{

msgs = new NdefMessage[rawMsgs.length];

for (int i = 0; i < rawMsgs.length; i++)

{

msgs[i] = (NdefMessage) rawMsgs[i];

}

} else

{

// 未知的标签类型

byte[] empty = new byte[] {};

NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN,

empty, empty, empty);

NdefMessage msg = new NdefMessage(new NdefRecord[] { record });

msgs = new NdefMessage[] { msg };

}

} else

{

finish();

}

return msgs;

}

    private void confirmDisplayedContentOverwrite(final NdefMessage msg)

{

String payload = new String(msg.getRecords()[0]

.getPayload());setTextFieldValues(payload);

}

    private void setTextFieldValues(String jsonString)

{

JSONObject inventory = null;

String name = “”;

try

{

inventory = new JSONObject(jsonString);

name = inventory.getString(“name”);

} catch (JSONException e)

{

}

//给unity调用的接口,需要挂载给Player物体,方法为NFC

UnityPlayer.UnitySendMessage(“Player”,”NFC”,name);

}

//NFC写入方法

//unity传进来需要写入的数据写入NFC

public void StartActivity0(String name)

{

mName=name;

//if(!mWriteMode)

//enableTagWriteMode();

enableTagWriteMode();

}

//关闭读取,打开写入

public void StartActivity1(String name)

{

//mName=name;

enableTagReadMode();

//mWriteMode=false;

}

//进入游戏后只有读取功能,关闭写入功能

//public void StartActivity2(String name)

//{

//mWriteMode=true;

//if(mWriteMode)

//enableTagReadMode();

//}

private NdefMessage createNdefFromJson()

{

// 创建一个JSON对象的值:

JSONObject computerSpecs = new JSONObject();

try

{

computerSpecs.put(“name”, mName);

} catch (JSONException e)

{}

//创建一个新的包含消息NDEF NDEF记录和使用应用程序的自定义MIME类型:

String mimeType = “application/xbw.game.playground.nfc”;

byte[] mimeBytes = mimeType.getBytes(Charset.forName(“UTF-8”));

String data = computerSpecs.toString();

byte[] dataBytes = data.getBytes(Charset.forName(“UTF-8”));

byte[] id = new byte[0];

NdefRecord record = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,

mimeBytes, id, dataBytes);

NdefMessage m = new NdefMessage(new NdefRecord[] { record });

        // 返回NDEF信息

return m;

}

    private void enableTagWriteMode()

{

mWriteMode = true;

mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent,

mWriteTagFilters, null);

}

    private void enableTagReadMode()

{

mWriteMode = false;

mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent,

mReadTagFilters, null);

}

    boolean writeTag(NdefMessage message, Tag tag)

{

int size = message.toByteArray().length;

try

{

Ndef ndef = Ndef.get(tag);

if (ndef != null)

{

ndef.connect();

                if (!ndef.isWritable())

{

Toast.makeText(this,

“Cannot write to this tag. This tag is read-only.”,

Toast.LENGTH_LONG).show();

return false;

}

if (ndef.getMaxSize() < size)

{

Toast.makeText(

this,

“Cannot write to this tag. Message size (” + size

+ ” bytes) exceeds this tag’s capacity of ”

+ ndef.getMaxSize() + ” bytes.”,

Toast.LENGTH_LONG).show();

return false;

}

                ndef.writeNdefMessage(message);

UnityPlayer.UnitySendMessage(“Player”,”reNFC”,reNFC);

Toast.makeText(this,

“A pre-formatted tag was successfully updated.”,

Toast.LENGTH_LONG).show();

return true;

} else

{

NdefFormatable format = NdefFormatable.get(tag);

if (format != null)

{

try

{

format.connect();

format.format(message);

Toast.makeText(

this,

“This tag was successfully formatted and updated.”,

Toast.LENGTH_LONG).show();

return true;

} catch (IOException e)

{

Toast.makeText(

this,

“Cannot write to this tag due to I/O Exception.”,

Toast.LENGTH_LONG).show();

return false;

}

} else

{

Toast.makeText(

this,

“Cannot write to this tag. This tag does not support NDEF.”,

Toast.LENGTH_LONG).show();

return false;

}

}

} catch (Exception e)

{

Toast.makeText(this,

“Cannot write to this tag due to an Exception.”,

Toast.LENGTH_LONG).show();

}

        return false;

}

    //NFC检查方法

    private void checkNfcEnabled()

{

Boolean nfcEnabled = mNfcAdapter.isEnabled();

if (!nfcEnabled)

{

new AlertDialog.Builder(MainActivity.this)

.setTitle(getString(R.string.warning_nfc_is_off))

.setMessage(getString(R.string.turn_on_nfc))

.setCancelable(false)

.setPositiveButton(“开启NFC”,

new DialogInterface.OnClickListener()

{

public void onClick(DialogInterface dialog,

int id)

{

startActivity(new Intent(

android.provider.Settings.ACTION_NFC_SETTINGS));

MainActivity.this.finish();

//这里改为ACTION_NFC_SETTINGS效果更好之前为//ACTION_WIRELESS_SETTINGS;

}

}

).create().show();

}

}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
大概就这样了,我们还需要在AndroidManifest.xml中添加NFC需要的权限,以及我们需要过滤的自定义NFC标签,

<?xml version=”1.0″ encoding=”utf-8″?>

< manifest xmlns:android=”http://schemas.android.com/apk/res/android”

package=”com.XBW.nfcgame”

android:versionCode=”1″

android:versionName=”1.0″ >

    <uses-sdk

android:minSdkVersion=”14″

android:targetSdkVersion=”22″ />

< uses-feature

android:name=”android.hardware.nfc”

android:required=”true” />

< uses-permission android:name=”android.permission.NFC” /><uses-permission android:name=”android.permission.INTERNET” />

< uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />

< uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />

< uses-permission android:name=”android.permission.READ_PHONE_STATE” />

< uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />

< uses-permission android:name=”android.permission.RESTART_PACKAGES” />

< uses-permission android:name=”android.permission.CHANGE_WIFI_STATE”/>

< uses-permission android:name=”android.permission.CAMERA”/>

< uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>

< uses-permission android:name=”android.permission.BATTERY_STATS”/>

< uses-permission android:name=”android.permission.CALL_PHONE”/>

< uses-permission android:name=”android.permission.VIBRATE”/>

< uses-permission android:name=”android.permission.FLASHLIGHT”/>

< uses-permission android:name=”android.permission.WRITE_SMS”/>

< uses-permission android:name=”android.permission.WAKE_LOCK”/>

< uses-permission android:name=”android.permission.EXPAND_STATUS_BAR”/>

< uses-permission android:name=”android.permission.MODIFY_AUDIO_SETTINGS”/>

< uses-permission android:name=”android.permission.RECORD_AUDIO”/>

< uses-permission android:name=”android.permission.GET_TASKS” />

< uses-permission android:name=”android.permission.INTERNET” />

< uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />

< uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />

< uses-permission android:name=”android.permission.CHANGE_WIFI_STATE” />

< uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />

< uses-permission android:name=”android.permission.READ_PHONE_STATE” />

< uses-permission android:name=”android.permission.MANAGE_ACCOUNTS”/>

< uses-permission android:name=”android.permission.GET_ACCOUNTS”/>

< !– 蓝牙分享所需的权限 –>

< uses-permission android:name=”android.permission.BLUETOOTH” />

< uses-permission android:name=”android.permission.BLUETOOTH_ADMIN” />

< application

android:allowBackup=”true”

android:icon=”@drawable/ic_launcher”

android:label=”@string/app_name”

android:theme=”@style/AppTheme” >

< activity

android:name=”.test”

android:label=”@string/app_name”

>

< intent-filter>

< action android:name=”android.intent.action.MAIN” />

                <category android:name=”android.intent.category.LAUNCHER” />

< /intent-filter>

< intent-filter>

< action android:name=”android.nfc.action.NDEF_DISCOVERED” />

< category android:name=”android.intent.category.DEFAULT” />

< data android:mimeType=”application/xbw.game.playground.nfc” />

< /intent-filter>

< /activity>

< activity

android:name=”.MainActivity”

android:label=”@string/app_name”

>< /activity>

< activity

android:name=”com.mob.tools.MobUIShell”

android:theme=”@android:style/Theme.Translucent.NoTitleBar”

android:configChanges=”keyboardHidden|orientation|screenSize”

android:windowSoftInputMode=”stateHidden|adjustResize” >

< intent-filter>

< data android:scheme=”tencent100371282″ />

< action android:name=”android.intent.action.VIEW” />

< category android:name=”android.intent.category.BROWSABLE” />

< category android:name=”android.intent.category.DEFAULT” />

< /intent-filter>

< /activity>

<!– 调用新浪原生SDK,需要注册的回调activity –>

< activity

android:name=”cn.sharesdk.sina.weibo.SinaActivity”

android:theme=”@android:style/Theme.Translucent.NoTitleBar”>

< intent-filter>

< action android:name=”com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY” />

< category android:name=”android.intent.category.DEFAULT” />

< /intent-filter>

< /activity>

</application>

</manifest>
///////////////////////////////////////////////////////////////////////////////////////////////////////////
直接在工程中找的,因为后期添加了新浪微博的SDK,需要添加更多的权限,我们后续再说,这个NFC的SDK就已经弄好了,我们导出工程为jar包就好了,下面就是在unity端调用接口了,先写一下接口具体怎么调用,
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

if (reNFC1 == “N”)

{

if (clo)

{

//GUI.skin = GUIskin;

if (GUI.Button(new Rect(Screen.width * 0.36f, Screen.height * 0.6f, Screen.width * 0.24f, Screen.height * 0.13f), “”))//点击确定进入游戏NFC为读取模式,进入游戏

{

music.PlayOneShot(beep1);

using (AndroidJavaClass jc = new AndroidJavaClass(“com.unity3d.player.UnityPlayer”))

{

using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>(“currentActivity”))

{

//调用Android插件中UnityTestActivity中StartActivity0方法,stringToEdit表示它的参数

jo.Call(“StartActivity0”, name1);

}

}

//Application.LoadLevel(“Loading”);

NFC2 = 0;

clo = false;

reNFC1 = “Y”;

}

if (GUI.Button(new Rect(Screen.width * 0.73f, Screen.height * 0.24f, Screen.width * 0.1f, Screen.height * 0.1f), “”))

{

music.PlayOneShot(beep1);

reNFC1 = “N”;

}

GUI.skin = GUIskin1;

if (GUI.Button(new Rect(0, 0, Screen.width, Screen.height), “”))

{

                }

}

else

{

//GUI.skin = GUIskin;

if (GUI.Button(new Rect(Screen.width * 0.36f, Screen.height * 0.6f, Screen.width * 0.24f, Screen.height * 0.13f), “”))//点击确定进入游戏NFC为读取模式,进入游戏

{

music.PlayOneShot(beep1);

using (AndroidJavaClass jc = new AndroidJavaClass(“com.unity3d.player.UnityPlayer”))

{

using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>(“currentActivity”))

{

//调用Android插件中UnityTestActivity中StartActivity0方法,stringToEdit表示它的参数

jo.Call(“StartActivity1”, name);

}

}

Application.LoadLevel(“Loading”);

}

if (GUI.Button(new Rect(Screen.width * 0.73f, Screen.height * 0.24f, Screen.width * 0.1f, Screen.height * 0.1f), “”))

{

music.PlayOneShot(beep1);

reNFC1 = “Y”;

}

GUI.skin = GUIskin1;

if (GUI.Button(new Rect(0, 0, Screen.width, Screen.height), “”))

{

                }

}

}

        if (NFC2 == 0)

{

GUI.skin = GUIskin1;

if (GUI.Button(new Rect(0, 0, Screen.width, Screen.height), “”))

{

            }

NFC = 1;

}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
依旧是比较杂乱,接口的调用都写在界面里了,我们在接下来的文章中继续讲解界面时再给大家贴出详细的代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: