简体   繁体   中英

SSLException when connecting with Microsoft Translator API

I have been trying to connect my Android app with Microsoft Translator API and I have already registered my app in the Windows Azure Marketplace. But when I am running my app I have been constantly getting an IOException as I open my app.

04-17 21:18:15.661: E/TranslateTask(274): IOException
04-17 21:18:15.661: E/TranslateTask(274): javax.net.ssl.SSLException: Not trusted server certificate
04-17 21:18:15.661: E/TranslateTask(274):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371)
04-17 21:18:15.661: E/TranslateTask(274):   at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168)
04-17 21:18:15.661: E/TranslateTask(274):   at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:399)
04-17 21:18:15.661: E/TranslateTask(274):   at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:147)
04-17 21:18:15.661: E/TranslateTask(274):   at ac.lk.iit.androidtranslatorproject.TranslateActivity$GetAccessTokenTask.doInBackground(TranslateActivity.java:212)
04-17 21:18:15.661: E/TranslateTask(274):   at ac.lk.iit.androidtranslatorproject.TranslateActivity$GetAccessTokenTask.doInBackground(TranslateActivity.java:1)
04-17 21:18:15.661: E/TranslateTask(274):   at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-17 21:18:15.661: E/TranslateTask(274):   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
04-17 21:18:15.661: E/TranslateTask(274):   at java.util.concurrent.FutureTask.run(FutureTask.java:137)
04-17 21:18:15.661: E/TranslateTask(274):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
04-17 21:18:15.661: E/TranslateTask(274):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
04-17 21:18:15.661: E/TranslateTask(274):   at java.lang.Thread.run(Thread.java:1096)
04-17 21:18:15.661: E/TranslateTask(274): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
04-17 21:18:15.661: E/TranslateTask(274):   at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)
04-17 21:18:15.661: E/TranslateTask(274):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)
04-17 21:18:15.661: E/TranslateTask(274):   ... 11 more
04-17 21:18:15.661: E/TranslateTask(274): Caused by: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
04-17 21:18:15.661: E/TranslateTask(274):   at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:149)
04-17 21:18:15.661: E/TranslateTask(274):   at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202)
04-17 21:18:15.661: E/TranslateTask(274):   at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164)
04-17 21:18:15.661: E/TranslateTask(274):   ... 12 more

Further, the following are the related files to the application.

TranslateActivity.java

package ac.lk.iit.androidtranslatorproject;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

