Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android Beam

android Beam

編輯:關於Android編程

Beaming NDEF Messages to Other Devices

Android Beam allows simple peer-to-peer data exchange between two Android-powered devices. The application that wants to beam data to another device must be in the foreground and the device receiving the data must not be locked. When the beaming device comes in close enough contact with a receiving device, the beaming device displays the "Touch to Beam" UI. The user can then choose whether or not to beam the message to the receiving device.

安卓Beam允許在兩台Android支持設備進行點對點數據交換,應用想要beam數據給另一台設備(必須在前端),收到數據的設備必須不能被鎖定,當beam設備與接受設備足夠接近時,beam設備展示了“Touch to Beam”的界面,用戶可以選擇是否發送信息給接受設備。

Note: Foreground NDEF pushing was available at API level 10, which provides similar functionality to Android Beam. These APIs have since been deprecated, but are available to support older devices. See enableForegroundNdefPush() for more information.

注意:前台NDEF推送在API10提供了和安卓Beam相似的功能,這些API已經被棄用了,但是仍然支持老的設備,可以從enableForegroundNdefPush()查看更多信息

You can enable Android Beam for your application by calling one of the two methods:

你能夠打開應用的安卓Beam功能通過調用如下兩個方法之一:

setNdefPushMessage(): Accepts an NdefMessage to set as the message to beam. Automatically beams the message when two devices are in close enough proximity.

setNdefPushMessageCallback(): Accepts a callback that contains a createNdefMessage() which is called when a device is in range to beam data to. The callback lets you create the NDEF message only when necessary.

An activity can only push one NDEF message at a time, so setNdefPushMessageCallback() takes precedence over setNdefPushMessage() if both are set. To use Android Beam, the following general guidelines must be met:

一個Activity只能推送一個NDEF信息在一個時刻,所以 setNdefPushMessageCallback() 優先於setNdefPushMessage() 如果都設置的話,為了使用android Beam,如下一般原則必須滿足:

The activity that is beaming the data must be in the foreground. Both devices must have their screens unlocked.

activity 正在推送時都必須在前台,而且兩個設備的屏幕處於解鎖狀態

You must encapsulate the data that you are beaming in an NdefMessage object.

你必須封裝成NdefMessage對象來beam

The NFC device that is receiving the beamed data must support the com.android.npp NDEF push protocol or NFC Forum's SNEP (Simple NDEF Exchange Protocol). The com.android.npp protocol is required for devices on API level 9 (Android 2.3) to API level 13 (Android 3.2). com.android.npp and SNEP are both required on API level 14 (Android 4.0) and later.

NFC設備收到beam過來的數據必須com.android.npp的NDEF推送協議或者Forum's SNEP協議,com.android.npp協議要求設備在 API level 9 (Android 2.3) to API level 13 (Android 3.2),SNEP要求兩台設備都在Android 4.0以上。

Note: If your activity enables Android Beam and is in the foreground, the standard intent dispatch system is disabled. However, if your activity also enables foreground dispatching, then it can still scan tags that match the intent filters set in the foreground dispatching.

注意:如果你的Activity打開了Android Beam而且處於前台,則標准的intent分發系統是不可用的,如果你的activity還打開了前台調度,它仍然能夠掃描通過前台調度系統匹配到的標簽。


To enable Android Beam:

1.Create an NdefMessage that contains the NdefRecords that you want to push onto the other device.

創建一個包含了你想要推送給其他設備的NdefRecords的NdefMessage。

2.Call setNdefPushMessage() with a NdefMessage or call setNdefPushMessageCallback passing in a NfcAdapter.CreateNdefMessageCallback object in the onCreate() method of your activity. These methods require at least one activity that you want to enable with Android Beam, along with an optional list of other activities to activate.
In general, you normally use setNdefPushMessage() if your Activity only needs to push the same NDEF message at all times, when two devices are in range to communicate. You use setNdefPushMessageCallback when your application cares about the current context of the application and wants to push an NDEF message depending on what the user is doing in your application.

調用有一個NdefMessage的setNdefPushMessage() ,或者通過NfcAdapter.CreateNdefMessageCallback對象在調用setNdefPushMessageCallback回調在 onCreate() 方法在你的Activity,這些方法要求至少一個Activity打開了Android Beam,伴隨著其他活動來激活的可選列表。

一般,你總是需要推送NDEF message時調用setNdefPushMessage()在兩個設備在范圍內通信。如果使用setNdefPushMessageCallback回調則關心當前應用的上下文和你根據用戶的操作想要推送的NDEF數據在你的應用。

The following sample shows how a simple activity calls NfcAdapter.CreateNdefMessageCallback in the onCreate() method of an activity (see AndroidBeamDemo for the complete sample). This example also has methods to help you create a MIME record:

下面簡單的展示了一個簡單的Activity調用NfcAdapter.CreateNdefMessageCallback在onCreate() ,完整的例子查看see AndroidBeamDemo for the complete sample:

package com.example.android.beam;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.Charset;


public class Beam extends Activity implements CreateNdefMessageCallback {
    NfcAdapter mNfcAdapter;
    TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.textView);
        // Check for available NFC Adapter
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mNfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        // Register callback
        mNfcAdapter.setNdefPushMessageCallback(this, this);
    }

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        String text = ("Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis());
        NdefMessage msg = new NdefMessage(
                new NdefRecord[] { createMime(
                        "application/vnd.com.example.android.beam", text.getBytes())
         /**
          * The Android Application Record (AAR) is commented out. When a device
          * receives a push with an AAR in it, the application specified in the AAR
          * is guaranteed to run. The AAR overrides the tag dispatch system.
          * You can add it back in to guarantee that this
          * activity starts when receiving a beamed message. For now, this code
          * uses the tag dispatch system.
          */
          //,NdefRecord.createApplicationRecord("com.example.android.beam")
        });
        return msg;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    void processIntent(Intent intent) {
        textView = (TextView) findViewById(R.id.textView);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        textView.setText(new String(msg.getRecords()[0].getPayload()));
    }
}
Note that this code comments out an AAR, which you can remove. If you enable the AAR, the application specified in the AAR always receives the Android Beam message. If the application is not present, Google Play is started to download the application. Therefore, the following intent filter is not technically necessary for Android 4.0 devices or later if the AAR is used:


  
  
  
With this intent filter, the com.example.android.beam application now can be started when it scans an NFC tag or receives an Android Beam with an AAR of type com.example.android.beam, or when an NDEF formatted message contains a MIME record of type application/vnd.com.example.android.beam.

Even though AARs guarantee an application is started or downloaded, intent filters are recommended, because they let you start an Activity of your choice in your application instead of always starting the main Activity within the package specified by an AAR. AARs do not have Activity level granularity. Also, because some Android-powered devices do not support AARs, you should also embed identifying information in the first NDEF record of your NDEF messages and filter for that as well, just in case. See Creating Common Types of NDEF records for more information on how to create records.


Android Beam

Android Beam:兩部NFC設備靠近時,通過觸摸一部NFC設備的屏幕,將數據推向另一部NFC設備。

可以傳輸文本(NDEF格式);也可傳輸文件(圖像、文本文件等)。

文件數據量較大,會自動開啟兩個設備的藍牙;若無藍牙則選用其他方式,如WiFi。


消息點到點傳輸的實現

靜態方法:在onCreat方法中調用如下方法:
NfcAdapter.setNdefPushMessage(NdefMessage message,Activity activity,Activity … activitys)

可以指定多個窗口,但一般指定一個窗口,不用指定後面的第3個參數

該方法直接推送一個NdefMessage對象,在推送之前要先創建該NdefMessage對象


動態方法:在onCreat方法中調用如下方法:
NfcAdapter.setNdefPushMessageCallback(CreateNdefMessageCallback callback,Activity activity,Activity … activitys)

該方法為一個或多個窗口指定一個回調函數,當兩個NFC設備靠近並建立連接後,調用該回調方法(CreateNdefMessageCallback接口中包含這個方法)。

該方法原型:public NdefMessage createNdefMessage(NfcEvent event),NfcEvent對象封裝了NFC相關信息。
該方法的返回值為用於推送的NdefMessage對象。


