12

我想通过发送String NFC而我的应用程序使用screen pinning。它不起作用:转移不会发生;但如果我禁用屏幕锁定String作品的转移。如何在屏幕锁定时通过NFC发送字符串?

我可以禁用屏幕固定一下然后执行转移,但这是一个安全风险。

我该怎么做?


这里是所有的代码,如果你想尝试。所有你需要做的是通过你的应用程序设置手动启用屏幕锁定(所以它是更少的代码,并仍然产生相同的结果)。我使用两个运行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> 
+0

你试过你的榜样?你测试过哪款Android版本和设备?我刚刚使用运行Android 5.0.1(LRX22C)的Nexus 4进行了测试,即使屏幕固定,您的示例也可以正常工作。 – 2015-02-20 10:06:35

+0

我用两台运行Android 5的Nexus 7试了一下。你的设备都必须有屏幕锁定才能遇到问题。 – 2015-02-21 04:50:25

+0

在Android 5.0.1上,您的示例仍然有效:在接收设备上,屏幕自动*取消固定*,并开始一个新的活动实例。这可能是由于手动固定,而不是通过程序代码? – 2015-02-23 11:15:33

回答

4

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

在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); 

然后您将收到no intents no tifying你关于发现标签通过活动的onActivityResult()方法:

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

而且,你必须禁用您onPause()方法的前景调度:

nfcAdapter.disableForegroundDispatch(this);