(Update: I got a reply from Jouni Malinen on the hostap mailinglist, I tried his approachm but that doesn't seem to work either. I posted the message below on the hostap mailinglist as well, since it seems to be an Android-wpa_supplicant combination problem)
Hello Jouni, Thanks for the reply. I've tried talking to the Unix domain Socket, but it doesn't work. It appears to be a permission problem. You mentioned that Solution 3 should work. Quote from my previous post; "- Solution 3: Talking directly to the control interface of wpa_suplicant using Unix domain sockets. I found that the Android API supplies us with the LocalSocket class for this. ..." I have tried 2 ways of connecting to the wpa_supplicant Unix domain socket(s). 1. From an Android terminal emulator through wpa_cli. 2. I adapted an example Java Android program (original: http://all4dev.blogspot.com/2009/02/android-localsocket-localserversocket.html). For clarity: each Android app has its own group and username, for example <group:user> = app_35:app_35. For each approach I adjusted wpa_supplicant.conf>ctrl_interface_group to allow an app access to the domain sockets, for example (ctrl_interface_group=app_35). Results approach 1 ( From an Android terminal emulator through wpa_cli. ): 1. I start up the Android terminal emulator and enter the command wpa_cli -p/data/misc/wifi/sockets/ctrl_wpa_79-0. I get the message: "Using interface 'tiwlan0' Could not connect to wpa_supplicant - re-trying" (The output is the same if I don't add the path to the socket, or change the path to /data/misc/wifi/sockets.) Results approaches 2a and 2b: Next, I tried it from an Android Java program (with the correct wpa_supplicant.conf.ctrl_interface_group and after wpa_cli>reconfigure) using 2 slightly different approaches: a. When I use 'tiwlan0' as LocalSocketAddress, I use an abstract namespace for the LocalSocket. When I do this I get a 'connection refused' error message from the Android debug tool logcat. b. When In use "/data/misc/wifi/sockets/ctrl_wpa_79-0", I use the Filesystem Namespace. I then get a 'permission denied' error message. a&b Both throw an IOException at the line "receiver.connect(new LocalSocketAddress(SOCKET_ADDRESS, NAMESPACE)); " (this happens when "if socket is in invalid state or the address does not exist."). So, or I'm doing something wrong, or something goes wrong with the socket permissions. In the adb shell output the file permissions for the sockets are set to <group:user> system:wifi. Below this message you can find the shell output and the Java code. Thanks for any help in advance. Kind regards, Aäron Jansen ***** Extra = ADB shell output showing location of sockets, and wpa_supplicant.conf ***** C:\Users\ajansen\Desktop\android-sdk-windows\tools>adb root adbd is already running as root C:\Users\ajansen\Desktop\android-sdk-windows\tools>adb shell # cd /data/misc/wifi cd /data/misc/wifi # cat wpa_supplicant.conf cat wpa_supplicant.conf ctrl_interface=tiwlan0 ctrl_interface_group=app_35 network={ ssid="aaron" proto=WPA2 key_mgmt=WPA-EAP eap=PEAP pairwise=CCMP } # # cd sockets cd sockets # pwd pwd /data/misc/wifi/sockets # ls ls wpa_ctrl_79-1 wpa_ctrl_79-0 # ls -l ls -l srw-rw---- system wifi 2010-02-23 10:23 wpa_ctrl_79-1 srw-rw---- system wifi 2010-02-23 10:23 wpa_ctrl_79-0 # ***** Java code ***** package com.example.demolocalsocket; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; /** * * @author Denis Migol * */ public class DemoLocalSocketActivity extends Activity { public static String SOCKET_ADDRESS = "tiwlan0"; public static LocalSocketAddress.Namespace NAMESPACE = LocalSocketAddress.Namespace.ABSTRACT; // background threads use this Handler to post messages to // the main application thread private final Handler handler = new Handler(); public class NotificationRunnable implements Runnable { private String message = null; public void run() { if (message != null && message.length() > 0) { showNotification(message); } } /** * @param message the message to set */ public void setMessage(String message) { this.message = message; } } // post this to the Handler when the background thread notifies private final NotificationRunnable notificationRunnable = new NotificationRunnable(); public void showNotification(String message) { Toast.makeText(this, message+ " " + this.handler.toString(), Toast.LENGTH_LONG).show(); } class SocketListener extends Thread { private Handler handler = null; private NotificationRunnable runnable = null; public SocketListener(Handler handler, NotificationRunnable runnable) { this.handler = handler; this.runnable = runnable; this.handler.post(this.runnable); } /** * Show UI notification. * @param message */ private void showMessage(String message) { this.runnable.setMessage(message); this.handler.post(this.runnable); } @Override public void run() { //showMessage("DEMO: SocketListener started!"); try { //LocalServerSocket server = new LocalServerSocket(SOCKET_ADDRESS); LocalSocket receiver = new LocalSocket(); receiver.connect(new LocalSocketAddress(SOCKET_ADDRESS, NAMESPACE)); showMessage("test"); InputStream input = receiver.getInputStream(); while (true) { //LocalSocket receiver = server.accept(); if (receiver != null) { // simply for java.util.ArrayList int readed = input.read(); showMessage("input.read()"); int size = 0; int capacity = 0; byte[] bytes = new byte[capacity]; // reading while (readed != -1) { // java.util.ArrayList.Add(E e); capacity = (capacity * 3)/2 + 1; //bytes = Arrays.copyOf(bytes, capacity); byte[] copy = new byte[capacity]; System.arraycopy(bytes, 0, copy, 0, bytes.length); bytes = copy; bytes[size++] = (byte)readed; // read next byte readed = input.read(); } showMessage(new String(bytes, 0, size)); } } } catch (IOException e) { showMessage("test2"); Log.e("**************"+getClass().getName(), e.getMessage()); //showMessage(e.toString()); } } } public static void writeSocket(String message) throws IOException { //LocalSocket sender = new LocalSocket(); //sender.connect(new LocalSocketAddress(SOCKET_ADDRESS, NAMESPACE)); //sender.getOutputStream().write(message.getBytes()); //sender.getOutputStream().close(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new SocketListener(this.handler, this.notificationRunnable).start(); Button send1 = (Button)findViewById(R.id.send_1_button); send1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { writeSocket("logoff"); } catch (IOException e) { Log.e(getClass().getName(), e.getMessage()); } } }); } } 2010/2/19 Aäron Jansen (Gmail) <aaron.jan...@gmail.com> Hi, (I'm new to posting questions on mailing lists. Suggestions on good posting behaviour are appreciated. :) ) FYI: I've also posted this issue on the Android Development Google Group. This is what I'm trying to achieve: I would like to write an Android app that is capable of talking to wpa_supplicant. More specifically, I would like to connect to a WPA2-EAP secured network (with authentication methods TTLS / PEAP / TLS), but since the device will be used by several users, the user credentials will be supplied by the user in my app, instead of by wpa_suplicant.conf. I don't want to write my own supplicant software, I would like to be able to communicate with it. (I am able to connect to the network when I provide the user credentials as well in the /data/misc/wifi/ wpa_supplicant.conf file) I've looked at several solutions and their problems, and I would like some advice on them. Maybe I've overlooked something: - Solution 1: Using the Android Wifi API. Problem: The Android WiFi API doesn't seem to support TTLS / PEAP / TLS. Strange other thing is: It appears to support LEAP, but I can't find a way to supply the user credentials to the WifiConfiguration. - Solution 2: Letting the app write to /data/misc/wifi/ wpa_supplicant.conf and then reassociating. Problem: I understand from the API that apps can only write to their own private space or the external SD store. I've also tried writing to a file with the Terminal Emulator app. This doesn't work. I can only write wpa_supplicant.conf in the adb shell with root acces. - Solution 3: Talking directly to the control interface of wpa_suplicant using Unix domain sockets. I found that the Android API supplies us with the LocalSocket class for this. However, I have no idea how to cummunicate with the wpa_supplicant control interface domain socket. (I will also post this on a wpa_supplicant forum). - Solution 4: Using java.lang.Runtime and .Process for running wpa_cli and communicating with it. Problem: I expect there will be Manifest.permission conflicts. - Solution 5: Another option might be to use Android NDK / JNI to be able to use the helper functions in c that wpa_supplicant provides. Problem: This might be a solution, but it seems to me that it complicates matters a lot. And I also wonder if there might be some Manifest.permission conflicts. - Solution 6: Finding some open source Java supplicant code and adapting this. Problem: I haven't found it yet. (My C skills aren't so good, and it needs to work on Android). I really need some help on this. Is there somebody with some more experience on this topic? I hope somebody would be able to enlighten me by providing some answers or pointers on where to look. Any help would be greatly appreciated. Thanks in advance, a2ronus -- Met vriendelijke groet, Aäron Jansen -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en