Uri

Uri:Uniform Resource Identifier,通用資源標識符,Android上可用的每種資源:HTML文檔、圖像、視頻片段等。根據Uri可以找到某個資源文件。如:ContentProvider共享數據,生成數據的Uri格式共程序調用。

Uri由三部分組成:命名機制(scheme)+存放資源的主機名(authority)+資源自身的名稱(path)

例如:所有聯系人Uri:content://contacts/people
某個聯系人Uri:content://contacts/people/5


文件點到點傳輸的實現

靜態方法:在onCreat方法中調用如下方法:
NfcAdapter.setBeamPushUris(Uri[] uris,Activity activity)

可以直接推送1個多個Uri標示的文件,Uri的scheme必須是file或content,如:file:///sdcard/test.jpg


動態方法:在onCreat方法中調用如下方法:

NfcAdapter.setBeamPushUrisCallback(CreateBeamUrisCallback callback,Activity)

該方法為窗口指定一個回調函數,當兩個NFC設備靠近並建立連接後,調用該回調方法(CreateBeamUrisCallback接口中包含這個方法)。

該方法原型:public Uri[] createBeamUris(NfcEvent event),NfcEvent對象封裝了NFC相關信息。
該方法的返回值為1個或多個Uri,即1個或多個文件。


消息點到點傳輸的實現例子代碼:

資源文件:




    

    

    


清單文件:



    

    

    
        
            
                

                
            
        
        
    


Activity:

package mobile.android.android.beam;

import java.nio.charset.Charset;
import java.util.Locale;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;

//需要實現CreatNdefMessageCallback接口,OnNdefPushCompleteCallback接口
public class AndroidBeamMainActivity extends Activity implements
		CreateNdefMessageCallback,OnNdefPushCompleteCallback
{

	private EditText mBeamText;

	private NfcAdapter mNfcAdapter;
	private PendingIntent mPendingIntent;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_android_beam);
		mBeamText = (EditText) findViewById(R.id.edittext_beam_text);
		mNfcAdapter = mNfcAdapter.getDefaultAdapter(this);
		mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
				getClass()), 0);
		//指定推送消息的回調對象
		mNfcAdapter.setNdefPushMessageCallback(this, this);
		//指定推送完成後的回調對象
		mNfcAdapter.setOnNdefPushCompleteCallback(this, this);

	}

	//當推送消息方完成消息推送後調用該方法(屏幕縮小方)
	@Override
	public void onNdefPushComplete(NfcEvent event)
	{
		//Toast.makeText(this, "消息傳輸完成", Toast.LENGTH_LONG).show();
		Log.d("message", "complete");
		
	}

	//實現回調方法
	@Override
	public NdefMessage createNdefMessage(NfcEvent event)
	{
		//獲得文本框中輸入的字符
		String text = mBeamText.getText().toString().trim();
		//如果未輸入字符,則使用以下文本傳送
		if ("".equals(text))
		{
			text = "Android Beam Test";
		}
		//創建一個封裝文本數據的NdefMessage對象,creatTextRecord方法用於創建封裝文本的NdefRecord對象
		NdefMessage msg = new NdefMessage(new NdefRecord[]
		{ createTextRecord(text) });
		return msg;
	}

	@Override
	public void onResume()
	{
		super.onResume();
		if (mNfcAdapter != null)
			mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null,
					null);
		
	}

	@Override
	public void onPause()
	{
		super.onPause();
		if (mNfcAdapter != null)
			mNfcAdapter.disableForegroundDispatch(this);

	}

	@Override
	public void onNewIntent(Intent intent)
	{
		//接收到數據後進行處理
		processIntent(intent);
	}

	public NdefRecord createTextRecord(String text)
	{
		byte[] langBytes = Locale.CHINA.getLanguage().getBytes(
				Charset.forName("US-ASCII"));
		Charset utfEncoding = Charset.forName("UTF-8");
		byte[] textBytes = text.getBytes(utfEncoding);
		int utfBit = 0;
		char status = (char) (utfBit + langBytes.length);
		byte[] data = new byte[1 + langBytes.length + textBytes.length];
		data[0] = (byte) status;
		System.arraycopy(langBytes, 0, data, 1, langBytes.length);
		System.arraycopy(textBytes, 0, data, 1 + langBytes.length,
				textBytes.length);
		NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
				NdefRecord.RTD_TEXT, new byte[0], data);
	  
		return record;
	}

	//處理接收到的數據,將數據解析後並Toast出來
	void processIntent(Intent intent)
	{

		Parcelable[] rawMsgs = intent
				.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

		NdefMessage msg = (NdefMessage) rawMsgs[0];
		String text = TextRecord.parse(msg.getRecords()[0]).getText();
		Toast.makeText(this, text, Toast.LENGTH_LONG).show();
	}
}

