Created
September 9, 2015 07:13
-
-
Save proycon/16439d5b6d80b68f73ee to your computer and use it in GitHub Desktop.
Home automation android app with speech to text through google API, with self-signed certificate cause I'm cheap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.anaproy.homecontrol; | |
| import java.util.ArrayList; | |
| import android.app.Activity; | |
| import android.content.Intent; | |
| import android.os.Bundle; | |
| import android.speech.RecognizerIntent; | |
| import android.view.View; | |
| import android.view.View.OnClickListener; | |
| import android.widget.TextView; | |
| import android.widget.Toast; | |
| import android.content.Context; | |
| import android.net.ConnectivityManager; | |
| import android.net.NetworkInfo; | |
| import android.net.http.SslError; | |
| import android.net.http.SslError; | |
| import java.io.InputStream; | |
| import java.io.InputStreamReader; | |
| import java.io.BufferedInputStream; | |
| import java.io.FileInputStream; | |
| import java.net.URL; | |
| import java.net.HttpURLConnection; | |
| import java.net.Authenticator; | |
| import java.net.PasswordAuthentication; | |
| import javax.net.ssl.HttpsURLConnection; | |
| import javax.net.ssl.SSLContext; | |
| import javax.net.ssl.TrustManager; | |
| import javax.net.ssl.TrustManagerFactory; | |
| import javax.net.ssl.HostnameVerifier; | |
| import javax.net.ssl.SSLSession; | |
| import java.security.KeyStore; | |
| import java.security.cert.CertificateFactory; | |
| import java.security.cert.Certificate; | |
| import java.security.cert.X509Certificate; | |
| import java.net.URLEncoder; | |
| import java.net.MalformedURLException; | |
| import java.lang.Exception; | |
| import java.io.IOException; | |
| import java.net.SocketTimeoutException; | |
| import android.util.Log; | |
| import android.os.AsyncTask; | |
| import android.webkit.WebView; | |
| import android.webkit.WebViewClient; | |
| import android.webkit.SslErrorHandler; | |
| import android.webkit.HttpAuthHandler; | |
| public class MainActivity extends Activity implements OnClickListener { | |
| protected static final int REQUEST_OK = 1; | |
| private class HomeControlWebViewClient extends WebViewClient { | |
| @Override | |
| public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { | |
| handler.proceed(); // Ignore SSL certificate errors!! (we are self-signed) | |
| } | |
| @Override | |
| public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { | |
| handler.proceed("USERNAME", "PASSWORD"); | |
| } | |
| } | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| setContentView(R.layout.activity_main); | |
| WebView webview = (WebView) findViewById(R.id.webview); | |
| webview.setWebViewClient(new HomeControlWebViewClient()); | |
| webview.getSettings().setJavaScriptEnabled(true); | |
| webview.getSettings().setDomStorageEnabled(true); | |
| webview.getSettings().setBuiltInZoomControls(true); | |
| webview.getSettings().setUseWideViewPort(true); | |
| webview.getSettings().setMediaPlaybackRequiresUserGesture(false); | |
| webview.getSettings().setLoadWithOverviewMode(true); | |
| webview.loadUrl("https://home.anaproy.nl"); | |
| } | |
| @Override | |
| public void onClick(View v) { | |
| } | |
| @Override | |
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
| super.onActivityResult(requestCode, resultCode, data); | |
| if (requestCode==REQUEST_OK && resultCode==RESULT_OK) { | |
| ArrayList<String> speech2text = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); | |
| String text = speech2text.get(0); | |
| //((TextView)findViewById(R.id.text1)).setText(text); | |
| Toast.makeText(this, text, Toast.LENGTH_LONG).show(); | |
| ConnectivityManager connMgr = (ConnectivityManager) | |
| getSystemService(Context.CONNECTIVITY_SERVICE); | |
| NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); | |
| if (networkInfo != null && networkInfo.isConnected()) { | |
| new TransferTask().execute(text); | |
| } else { | |
| // display error | |
| Toast.makeText(this, "No network connection present", Toast.LENGTH_LONG).show(); | |
| } | |
| } | |
| } | |
| private class TransferTask extends AsyncTask<String, Void, String> { | |
| @Override | |
| protected String doInBackground(String... text) { | |
| return transfer(text[0]); | |
| } | |
| protected void onPostExecute(String response) { | |
| Toast.makeText(MainActivity.this, response, Toast.LENGTH_LONG).show(); | |
| } | |
| } | |
| private String transfer(String text) { | |
| String response = ""; | |
| SSLContext sslcontext; | |
| try { | |
| // Load CAs from an InputStream | |
| // (could be from a resource or ByteArrayInputStream or ...) | |
| CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |
| InputStream caInput = getResources().openRawResource(R.raw.anaproy2014); | |
| Certificate ca; | |
| try { | |
| ca = cf.generateCertificate(caInput); | |
| System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); | |
| } finally { | |
| caInput.close(); | |
| } | |
| // Create a KeyStore containing our trusted CAs | |
| String keyStoreType = KeyStore.getDefaultType(); | |
| KeyStore keyStore = KeyStore.getInstance(keyStoreType); | |
| keyStore.load(null, null); | |
| keyStore.setCertificateEntry("ca", ca); | |
| // Create a TrustManager that trusts the CAs in our KeyStore | |
| String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); | |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); | |
| tmf.init(keyStore); | |
| // Create an SSLContext that uses our TrustManager | |
| sslcontext = SSLContext.getInstance("TLS"); | |
| sslcontext.init(null, tmf.getTrustManagers(), null); | |
| } catch (Exception e) { | |
| Log.d("HomeControl", Log.getStackTraceString(e)); | |
| response = "Error setting up SSL"; | |
| return response; | |
| } | |
| // fetch data | |
| String baseurl = "https://home.anaproy.nl/voice/process/"; | |
| String strUrl = baseurl + URLEncoder.encode(text); | |
| try { | |
| // Create an HostnameVerifier that hardwires the expected hostname. | |
| // Note that is different than the URL's hostname: | |
| // example.com versus example.org | |
| HostnameVerifier hostnameVerifier = new HostnameVerifier() { | |
| @Override | |
| public boolean verify(String hostname, SSLSession session) { | |
| HostnameVerifier hv = | |
| HttpsURLConnection.getDefaultHostnameVerifier(); | |
| return hv.verify("anaproy.nl", session); | |
| } | |
| }; | |
| Authenticator.setDefault(new Authenticator() { | |
| protected PasswordAuthentication getPasswordAuthentication() { | |
| String username="USERNAME"; | |
| String password="PASSWORD"; | |
| return new PasswordAuthentication(username, password.toCharArray()); | |
| } | |
| }); | |
| URL url = new URL(strUrl); | |
| HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); | |
| conn.setHostnameVerifier(hostnameVerifier); | |
| conn.setSSLSocketFactory(sslcontext.getSocketFactory()); | |
| conn.setReadTimeout(10000 /* milliseconds */); | |
| conn.setConnectTimeout(15000 /* milliseconds */); | |
| conn.setRequestMethod("GET"); | |
| // Starts the query | |
| conn.connect(); | |
| int httpresponse = conn.getResponseCode(); | |
| if (httpresponse == 403) { | |
| //used when the server does not understand the user | |
| response = "Sorry, I don't understand that"; | |
| } else if (httpresponse != 200) { | |
| response = "Error relaying voice command, computer says no :("; | |
| } else { | |
| response = "ok!"; | |
| } | |
| conn.disconnect(); | |
| } catch (MalformedURLException e) { | |
| response = "Malformed URL: " + strUrl; | |
| } catch (SocketTimeoutException e) { | |
| response = "Connect to server timed out"; | |
| } catch (IOException e) { | |
| Log.d("HomeControl", Log.getStackTraceString(e)); | |
| response = "Unable to open connect to server"; | |
| } catch (Exception e) { | |
| Log.d("HomeControl", Log.getStackTraceString(e)); | |
| response = "Unknown error while connecting to server"; | |
| } | |
| return response; | |
| } | |
| //buttons | |
| public void backClick(View view) { | |
| WebView webview = (WebView) findViewById(R.id.webview); | |
| if (webview.canGoBack()) { | |
| webview.goBack(); | |
| } | |
| } | |
| public void speakClick(View view) { | |
| Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); | |
| i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US"); | |
| try { | |
| startActivityForResult(i, REQUEST_OK); | |
| } catch (Exception e) { | |
| Toast.makeText(this, "Error initializing speech to text engine.", Toast.LENGTH_LONG).show(); | |
| } | |
| } | |
| public void refreshClick(View view) { | |
| WebView webview = (WebView) findViewById(R.id.webview); | |
| webview.reload(); | |
| } | |
| //not in interface currently | |
| public void lightsOn(View view) { | |
| new TransferTask().execute("lights on"); | |
| } | |
| public void lightsOff(View view) { | |
| new TransferTask().execute("lights off"); | |
| } | |
| public void officelightOn(View view) { | |
| new TransferTask().execute("office light on"); | |
| } | |
| public void officelightOff(View view) { | |
| new TransferTask().execute("office light off"); | |
| } | |
| public void tvlightOn(View view) { | |
| new TransferTask().execute("tv light on"); | |
| } | |
| public void tvlightOff(View view) { | |
| new TransferTask().execute("tv light off"); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment