Good day,
I'm trying to connect to AWS IoT with android using its SDK, no problem with Android 7 and above. But there's a compatibility problem with below versions. This is detailed in this Issue. I tried using Paho as client library but I haven't been able to figure out how to use those certificates with the Socket factory. Any idea how can I use those certificates with some MQTT Client library?
In the Java SDK was pretty easy to connect and no problem at all, I didn't have to use a keystore for that. Why Android needs to use a keystore to manage those certificates?. Should I install those certificates in the security settings as well?
I have tried using this wrapper. But is quite confuse how it uses those keystores. It throws and exception as it can't create it. Using that wrapper I have been able make some modifications and make it run. But it doesn't trigger anything neither onFail or onSuccess.
This is what I have done:
The class SocketFactory can be found here
void MqttSetup() {
CLIENT = new MqttAndroidClient(getBaseContext(), BROKER, MqttClient.generateClientId());
MQTT_CONNECTION_OPTIONS = new MqttConnectOptions();
/**
* SSL broker requires a certificate to authenticate their connection
* Certificate can be found in resources folder /res/raw/
*/
SocketFactory.SocketFactoryOptions socketFactoryOptions = new SocketFactory.SocketFactoryOptions();
try {
socketFactoryOptions.withCaInputStream(getResources().openRawResource(R.raw.keystore));
MQTT_CONNECTION_OPTIONS.setSocketFactory(new SocketFactory(socketFactoryOptions));
} catch (IOException | NoSuchAlgorithmException | KeyStoreException | CertificateException | KeyManagementException | UnrecoverableKeyException e) {
e.printStackTrace();
}
}
void MqttConnect() {
try {
final IMqttToken token = CLIENT.connect(MQTT_CONNECTION_OPTIONS);
token.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
// We are connected
Log.d("mqtt:", "connected, token:" + asyncActionToken.toString());
subscribe(TOPIC, (byte) 1);
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Something went wrong e.g. connection timeout or firewall problems
Log.d("mqtt:", "not connected" + asyncActionToken.toString());
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
When I try to connect to the broker it seems that it can make a connection as it's registered in the Monitor of Aws IoT. But those listeners don't get triggered and there are no thrown exceptions. I thought that I might not be loading those certificates properly.
I have the next files downloaded from Aws IoT (not sure how to bind them in a keystore and access them):
certificate.pem.crt
private.pem.key
public.pem.key
Thanks.
Related
My situation:
I'm trying to create an android app using unity that has a server running, so I can call the service from a PC.
However, when I try to connect to the server I get the error message:
SocketException: No connection could be made because the target machine actively refused it.
System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP, Boolean requireSocketPolicy)
System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP)
System.Net.Sockets.TcpClient.Connect (System.Net.IPEndPoint remote_end_point)
System.Net.Sockets.TcpClient.Connect (System.Net.IPAddress[] ipAddresses, Int32 port)
Doing ping on the IP Address is fine, so the host is reachable, as far as I know android devices don't have firewalls, so my guess it is a problem with the port.
Currently I'm trying to run the service on port 9096, which works if I just run the application in the editor. Is this a valid port for android?
If not, what would be a valid one?
Do you have any other ideas on what the problem could be?
Thank you.
Additional info:
The device is Google Tango and I want to use Thrift to create a server and access the location of the device from a windows coomputer.
========================================================
UPDATE: included code for server and client
public void startServerService()
{
try
{
TangoService.Processor processor = new TangoService.Processor(this);
serverTransport = new TServerSocket(9096);
server = new TThreadPoolServer(processor, serverTransport);
Debug.Log("Starting the server...");
server.Serve();
}
catch (UnityException e)
{
Debug.Log(e);
}
}
void startClient()
{
try{
TTransport transport = new TSocket(ipAddress, 9096);
transport.Open ();
TProtocol protocol = new TBinaryProtocol(transport);
client=new TangoService.Client(protocol);
}
catch(UnityException e)
{
Debug.Log(e);
}
}
My project has been using Android Volley network framework for a long time, but recently I found a SSL 3.0 protocol bug published on the Internet.
I want to know how can I find out what's the TLS version my project used, and how to confirm whether the library is updated.
Here is my source code fragment:
HttpStack stack = new HurlStack();
Network network = new BasicNetwork(stack);
mHttpRequestQueue = new RequestQueue(new NoCache(), network);
mHttpRequestQueue.start();
I think the point is in HurlStack class, and it depends on org.apache.http package, but I can't figure out where TLS/SSL configuration is.
You may modify the version of TLS used in Volley by creating a custom HTTPStack and setting the stack in the Volley.newRequestQueue(context, httpStack) method in Volley.java. Although, you only need to do this for Android versions 16-19. Before v16, TLS 1.2 isn't supported and after v19, TLS 1.2 is enabled by default. So, you should focus on manually setting TLS to 1.2 for Android versions 16-19.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
try {
ProviderInstaller.installIfNeeded(getContext());
} catch (GooglePlayServicesRepairableException e) {
// Indicates that Google Play services is out of date, disabled, etc.
// Prompt the user to install/update/enable Google Play services.
GooglePlayServicesUtil.showErrorNotification(e.getConnectionStatusCode(), getContext());
// Notify the SyncManager that a soft error occurred.
syncResult.stats.numIOExceptions++;
return;
} catch (GooglePlayServicesNotAvailableException e) {
// Indicates a non-recoverable error; the ProviderInstaller is not able
// to install an up-to-date Provider.
// Notify the SyncManager that a hard error occurred.
syncResult.stats.numAuthExceptions++;
return;
}
HttpStack stack = null;
try {
stack = new HurlStack(null, new TLSSocketFactory());
} catch (KeyManagementException e) {
e.printStackTrace();
Log.d("Your Wrapper Class", "Could not create new stack for TLS v1.2");
stack = new HurlStack();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
Log.d("Your Wrapper Class", "Could not create new stack for TLS v1.2");
stack = new HurlStack();
}
requestQueue = Volley.newRequestQueue(context, stack);
} else {
requestQueue = Volley.newRequestQueue(context);
}
And then use a TLSSocketFactory class which extends SSLSocketFactory like the one Florian Krauthan created here, where the v1.2 TLS protocol is enabled: https://gist.github.com/fkrauthan/ac8624466a4dee4fd02f#file-tlssocketfactory-java
On Android the used TLS version mostly depends on the used Android version.
Apache Volley bases on Apache Http Client which bases on HttpsUrlConnection, therefore the standard SSL/TLS SSLSocketFactory is used.
On Android below 4.3 usually only SSLv3 and TLS 1.0 are supported. On later versions TLS 1.1 and 1.2 are often supported but disabled.
Starting with Android 5 TLS 1.1 and TLS 1.2 are supported and enabled by default
#w3bshark's answer worked for me. But Before using that code, Make sure you include the code to update Security Provider. In my case, TLS didn't work until i update security provider. Following is the code to update it.
private void updateAndroidSecurityProvider() {
try {
ProviderInstaller.installIfNeeded(this);
} catch (GooglePlayServicesRepairableException e) {
Log.e("Test321", "PlayServices not installed");
} catch (GooglePlayServicesNotAvailableException e) {
Log.e("Test321", "Google Play Services not available.");
}
}
I'm trying to do a server-less app for IM. I use apple bonjour protocol to discover xmpp services. But once I get those I can't connect to my host (linux computer using pidgin + bonjour).
Here is my code (taken from here) :
public class Xmpp extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0)
{
ConnectionConfiguration connConfig =
new ConnectionConfiguration("192.168.0.11", 5298, "bonjour");
XMPPConnection connection = new XMPPConnection(connConfig);
try
{
// Connect to the server
connection.connect();
// Most servers require you to login before performing other tasks.
connection.login("grea08", "mypass");
// Start a new conversation with John Doe and send him a message.
Chat chat = connection.getChatManager().createChat("grea09#192.168.0.11", new MessageListener() {
public void processMessage(Chat chat, Message message) {
// Print out any messages we get back to standard out.
Log.v(getClass().getName(), "Received message: " + message);
}
});
chat.sendMessage("Howdy!");
} catch (XMPPException e)
{
// TODO Auto-generated catch block
Log.e(getClass().getName(), "Xmpp error !", e);
}
// Disconnect from the server
connection.disconnect();
return null;
}
}
I've got an XmppException "No response from server". I think that the host is not an XMPP server and we must use the protocol this way.
Smack and aSmack has no support for XEP-0174 (aka. link-local or serverless messaging). Jonas patches never made it into the trunk. The corresponding issue to track is SMACK-262.
Gibberbot open source project supports XMPP and Bonjour serverless communication.
It also can be installed from Google Play.
Perhaps you can check out its sources and extract the relevant code for your app. :-)
Try creating your XMPPConnection with a configuration:
ConnectionConfiguration config = new ConnectionConfiguration("192.189.0.11", port);
//Set optional configurations on the config object.
Connection connection = new XMPPConnection(config);
I would like to implement an application to receive a file from a Bluetooth device.
Before receiving, a notification will be raised to accept an incoming file request.
From there, i would like to activate "accept" and download the file automatically without raising an accept dialog when the user receive a second file from another Bluetooth paired device, without notification disturbance when the user launchs an application.
I developed an app that include this kind of task, and you can use BluetoothChat example.
You must set the secure flag to false:
`
boolean secure = false;
try {
if (secure) {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE);
} else {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
mmServerSocket = tmp;
}`
And then read the buffer from the InputStream that you can find in ConnectedThread:
while (true) {
try {
bytes = mmInStream.read(buffer);
/*write bytes in a file*/
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
BluetoothChatService.this.start();
break;
}
}
You can try using the Bluetooth socket connection to set a client server TCP like connection.
ON ROOTED DEVICES, You can just install only two apps on your phone to achieve your goal.
XPosed Installer
Auto-Accept
This way you hook System service.
import android.util.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial implements IXposedHookLoadPackage
{
private String TAG="TUTORIAL";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth"))
{
Log.i(TAG,"Not: "+lpparam.packageName);
return;
}
Log.i(TAG,"Yes "+lpparam.packageName);
findAndHookMethod("com.android.bluetooth.opp.BluetoothOppManager", lpparam.classLoader, "isWhitelisted", String.class,new XC_MethodHook() {
#Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.v(TAG,"HOOK DONE");
param.setResult(true); /* you can compare the sender address(String) with your computer and determine if you return true or just allow the original method to be called after this returns.*/
}
});
}
}
For more information, please visit my answer in SO.
I'll post some direct links here.
Links
Dropbox link of the auto accepting app
Dropbox link of the project files (zip)
Xposed apk site
Towelroot site to root your phone
Auto-Accept github repository
How can access to wss:// protocol in java ?
i use benkay / java-socket.io.client
but it's not support wss protocol.
i tried use SSLEngine. but it's very hard work.
how can connect to ssl in java ?
I tried change SocketChannel by SSLEngine. but it is not worked.
ssl channel is ok. but i can't wire this original websocket part.
this is source code.
client = SocketChannel.open(remote);
client.configureBlocking(false);
//client.connect(remote);
selector = Selector.open();
this.conn = new WebSocket(client, new LinkedBlockingQueue<ByteBuffer>(), this);
client.register(selector, SelectionKey.OP_READ);
try {
sslClient = new SSLClient(keyStore, storepass.toCharArray(), client);
sslClient.beginHandShake();
startClient()
} catch (Exception e) {
e.printStackTrace();
}
this point uncorret ?? i don't know .. not same the original websocket code.. may problem is this point. how can fix it ??
public void startClient()
{
try
{
while(true)
{
if(selector.select() <= 0)
{
continue;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while(it.hasNext())
{
SelectionKey key = (SelectionKey)it.next();
Log.e("key","key");
if(key.isReadable())
{
read(key);
}
it.remove();
}
}
}
catch(Exception e)
{
}
}
and SSLClient is http://rapidant.tistory.com/attachment/cfile25.uf#121346414D45B0960BD01B.zip
key store : change JKS to BKS, not problem.
how can wrap the SocketChannel ?
(Web browser it worked.)
You could check out my fork of the Autobahn WebSocket Library.
Secure WebSockets based upon Autobahn
You don't want to use SSLEngine on Android because it is broken.