TextRecord:

package mobile.android.android.beam;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import android.nfc.NdefRecord;


public class TextRecord
{
	private final String mText;

	private TextRecord(String text)
	{
		
		mText = text;
	}

	public String getText()
	{
		return mText;
	}


	//  將純文本內容從NdefRecord對象中解析出來
	public static TextRecord parse(NdefRecord record)
	{
		
		if(record.getTnf() != NdefRecord.TNF_WELL_KNOWN)
			return null;
		if(!Arrays.equals(record.getType(), NdefRecord.RTD_TEXT))
			return null;

		try
		{
			byte[] payload = record.getPayload();
			/*
			 * payload[0] contains the "Status Byte Encodings" field, per the
			 * NFC Forum "Text Record Type Definition" section 3.2.1.
			 * 
			 * bit7 is the Text Encoding Field.
			 * 
			 * if (Bit_7 == 0): The text is encoded in UTF-8 if (Bit_7 == 1):
			 * The text is encoded in UTF16
			 * 
			 * Bit_6 is reserved for future use and must be set to zero.
			 * 
			 * Bits 5 to 0 are the length of the IANA language code.
			 */
			String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8"
					: "UTF-16";
			int languageCodeLength = payload[0] & 0x3f;
			String languageCode = new String(payload, 1, languageCodeLength,
					"US-ASCII");
			String text = new String(payload, languageCodeLength + 1,
					payload.length - languageCodeLength - 1, textEncoding);
			return new TextRecord(text);
		}
		catch (UnsupportedEncodingException e)
		{
			// should never happen unless we get a malformed tag.
			throw new IllegalArgumentException(e);
		}
	}


}


文件點到點傳輸的實現例子程序:

資源文件:




清單文件:




    

    
    
    
        
            
                

                
            
        
    


Activity:

package mobile.android.nfcfile;

import java.io.FileOutputStream;
import java.io.InputStream;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateBeamUrisCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;

//需要實現CreatBeamUrisCallback接口
public class NFCFileActivity extends Activity implements CreateBeamUrisCallback
{
	private NfcAdapter mNfcAdapter;
	private PendingIntent mPendingIntent;
    private final String targetFilename = "/sdcard/temp_icon.png"; 
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_nfcfile);
		mNfcAdapter = mNfcAdapter.getDefaultAdapter(this);
		mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
				getClass()), 0);
		//指定觸發NFC Beam傳輸的回調對象
		mNfcAdapter.setBeamPushUrisCallback(this, this);

		try
		{
			//將assets目錄中的icon.png文件復制到SD卡的根目錄,文件名由targetFilename指定
			InputStream is = getResources().getAssets().open("icon.png");
			FileOutputStream fos = new FileOutputStream(targetFilename);
			byte[] buffer = new byte[10000];
			int n = is.read(buffer);
			fos.write(buffer, 0, n);
			fos.close();
			is.close();
		}
		catch (Exception e)
		{

		}

	}

	//當開始傳輸文件時調用的方法,並返回的一個或多個Uri
	@Override
	public Uri[] createBeamUris(NfcEvent event)
	{
		Uri[] uris = new Uri[1];
		//該Uri指向要傳輸的文件
		Uri uri = Uri.parse("file://" + targetFilename);
				
		uris[0] = uri;

		return uris;
	}
}


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved