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