I know similar questions are asked but the answers didn't work for me. I tried this answer but it throws null pointer exception. I also saw this answer but WifiP2pManager does not have any property or method that returns device name.
Can anyone please help?
I basically want to show user their device name and let them change it if they want to set custom name.
Thanks.
If you're still looking for the answer, here's how:
Identify own device name
This becomes available upon receiving the WIFI_P2P_THIS_DEVICE_CHANGED_ACTION intent in your broadcast receiver. Simply use the deviceName member variable like so:
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
WifiP2pDevice self = (WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
// Now self.deviceName gives you own device name
} else if(WifiP2pManager.WIFI_P2P...) {
...
2. Change own device name
There's no method to change the device name using the WifiP2pManager as per the develper docs, and although a public setDeviceName() method exists in the source code, you can't call it on your object (probably to keep devs from calling it on an object representing a nearby peer device). What worked for me was to obtain a Method object representing said method and invoking it on my WifiP2pManager instance:
private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
...
public void changeDeviceName(String deviceNewName) {
try {
Method method = manager.getClass().getMethod("setDeviceName", WifiP2pManager.Channel.class, String.class, WifiP2pManager.ActionListener.class);
method.invoke(manager, channel, deviceNewName, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(MainActivity.this, "Name successfully changed", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(int reason) {
Toast.makeText(MainActivity.this, "Request failed: " + reason, Toast.LENGTH_SHORT).show();
Log.d(TAG, "Name change failed: " + reason);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
Alternatively, users can rename their device manually from the advanced WiFi settings (Preferences > Advanced > WiFi Direct > Configure Device),
EDIT: Starting with Pie, use of non-SDK interfaces (essentially classes, variables or methods marked with #hide, which you access using reflection) is being restricted and will eventually be disallowed. The above method is currently greylisted (which means support for reflecting it might be removed in the future). Read up more here: https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces
Related
I'm working on a project that improves Automation Test for Android's App. What I want to do is very "easy": I have this very simple SIP Client with a basic UI and developed just reading the API guides on the android developer website (https://developer.android.com/guide/topics/connectivity/sip.html) that receives and makes SIP calls.
I need to control remotely this app from my PC, connected at the same local network or the same wifi, by sending commands or similar (without interact with the phone) to the app itslef running normally on my phone.For a specific example I posted the method initiateCall() that calls sipAddress(in the app, sipAddress is taken from a Text Box), what I want to do is:
Starting the app on my phone
calling the method initiateCall() from my pc giving a sipAddress as a parameter (I must not use the UI from the app running, that's why I need to give the sipAddress)
check if an outgoing call starts from the app running on my phone
I thought that the solution must be something about web-services,but I don't have any better ideas and i don't know how to start and where to start solving this problem,that's why i need you help.
public void initiateCall() {
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// set up the listener for outgoing calls
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
updateStatus(call, 2);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Call End");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress,
listener, 30);
} catch (Exception e) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
You could do it REST API style. You would need to set up a minimalistic webserver.
If you access for example the url phoneip/ctrl/makecall?number=yournumber a serverside method us called if set up correctly. Then you can call you method and use the GET or POST variables as arguments.
You would have to look into Java Webserver Libraries/Frameworks. You can pick a lightweight one for that purpose. For example this one.
You could then also add security features (authentification to protect it) quite easily.
Example with sparkjava
import static spark.Spark.*;
....
get("/ctrl/makecall", (request, response) -> {
String phonenum = request.queryParams("number"); //may not be accurate; you have to determine the GET variable called "number" in that case; you can rename it; see docs!!!
//call your method with proper arguments
});
I am trying to connect two device to each other by wifi direct. I set the group owner intent to 15, like this :
config.groupOwnerIntent = 15;
but it does not work at all. Also I try to remove all of previous groups that are saved in devices in case of having impact on GO selection.
All the time the other device is getting to be GO. Do you have any idea what could be the problem?
Basically if you would want other device to be Group owner, then use the CreateGroup function to make a group on that device.
The problem is that config.groupOwnerIntent = 15; works with same brands (for example, if both your devices are Samsungs). With different devices sometimes this bug appears.
Also it depends on your connection:
manager.connect(channel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
}
#Override
public void onFailure(int reason) {
Toast.makeText(context, "Connect failed. Retry.",
Toast.LENGTH_SHORT).show();
}
});
or
manager.createGroup(channel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// Device is ready to accept incoming connections from peers.
}
#Override
public void onFailure(int reason) {
Toast.makeText(WiFiDirectActivity.this, "P2P group creation failed. Retry.",
Toast.LENGTH_SHORT).show();
}
});
Your code doesn't help if you use the second one.
Having same problem with Samsung and Xiaomi now, always same group owner. If a test on both Samsungs everything is okay.
Wifi P2P service discovery is not behaving as expected. I am seeing intermittent issues where the DNSSD listeners are not called always and hence I have no clue of nearby devices running the same app. I am using the following two APIs - one to register a service to be discovered by other devices and the other to discover the nearby services running on other devices. Any idea if I am doing anything wrong here or is there some specific sequence of other android API calls that need to be made before I call these APIs to ensure that the listeners are always called whenever there is a new service registered or even if a service is registered before we call the API to discover the local services.
API to register a local service:
private void registerService() {
Map<String, String> values = new HashMap<String, String>();
values.put("name", "Steve");
values.put("port", "8080");
WifiP2pServiceInfo srvcInfo = WifiP2pDnsSdServiceInfo.newInstance(mMyDevice.deviceName, "_http._tcp", values);
manager.addLocalService(channel, srvcInfo, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Toast.makeText(WiFiDirectActivity.this, "Local service added successfully",
Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int reasonCode) {
Toast.makeText(WiFiDirectActivity.this, "Local service addition failed : " + reasonCode,
Toast.LENGTH_SHORT).show();
}
});
}
API to discover local services:
public void discoverService() {
manager.clearServiceRequests(channel, null);
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
#Override
/* Callback includes:
* fullDomain: full domain name: e.g "printer._ipp._tcp.local."
* record: TXT record data as a map of key/value pairs.
* device: The device running the advertised service.
*/
public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
Log.d(TAG, "DnsSdTxtRecord available -" + record.toString());
}
};
DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
#Override
public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice resourceType) {
Log.d(TAG, "onBonjourServiceAvailable " + instanceName);
}
};
manager.setDnsSdResponseListeners(channel, servListener, txtListener);
WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
manager.addServiceRequest(channel, serviceRequest, new ActionListener() {
#Override
public void onSuccess() {
// Success!
Log.d(TAG, "addServiceRequest success");
}
#Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG, "addServiceRequest failure with code " + code);
}
});
manager.discoverServices(channel, new ActionListener() {
#Override
public void onSuccess() {
// Success!
Log.d(TAG, "discoverServices success");
}
#Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
if (code == WifiP2pManager.P2P_UNSUPPORTED) {
Log.d(TAG, "P2P isn't supported on this device.");
} else {
Log.d(TAG, "discoverServices failure");
}
}
});
}
Note: manager & channel are initialized as
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);
WifiP2p (in general):
Some time ago I was developing an application with a pretty complex network connectivity system based on WifiP2p with Service Broadcasting/Discovery. And based on that experience I already wrote few posts here on SO about how difficult, wearing and problematic that is. Here are two of them (they are quite full of the inside knowledge I acquired about WifiP2p with Service Discovery, and WifiP2p itself):
Why is discovering peers for Android WifiDirect so unreliable
Wi-fi P2P. Inform all peers available of some event
I would advise you to read both of my answers (even though they are focused a bit more on the WifiP2p itself). They should give you some perspective on the things you should be looking for when working with the WifiP2p Service Discovery.
I can easily say that if you want to build an efficient, relatively reliable and robust WifiP2p connection system (especially with Service Discovery), you will have to work your ass off.
WifiP2p Service Discovery:
To better answer your exact question, I will tell you what I did (different from you) to make my Service Discovery work pretty reliably.
1. Broadcasting Service:
First of all: before registering your Service (with addLocalService method) you should use the WifiP2pManager's clearLocalServices method. And it is important, that you should only call addLocalService if the listener passed in the clearLocalServices returned with the onSuccess callback.
Although this sets up the broadcasting pretty nicely, I found that other nodes were not always able to detect the broadcasted service (especially when those nodes weren't already actively detecting services at the moment of registering your local Service - but they "joined" later). I couldn't find a way to fix this issue 100% reliably. And believe me I was trying probably everything WifiP2p-related. And no, the clearLocalServices-addLocalService sequence wasn't really giving satisfying results. Or more so: doing something different was working much better. What I decided to do, was after I successfully added local service (onSuccess callback from addLocalService), I started a Thread that would periodically call WifiP2pManager's method discoverPeers. That seemed to be forcing to rebroadcast all the service information.
So... basically the base of your broadcasting code should look more-less like this (bare in mind that every single piece of code I will post here is stripped-off of all "checks" if the network connectivity system is in the right state, you should design them yourself to fit your solution the best):
public void startBroadcastingService(){
mWifiP2pManager.clearLocalServices(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
mWifiP2pManager.addLocalService(mWifiP2pChannel, mWifiP2pServiceInfo,
new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
// service broadcasting started
mServiceBroadcastingHandler
.postDelayed(mServiceBroadcastingRunnable,
SERVICE_BROADCASTING_INTERVAL);
}
#Override
public void onFailure(int error) {
// react to failure of adding the local service
}
});
}
#Override
public void onFailure(int error) {
// react to failure of clearing the local services
}
});
}
where the mServiceBroadcastingRunnable should be:
private Runnable mServiceBroadcastingRunnable = new Runnable() {
#Override
public void run() {
mWifiP2pManager.discoverPeers(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
}
#Override
public void onFailure(int error) {
}
});
mServiceBroadcastingHandler
.postDelayed(mServiceBroadcastingRunnable, SERVICE_BROADCASTING_INTERVAL);
}
};
2. Discovering Service:
For the discovering of your service I used similar approach. Both with the setting up the discovering, and with trying to force "rediscovery" of services.
Setting up was performed with the sequence of the following three WifiP2pManager's methods:
removeServiceRequest, addServiceRequest, discoverServices
They were called in this exact order and a particular method (second or the third one to be exact) has been called only after the previous one had "returned" with the onSuccess callback.
The rediscovery of services was being performed with the intuitive method (just by repeating the mentioned sequence: removeServiceRequest -> addServiceRequest -> discoverServices).
The base of my code looked more-less like this (to start Service Discovery I would first call prepareServiceDiscovery() and then startServiceDiscovery()):
public void prepareServiceDiscovery() {
mWifiP2pManager.setDnsSdResponseListeners(mWifiP2pChannel,
new WifiP2pManager.DnsSdServiceResponseListener() {
#Override
public void onDnsSdServiceAvailable(String instanceName,
String registrationType, WifiP2pDevice srcDevice) {
// do all the things you need to do with detected service
}
}, new WifiP2pManager.DnsSdTxtRecordListener() {
#Override
public void onDnsSdTxtRecordAvailable(
String fullDomainName, Map<String, String> record,
WifiP2pDevice device) {
// do all the things you need to do with detailed information about detected service
}
});
mWifiP2pServiceRequest = WifiP2pDnsSdServiceRequest.newInstance();
}
private void startServiceDiscovery() {
mWifiP2pManager.removeServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
mWifiP2pManager.addServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
mWifiP2pManager.discoverServices(mWifiP2pChannel,
new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
//service discovery started
mServiceDiscoveringHandler.postDelayed(
mServiceDiscoveringRunnable,
SERVICE_DISCOVERING_INTERVAL);
}
#Override
public void onFailure(int error) {
// react to failure of starting service discovery
}
});
}
#Override
public void onFailure(int error) {
// react to failure of adding service request
}
});
}
#Override
public void onFailure(int reason) {
// react to failure of removing service request
}
});
}
the mServiceDiscoveringRunnable was just:
private Runnable mServiceDiscoveringRunnable = new Runnable() {
#Override
public void run() {
startServiceDiscovery();
}
};
All this made my system work quite well. It wasn't perfect yet, but with the lack of documentation on this subject I think I couldn't do much more to improve it.
If you test this approach, be sure to tell me how it works for you (or if it works for you ;) ).
if the problem is the detection of the service i believe that crearing group is the best way to make the device and service detectable but the if created group in the all devices then you cannot connect in direct.
but as wifi network.
i do it every day and it works.
When a user changes his/her privacy settings through AppOps (e.g. denying an application access to phone contacts), AppOpsManager sends to anyone who listens what the users have changed (i.e. the package name and the operation (e.g. Read contacts)).
So I wrote a listener to do so. However, we the user make only one change, I receive too many duplicate events (e.g. 10 events that the user decided to deny Angry Bird access to his/her location) and then the app crashes.
Here is my code to register listners for each pair of package & operation:
public void startWatchingOperations(AppOpsManager appOps, List<AppOpsManager.PackageOps> opsforapps) {
SharedPreferences myAppListnerPreferences = getSharedPreferences(APP_OPS_PREFERENCES, Activity.MODE_PRIVATE);
for (AppOpsManager.PackageOps o:opsforapps) {
List<OpEntry> opEntry = o.getOps();
//if I already assigned a listener to this pari of package & operation, then skip
if (myAppListnerPreferences.getBoolean(o.getPackageName(), false)==false) {
for (OpEntry entry:opEntry) {
//for each pair of package & operation, assign a new listener
ChangePrivacySettingsListener opsListner = new ChangePrivacySettingsListener(getApplicationContext());
appOps.startWatchingMode(entry.getOp(),o.getPackageName(),opsListner);
}
myAppListnerPreferences.edit().putBoolean(o.getPackageName(), true).apply();
}
}
}
Here is a snippet of the listener
public class ChangePrivacySettingsListener implements AppOpsManager.Callback {
public void opChanged(int op, String packageName) {
AppOpsManager appOps= (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
PackageManager pkg = context.getPackageManager();
try {
//this is an object to store the event: package name,
// the operation that has been changed, & time stamp
PrivacySetting privacySetting = new PrivacySetting();
privacySetting.setPackageName(packageName);
privacySetting.setOperation(OPERATIONS_STRINGS[op]);
privacySetting.setDecisionTime(Calendar.getInstance(TimeZone.getDefault()).getTimeInMillis());
privacySetting.setUserId(userId);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Her is the part of AppOpsManager.java that allows me to listen to user's changes.
public class AppOpsManager {
final HashMap<Callback, IAppOpsCallback> mModeWatchers
= new HashMap<Callback, IAppOpsCallback>();
public void startWatchingMode(int op, String packageName, final Callback callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb == null) {
cb = new IAppOpsCallback.Stub() {
public void opChanged(int op, String packageName) {
callback.opChanged(op, packageName);
}
};
mModeWatchers.put(callback, cb);
}
try {
mService.startWatchingMode(op, packageName, cb);
} catch (RemoteException e) {
}
}
}
I double checked to ensure that I've never assigned more than one listener to each pair of package & operation.
I would appreciate hints about potential causes.
Here is a link to AppOpsManager.java
Try moving the deceleration of ChangePrivacySettingsListener opsListner to be out side of the for block:
public void startWatchingOperations(AppOpsManager appOps, List<AppOpsManager.PackageOps> opsforapps) {
ChangePrivacySettingsListener opsListner;
SharedPreferences myAppListnerPreferences = getSharedPreferences(APP_OPS_PREFERENCES, Activity.MODE_PRIVATE);
for (AppOpsManager.PackageOps o:opsforapps) {
List<OpEntry> opEntry = o.getOps();
//if I already assigned a listener to this pari of package & operation, then skip
if (myAppListnerPreferences.getBoolean(o.getPackageName(), false)==false) {
for (OpEntry entry:opEntry) {
//for each pair of package & operation, assign a new listener
opsListner = new ChangePrivacySettingsListener(getApplicationContext());
appOps.startWatchingMode(entry.getOp(),o.getPackageName(),opsListner);
}
myAppListnerPreferences.edit().putBoolean(o.getPackageName(), true).apply();
}
}
}
And please let me know what happened?
Just in case this is helpful to someone, up to at least Android Oreo, calling AppOpsManager.startWatchingMode(op, packageName, callback) will cause callback to be invoked when the setting is changed (1) for the op with any package, AND (2) for any AppOps setting changes with packageName. This can be seen from the AppOpsService.java source, particularly AppOpsService.startWatchingMode() which registers the callback, AppOpsService.setMode() which calls the callback when the AppOps setting is changed.
For example, if you register a callback with startWatchingMode(appOps1, package1, callback) and startWatchingMode(appOps2, package1, callback),
when there is a change in the setting for appOps3 for package1, the callback will be called twice since you have registered for package1 two times. If there is a change in appOps1 for package1, the callback will be invoked 3 times, because you have registered once for appOps1, and twice for package1.
The solution is to register either for the set of AppOps you are interested in (without duplications), with the packageName parameter set to null, or register for the set of packages you are interested in, with op parameter set to AppOpsManager.OP_NONE.
Also you need to ensure that all listeners are unregistered (e.g. in onDestroy of your activity) using stopWatchingMode. Otherwise, the callback entries will accumulate across Activity lifecycles (until the app is terminated) and you will start getting duplicates. This also means that you should keep references to all the listeners created.
How to pair a Bluetooth Low Energy(BLE) device with Android to read encrypted data.
Using the information in the Android BLE page, I am able to discover the device, connect to it, discover services and read un-encrypted characteristics.
When I try to read an encrypted characteristic (one that will cause iOS to show a popup asking to pair and then complete the read) I am getting an error code 5, which corresponds to Insufficient Authentication.
I am not sure how to get the device paired or how to provide the authentication information for the read to complete.
I toyed with BluetoothGattCharacteristics by trying to add descriptors, but that did not work either.
Any help is appreciated!
When you get the GATT_INSUFFICIENT_AUTHENTICATION error, the system starts the bonding process for you. In the example below I'm trying to enable notifications and indications on glucose monitor. First I'm enabling the notifications on Glucose Measurement characteristic which can cause the error to appear.
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
if (GM_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid())) {
mCallbacks.onGlucoseMeasurementNotificationEnabled();
if (mGlucoseMeasurementContextCharacteristic != null) {
enableGlucoseMeasurementContextNotification(gatt);
} else {
enableRecordAccessControlPointIndication(gatt);
}
}
if (GM_CONTEXT_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid())) {
mCallbacks.onGlucoseMeasurementContextNotificationEnabled();
enableRecordAccessControlPointIndication(gatt);
}
if (RACP_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid())) {
mCallbacks.onRecordAccessControlPointIndicationsEnabled();
}
} else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) {
// this is where the tricky part comes
if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_NONE) {
mCallbacks.onBondingRequired();
// I'm starting the Broadcast Receiver that will listen for bonding process changes
final IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mContext.registerReceiver(mBondingBroadcastReceiver, filter);
} else {
// this situation happens when you try to connect for the second time to already bonded device
// it should never happen, in my opinion
Logger.e(TAG, "The phone is trying to read from paired device without encryption. Android Bug?");
// I don't know what to do here
// This error was found on Nexus 7 with KRT16S build of Andorid 4.4. It does not appear on Samsung S4 with Andorid 4.3.
}
} else {
mCallbacks.onError(ERROR_WRITE_DESCRIPTOR, status);
}
};
Where the mBondingBroadcastReceiver is:
private BroadcastReceiver mBondingBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
final int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);
Logger.d(TAG, "Bond state changed for: " + device.getAddress() + " new state: " + bondState + " previous: " + previousBondState);
// skip other devices
if (!device.getAddress().equals(mBluetoothGatt.getDevice().getAddress()))
return;
if (bondState == BluetoothDevice.BOND_BONDED) {
// Continue to do what you've started before
enableGlucoseMeasurementNotification(mBluetoothGatt);
mContext.unregisterReceiver(this);
mCallbacks.onBonded();
}
}
};
Remember to unregister the broadcast receiver when exiting the activity. It may have not been unregistered by the receicver itself.
You might need to check the Kernel smp.c file, which method of paring it invoke for paring. 1) passkey 2)Just work or etc . i guess if it will be able to invoke MIMT and passkey level of security , there will not be any authentication issue. Make sure all flags is set to invoke the SMP passkey methods. track by putting some print in smp.c file.
A solution which works in ICS : with btmgmt tool in android and hooking it in encryption APIs. with passkey or any other methods. it works. You might need to add the passkey APIs in btmgmt from latest bluez code.
i think new android 4.4 provide pairing method. same problem already i am facing so wait for update and hope over problem solved createBond() method .
http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#setPairingConfirmation%28boolean%29