У меня возникли проблемы с использованием одной из библиотек OAuth, которые я нашел в сети в своем приложении Scala для Android. Вместо того, чтобы найти способ использовать lib, я просто свернул свой собственный ... Не уверен, что он будет работать против linkedin (он хорошо работает с Yammer, который использует HTTPS). Ниже приведен соответствующий код, заметьте, я довольно новичок как в Android, так и в Scala, так что, возможно, есть лучшие способы сделать это.
Файл макета "R.layout.authorization" очень простой, содержит две кнопки и текстовое поле в RelativeLayout.
class Authorization extends Activity {
val client = new DefaultHttpClient()
val reqUrl = "https://www.yammer.com/oauth/request_token"
val authUrl = "https://www.yammer.com/oauth/authorize?oauth_token="
val accessUrl = "https://www.yammer.com/oauth/access_token"
override def onCreate(bundle:Bundle) = {
super.onCreate(bundle)
this.setContentView(R.layout.authorization)
val authButton = findViewById(R.id.authButton).asInstanceOf[Button]
val getCodeButton = findViewById(R.id.getCode).asInstanceOf[Button]
val prefs = getSharedPreferences(PreferenceFile(), 0)
if(prefs.contains("oauth_request_token")) {
authButton.setVisibility(View.VISIBLE)
}
setupListeners(authButton, getCodeButton)
}
private def getAuthVerifier() = {
val authVerifierBox:EditText = Authorization.this.findViewById(R.id.authVerifier).asInstanceOf[EditText]
if(authVerifierBox != null && authVerifierBox.getText() != null) {
authVerifierBox.getText().toString()
} else {
""
}
}
private def setupListeners(authButton:Button, getCodeButton:Button) = {
authButton.setOnClickListener(new View.OnClickListener() {
override def onClick(view:View) = {
retrieveAuthTokenAndSecret()
}
})
getCodeButton.setOnClickListener(new View.OnClickListener() {
override def onClick(view:View) = {
try {
// Retrieve a request token with an async task and then start the browser...
// Use of an implicit definition to convert tuple to an async task.
(() => {
// Task to perform
val reqPost = new HttpPost(reqUrl)
reqPost.setHeader("Authorization", OAuthHeaderBuilder(null,null,null))
reqPost.setHeader("Content-Type", "application/x-www-form-urlencoded")
val reqResp= client.execute(reqPost)
reqResp.getEntity()
},
(entity:HttpEntity) => {
// PostExecute handle result from task...
if(entity != null) {
val reader = new BufferedReader(new InputStreamReader(entity.getContent()))
val line = reader.readLine()
val (oauth_request_token, oauth_token_secret) = OAuthTokenExtractor(line)
// Store request tokens so they can be used when retrieving auth tokens...
val editor = getSharedPreferences(PreferenceFile(), 0).edit()
editor.putString("oauth_request_token", oauth_request_token)
editor.putString("oauth_token_secret", oauth_token_secret)
editor.commit()
// Start browser...
val intent = new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl + oauth_request_token))
startActivity(intent)
val authButton = findViewById(R.id.authButton).asInstanceOf[Button]
authButton.setVisibility(View.VISIBLE)
}
}).doInBackground()
} catch {
case e:Exception => Log.e("ERROR", "ERROR IN CODE:"+e.toString())
}
}
})
}
private def retrieveAuthTokenAndSecret() = {
val authVerifier = getAuthVerifier()
val accessPost = new HttpPost(accessUrl)
val prefs = getSharedPreferences(PreferenceFile(), 0)
val token = prefs.getString("oauth_request_token","")
val secret = prefs.getString("oauth_token_secret","")
accessPost.setHeader("Authorization", OAuthHeaderBuilder(token, secret, authVerifier))
accessPost.setHeader("Content-Type", "application/x-www-form-urlencoded")
val accessResp = client.execute(accessPost)
val entity = accessResp.getEntity()
if(entity != null) {
val reader = new BufferedReader(new InputStreamReader(entity.getContent()))
val builder = new StringBuilder()
val line = reader.readLine()
val (oauth_token, oauth_token_secret) = OAuthTokenExtractor(line)
val result = new Intent()
val editor = getSharedPreferences(PreferenceFile(), 0).edit()
editor.putString("oauth_token", oauth_token)
editor.putString("oauth_token_secret", oauth_token_secret)
editor.commit()
setResult(Activity.RESULT_OK, result)
finish()
}
}
}
OAuthHeaderBuilder в основном является копией примера кода Yammer oauth:
object OAuthHeaderBuilder {
// Apply function taken from the Yammer oauth sample
def apply(token:String, secret:String,verifier:String):String = {
val buff = new StringBuilder()
val currentTime = System.currentTimeMillis()
// Hardcoded values for consumer key and secret...
val consumerKey = "<your consumer key here>"
val consumerSecret = "<your consumer secret here>"
buff.append("OAuth realm=\"");
buff.append("\", oauth_consumer_key=\"");
buff.append(consumerKey);
buff.append("\", ");
if (token != null) {
buff.append("oauth_token=\"");
buff.append(token);
buff.append("\", ");
}
buff.append("oauth_signature_method=\"");
buff.append("PLAINTEXT");
buff.append("\", oauth_signature=\"");
buff.append(consumerSecret);
buff.append("%26");
if (secret != null) {
buff.append(secret);
}
buff.append("\", oauth_timestamp=\"");
buff.append(currentTime);
buff.append("\", oauth_nonce=\"");
buff.append(currentTime);
if (verifier != null) {
buff.append("\", ");
buff.append("oauth_verifier=\"");
buff.append(verifier);
}
buff.append("\", oauth_version=\"1.0\"");
return buff.toString();
}
}
И для извлечения токенов я создал объект OAuthTokenExtractor ...
object OAuthTokenExtractor {
def apply(line:String) = {
val token = (line split ("&")).find(x => x.startsWith("oauth_token=")) match {
case Some(oauth_token) => (oauth_token split ("=") )(1)
case _ => ""
}
val secret = (line split ("&")).find(x => x.startsWith("oauth_token_secret=")) match {
case Some(oauth_token_secret) => (oauth_token_secret split ("=") )(1)
case _ => ""
}
(token,secret)
}
}
Надеюсь, это поможет:)