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

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;
}
///
依旧是比较杂乱,接口的调用都写在界面里了,我们在接下来的文章中继续讲解界面时再给大家贴出详细的代码。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值