这里有一些背景第一:
我正在尝试做一个概念验证的 Android 应用程序,它将检查我是否可以将一些 APDU 命令发送到 SIM 卡小程序并处理响应。
我使用SEEK for Android作为 Open Mobile API 的参考实现。
该应用程序应该可以在带有 Open Mobile API 的三星 Galaxy S3 智能手机上运行,如此处所述。
我不允许使用自定义 ROM,也不允许对 Android 源代码进行任何修改。
到目前为止我做了什么:
- 我已经下载了带有 Open Mobile API 和 Open Mobile API 包的 Android API lvl 18。
- 我创建了一个示例应用程序,它应该尝试访问我的 SIM 卡上的小程序,如此处所述。
单击按钮时,我收到 SecurityException
06-23 12:57:15.620: I/HelloSmartcard(5386): creating SEService object 06-23 12:57:15.655: I/SEService(5386): Connected 06-23 12:57:22.525: I/HelloSmartcard(5386): Retrieve available readers... 06-23 12:57:22.530: I/HelloSmartcard(5386): Create Session from the UICC reader... 06-23 12:57:23.275: I/HelloSmartcard(5386): Create logical channel within the session... 06-23 12:57:23.285: E/HelloSmartcard(5386): Error occured: 06-23 12:57:23.285: E/HelloSmartcard(5386): java.lang.SecurityException: Access Control Enforcer: access denied: EF_DIR not found!! 06-23 12:57:23.285: E/HelloSmartcard(5386): at org.simalliance.openmobileapi.SEService.checkForException(SEService.java:234) 06-23 12:57:23.285: E/HelloSmartcard(5386): at org.simalliance.openmobileapi.Session.openLogicalChannel(Session.java:302) 06-23 12:57:23.285: E/HelloSmartcard(5386): at com.example.testsmartcardaccess2.MainActivity$1.onClick(MainActivity.java:81) 06-23 12:57:23.285: E/HelloSmartcard(5386): at android.view.View.performClick(View.java:4475) 06-23 12:57:23.285: E/HelloSmartcard(5386): at android.view.View$PerformClick.run(View.java:18786) 06-23 12:57:23.285: E/HelloSmartcard(5386): at android.os.Handler.handleCallback(Handler.java:730) 06-23 12:57:23.285: E/HelloSmartcard(5386): at android.os.Handler.dispatchMessage(Handler.java:92) 06-23 12:57:23.285: E/HelloSmartcard(5386): at android.os.Looper.loop(Looper.java:176) 06-23 12:57:23.285: E/HelloSmartcard(5386): at android.app.ActivityThread.main(ActivityThread.java:5419) 06-23 12:57:23.285: E/HelloSmartcard(5386): at java.lang.reflect.Method.invokeNative(Native Method) 06-23 12:57:23.285: E/HelloSmartcard(5386): at java.lang.reflect.Method.invoke(Method.java:525) 06-23 12:57:23.285: E/HelloSmartcard(5386): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046) 06-23 12:57:23.285: E/HelloSmartcard(5386): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862) 06-23 12:57:23.285: E/HelloSmartcard(5386): at dalvik.system.NativeStart.main(Native Method) 06-23 12:57:23.285: I/Choreographer(5386): Skipped 45 frames! The application may be doing too much work on its main thread.
我有 org.simalliance.openmobileapi.jar 作为依赖项:
我有权限:
<uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD"/>
我在 SIM 卡上有 3 个小程序,我正在尝试调用 AID 下的那个
F9 F4 0F 65 18 C9 54 1E CD AD
这是我正在使用的粗略代码模板:
package com.example.testsmartcardaccess2;
import org.simalliance.openmobileapi.Channel;
import org.simalliance.openmobileapi.Reader;
import org.simalliance.openmobileapi.SEService;
import org.simalliance.openmobileapi.Session;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Toast;
public class MainActivity extends Activity implements SEService.CallBack {
private SEService seService;
private Reader uuicReader;
private boolean seServiceConnected;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
final String LOG_TAG = "HelloSmartcard";
try {
Log.i(LOG_TAG, "creating SEService object");
this.seServiceConnected = false;
seService = new SEService(MainActivity.this, MainActivity.this);
} catch (SecurityException e) {
Log.e(LOG_TAG,
"Binding not allowed, uses-permission org.simalliance.openmobileapi.SMARTCARD?");
} catch (Exception e) {
Log.e(LOG_TAG, "Exception: " + e.getMessage());
}
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
button = new Button(this);
button.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
button.setText("Click Me");
button.setEnabled(false);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
Log.i(LOG_TAG, "Retrieve available readers...");
Reader[] readers = seService.getReaders();
if (readers.length < 1)
return;
uuicReader = null;
for (Reader reader : readers) {
if (reader.getName().equalsIgnoreCase("SIM - UICC")) {
uuicReader = reader;
break;
}
}
Log.i(LOG_TAG, "Create Session from the UICC reader...");
Session session = uuicReader.openSession();
Log.i(LOG_TAG,
"Create logical channel within the session...");
Channel channel = session.openLogicalChannel(
new byte[] {
(byte) 0xF9,
(byte) 0xF4,
(byte) 0x0F,
(byte) 0x65,
(byte) 0x18,
(byte) 0xC9,
(byte) 0x54,
(byte) 0x1E,
(byte) 0xCD,
(byte) 0xAD
}
);
Log.d(LOG_TAG, "Send HelloWorld APDU command");
byte[] respApdu = channel.transmit(new byte[] {
(byte) 0x90, 0x10, 0x00, 0x00, 0x00 });
channel.close();
// Parse response APDU and show text but remove SW1 SW2
// first
byte[] helloStr = new byte[respApdu.length - 2];
System.arraycopy(respApdu, 0, helloStr, 0,
respApdu.length - 2);
Toast.makeText(MainActivity.this, new String(helloStr),
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e(LOG_TAG, "Error occured:", e);
return;
}
}
});
layout.addView(button);
setContentView(layout);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void serviceConnected(SEService arg0) {
Log.i("SEService", "Connected");
this.seServiceConnected = this.seService.isConnected();
updateButtonStatus(button, this.seServiceConnected);
}
private void updateButtonStatus(Button button, boolean enabled) {
button.setEnabled(enabled);
}
@Override
protected void onDestroy() {
if (seService != null && seService.isConnected()) {
seService.shutdown();
this.seServiceConnected = false;
updateButtonStatus(button, this.seServiceConnected);
}
super.onDestroy();
}
}
我相信我的 SIM 卡上没有设置有关小程序访问的内容,但由于那部分不是我的域,我不知道该怎么做才能解决这个问题。
我在 Google Groups 上遇到过这个与我的困境相似的讨论,但我不知道如何解释它。
任何帮助表示赞赏!