public class TranslateActivity extends Activity {
    private static final String TAG = "TranslateTask";
    private Spinner fromSpinner;
    private Spinner toSpinner;
    private EditText origText;
    private TextView transText;
    private Button transButton;
    private String fromLang;
    private String toLang;
    private TextWatcher textWatcher;
    private OnItemSelectedListener itemListener;
    private OnClickListener buttonListener;
    // needed to make translate requests to Microsoft
    private String accessToken;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_translate);
        findViews();
        setAdapters();
        setListeners();
        // get the access token from Microsoft
        new GetAccessTokenTask().execute();
    }

    private void findViews() {
        fromSpinner = (Spinner) findViewById(R.id.from_language);
        toSpinner = (Spinner) findViewById(R.id.to_language);
        origText = (EditText) findViewById(R.id.original_text);
        transText = (TextView) findViewById(R.id.translated_text);
        transButton = (Button) findViewById(R.id.translate_button);
    }

    /** Define data source for the spinners */
    private void setAdapters() {
        // Spinner list comes from a resource,
        // Spinner user interface uses standard layouts
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,R.array.languages,android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        fromSpinner.setAdapter(adapter);
        toSpinner.setAdapter(adapter);
        // Automatically select two spinner items
        fromSpinner.setSelection(8); // English (en)
        toSpinner.setSelection(25); // Spanish (es)
    }

    private void setListeners() {
        textWatcher = new TextWatcher() {
            public void beforeTextChanged(CharSequence s,int start, int count,int after) {
            }

            public void onTextChanged(CharSequence s,int start, int before,int count) {
                /*doTranslate2(origText.getText().toString().trim(),fromLang, toLang); */
            }

            public void afterTextChanged(Editable s) {
            }};
            origText.addTextChangedListener(textWatcher);
            itemListener = new OnItemSelectedListener() {
                public void onItemSelected(AdapterView parent, View v,int position, long id) {
                fromLang = getLang(fromSpinner);
                toLang = getLang(toSpinner);
                if (accessToken != null)
                    doTranslate2(origText.getText().toString().trim(), fromLang, toLang);
                }
                public void onNothingSelected(AdapterView parent) {
                    /* Do nothing */
                }};
                fromSpinner.setOnItemSelectedListener(itemListener);
                toSpinner.setOnItemSelectedListener(itemListener);
                buttonListener = new OnClickListener() {
                    public void onClick(View v) {
                    if (accessToken != null)
                        System.out.println(accessToken);
                        doTranslate2(origText.getText().toString().trim(), fromLang, toLang);
                    }};
                    transButton.setOnClickListener(buttonListener);
                }

                /** Extract the language code from the current spinner item */
            private String getLang(Spinner spinner) {
                String result = spinner.getSelectedItem().toString();
                int lparen = result.indexOf('(');
                int rparen = result.indexOf(')');
                result = result.substring(lparen + 1, rparen);
                return result;
            }

            private void doTranslate2(String original,String from, String to) {
                if (accessToken != null)
                    new TranslationTask().execute(original, from, to);
            }

            private class TranslationTask extends AsyncTask<String,Void,String> {
                protected void onPostExecute(String translation) {
                    transText.setText(translation);
                }
                protected String doInBackground(String... s) {
                    HttpURLConnection con2 = null;
                    String result = getResources().getString(
                    R.string.translation_error);
                    String original = s[0];
                    String from = s[1];
                    String to = s[2];
                    try {
                        // Read results from the query
                        BufferedReader reader;
                        String uri = "http://api.microsofttranslator.com" + "/v2/Http.svc/Translate?text=" + URLEncoder.encode(original) +"&from=" + from + "&to=" + to;
                        URL url_translate = new URL(uri);
                        String authToken = "Bearer" + " " + accessToken;
                        con2 = (HttpURLConnection) url_translate.
                        openConnection();
                        con2.setRequestProperty("Authorization", authToken);
                        con2.setDoInput(true);
                        con2.setReadTimeout(10000 /* milliseconds */);
                        con2.setConnectTimeout(15000 /* milliseconds */);
                        reader = new BufferedReader(new InputStreamReader(
                        con2.getInputStream(), "UTF-8"));
                        String translated_xml = reader.readLine();
                        reader.close();
                        /* translated_xml now contains the following XML:
                        <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hola</string> */
                        // parse the XML returned
                        DocumentBuilder builder = DocumentBuilderFactory.
                        newInstance().newDocumentBuilder();
                        Document doc = builder.parse(new InputSource(new StringReader(translated_xml)));
                        NodeList node_list = doc.getElementsByTagName("string");
                        NodeList l = node_list.item(0).getChildNodes();
                        Node node;
                        String translated = null;
                        if (l != null && l.getLength() > 0) {
                            node = l.item(0);
                            translated = node.getNodeValue();
                        }
                        if (translated != null)
                            result = translated;
                        } catch (IOException e) {
                            Log.e(TAG, "IOException", e);
                        } catch (SAXException e) {
                            e.printStackTrace();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        finally {
                            if (con2 != null) {
                                con2.disconnect();
                            }
                        }
                        return result;
                    }
                }

            private class GetAccessTokenTask extends AsyncTask<Void, Void, String> {
                protected void onPostExecute(String access_token) {
                    accessToken = access_token;
                }
                protected String doInBackground(Void... v) {
                    String result = null;
                    HttpURLConnection con = null;
                    String clientID = "<client id>";
                    String clientSecret = "<client secret>";
                    String strTranslatorAccessURI ="https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
                    String strRequestDetails = "grant_type=" + "client_credentials&client_id=" + URLEncoder.encode(clientID) + "&client_secret="+ URLEncoder.encode(clientSecret) + "&scope=http://api.microsofttranslator.com";

                    try {
                        URL url = new URL(strTranslatorAccessURI);
                        con = (HttpURLConnection) url.openConnection();
                        con.setReadTimeout(10000 /* milliseconds */);
                        con.setConnectTimeout(15000 /* milliseconds */);
                        con.setRequestMethod("POST");
                        con.setDoInput(true);
                        con.setDoOutput(true);
                        con.setChunkedStreamingMode(0);
                        // Start the query
                        con.connect();
                        OutputStream out = new BufferedOutputStream(con.getOutputStream());
                        out.write(strRequestDetails.getBytes());
                        out.flush();
                        // Read results from the query
                        BufferedReader reader = new BufferedReader(
                        new InputStreamReader(con.getInputStream(), "UTF-8"));
                        String payload = reader.readLine();
                        reader.close();
                        out.close();
                        /* payload now contains JSON attribute value pairs:
                        {"token_type":"http://schemas.xmlsoap.org/ws/2009/
                        11/swt-token-profile-1.0","access_token":"....",
                        "expires_in":"600","scope":
                        "http://api.microsofttranslator.com"} */
                        // Parse to get the access token
                        JSONObject jsonObject = new JSONObject(payload);
                        result = jsonObject.getString("access_token");
                    } catch (IOException e) {
                        Log.e(TAG, "IOException", e);
                    } catch (JSONException e) {
                        Log.e(TAG, "JSONException", e);
                    } finally {
                        if (con != null) {
                            con.disconnect();
                        }
                    }
                    return result;
                }
            }
}

I have not mentioned the client id and the secret but the error seems to be thrown out from doInBackground method and to be precise the point of method call connect().

The following is the layout page of the activity.

activity_translate.xml

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TableLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:stretchColumns="1"
        android:padding="10dip">
        <TableRow>
            <TextView android:text="@string/from_text" />
            <Spinner android:id="@+id/from_language" />
        </TableRow>
        <EditText
            android:id="@+id/original_text"
            android:hint="@string/original_hint"
            android:padding="10dip"
            android:textSize="18sp" />
        <TableRow>
            <TextView android:text="@string/to_text" />
            <Spinner android:id="@+id/to_language" />
        </TableRow>
        <TextView
            android:id="@+id/translated_text"
            android:padding="10dip"
            android:textSize="18sp" />
        <Button
            android:id="@+id/translate_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Translate"
            android:layout_gravity="center" />
    </TableLayout>
</ScrollView>

I have also made sure permission to use internet is enabled in app manifest file.

I would be grateful if somebody can help me out to find the solution for this issue since this is a totally new area to me and I would appreciate if the reason for the above error is also clearly explained. Please pardon me for any for any mistakes since as mentioned before I am new to this area of study.

I don't know if third-party libs can help in this case, but using OkHTTP library helped me to fix some errors concerning SSL certificates that rarely appeared in my app. https://github.com/square/okhttp

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM