【问题标题】:How can I send a string through NFC while Screen-Pinning?如何在屏幕固定时通过 NFC 发送字符串?
【发布时间】:2015-04-09 18:26:56
【问题描述】:

我正在尝试通过 NFC 发送String,而我的应用正在使用screen pinning。它不起作用:转移没有发生;但如果我禁用屏幕固定String 的传输工作。

我可以暂时禁用屏幕固定,然后执行传输,但这是一个安全风险。

我该怎么做?


如果您想尝试,这里是所有代码。您需要做的就是通过您的应用程序设置手动启用屏幕固定(因此它的代码更少并且仍然产生相同的结果)。我使用两个运行 Android 5.0 的 Nexus 7 对此进行了测试。

您不必阅读所有这些代码,如果您知道我可以添加到我的清单中允许在屏幕固定时使用 NFC 的内容,这个问题可能会得到解决。


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidnfc"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.NFC"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.androidnfc.MainActivity"
            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="text/plain" />
            </intent-filter>
        </activity>
    </application>
</manifest>

MainActivity.java

public class MainActivity extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback
{ 
   TextView textInfo;
   EditText textOut;  
   NfcAdapter nfcAdapter;

   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      textInfo = (TextView)findViewById(R.id.info);
      textOut = (EditText)findViewById(R.id.textout);

      nfcAdapter = NfcAdapter.getDefaultAdapter(this);
      nfcAdapter.setNdefPushMessageCallback(this, this);
      nfcAdapter.setOnNdefPushCompleteCallback(this, this);
   }

   @Override
   protected void onResume() 
   {
      super.onResume();
      Intent intent = getIntent();
      String action = intent.getAction();

      if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
      {
         Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
         NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
         NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
         NdefRecord NdefRecord_0 = inNdefRecords[0];
         String inMsg = new String(NdefRecord_0.getPayload());
         textInfo.setText(inMsg);
      }
   }

   @Override
   protected void onNewIntent(Intent intent) {
     setIntent(intent);
   }

   @Override
   public void onNdefPushComplete(NfcEvent event) {
      final String eventString = "onNdefPushComplete\n" + event.toString();
      runOnUiThread(new Runnable() {

        @Override
        public void run() {
          Toast.makeText(getApplicationContext(), eventString, Toast.LENGTH_LONG).show();
        }
       });
   }

   @Override
   public NdefMessage createNdefMessage(NfcEvent event) {
      String stringOut = textOut.getText().toString();
      byte[] bytesOut = stringOut.getBytes();

      NdefRecord ndefRecordOut = new NdefRecord(
         NdefRecord.TNF_MIME_MEDIA, 
         "text/plain".getBytes(),
                new byte[] {}, 
                bytesOut);

      NdefMessage ndefMessageout = new NdefMessage(ndefRecordOut);
      return ndefMessageout;
   }
}

布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidnfc.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/textout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

【问题讨论】:

  • 你试过你的例子吗?您使用哪个 Android 版本和设备进行了测试?我刚刚使用运行 Android 5.0.1 (LRX22C) 的 Nexus 4 进行了测试,即使屏幕固定,您的示例也能正常工作。
  • 我在两台运行 Android 5 的 Nexus 7 上进行了尝试。你的两台设备都必须固定屏幕才能遇到问题。
  • 在 Android 5.0.1 上,您的示例仍然有效:在接收设备上,屏幕会自动取消固定,并启动新的活动实例。这可能是由于手动固定而不是通过程序代码执行的吗?
  • 我已经用手动固定和代码固定进行了测试——两​​者都不起作用。

标签: android nfc android-5.0-lollipop nfc-p2p android-screen-pinning


【解决方案1】:

我不确定这是否真的回答了你的问题,但我想总结一下我的发现:

在 Android 5.0.1(Nexus 4 上的 LRX22C)上尝试您的示例时,接收方会在收到 NDEF 消息后自动取消固定屏幕并(重新)启动活动。因此,清单中注册的意图过滤器似乎优先于(手动?)屏幕固定。

我知道这与问题中描述的体验不太匹配。我想知道这是由于不同的 Android 版本(5.0 与 5.0.1)还是由于使用手动屏幕固定而不是编程屏幕固定...

在我的测试设置中,我能够通过使用前台调度系统注册活动以接收其 NDEF 消息来解决问题(即防止活动自动取消固定):

在您的 onResume() 方法中创建一个像这样的待处理意图并启用前台调度:

PendingIntent pi = this.createPendingResult(0x00A, new Intent(), 0);
nfcAdapter.enableForegroundDispatch(this, pi, null, null);

然后您将通过活动的onActivityResult() 方法收到通知您发现标签的意图:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case 0x00A:
            onNewIntent(data);
        break;
    }
}

此外,您必须在 onPause() 方法中禁用前台调度:

nfcAdapter.disableForegroundDispatch(this);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 2020-08-16
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多