jruby-am-api 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/README +0 -0
- data/Rakefile +2 -0
- data/jruby-am-api.gemspec +21 -0
- data/lib/android_market.rb +11 -0
- data/lib/android_market/session.rb +193 -0
- data/lib/android_market/tools.rb +37 -0
- data/lib/android_market/version.rb +3 -0
- data/lib/java/am-api-models_20101114.jar +0 -0
- data/lib/java/protobuf-format-java-1.2.jar +0 -0
- data/lib/java/protobuf-java-2.2.0.jar +0 -0
- metadata +74 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "android_market/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "jruby-am-api"
|
7
|
+
s.version = AndroidMarket::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Mason Chang"]
|
10
|
+
s.email = ["changmason@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/jruby-am-api"
|
12
|
+
s.summary = %q{android market api in jruby}
|
13
|
+
s.description = %q{a port of android market api from java}
|
14
|
+
|
15
|
+
s.rubyforge_project = "jruby-am-api"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
# java
|
3
|
+
require File.dirname(__FILE__) + "/java/protobuf-java-2.2.0.jar"
|
4
|
+
require File.dirname(__FILE__) + "/java/am-api-models_20101114.jar"
|
5
|
+
require File.dirname(__FILE__) + "/java/protobuf-format-java-1.2.jar"
|
6
|
+
|
7
|
+
# ruby
|
8
|
+
require File.dirname(__FILE__) + "/android_market/session"
|
9
|
+
|
10
|
+
module AndroidMarket
|
11
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/tools"
|
2
|
+
|
3
|
+
module AndroidMarket
|
4
|
+
class Session
|
5
|
+
|
6
|
+
java_import com.gc.android.market.api.model.Market
|
7
|
+
java_import com.gc.android.market.api.model.Market::Request
|
8
|
+
java_import com.gc.android.market.api.model.Market::Response
|
9
|
+
java_import com.gc.android.market.api.model.Market::RequestContext
|
10
|
+
java_import com.gc.android.market.api.model.Market::Request::RequestGroup
|
11
|
+
|
12
|
+
SERVICE = "android"
|
13
|
+
URL_LOGIN = "https://www.google.com/accounts/ClientLogin"
|
14
|
+
PROTOCOL_VERSION = 2
|
15
|
+
ACCOUNT_TYPE = { :google => 'GOOGLE',
|
16
|
+
:hosted => 'HOSTED',
|
17
|
+
:both => 'HOSTED_OR_GOOGLE' }
|
18
|
+
|
19
|
+
attr_accessor :context_builder, :auth_sub_token
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@callbacks = []
|
23
|
+
@request_builder = Request.new_builder()
|
24
|
+
@context_builder = RequestContext.new_builder()
|
25
|
+
|
26
|
+
@context_builder.set_unknown1(0)
|
27
|
+
@context_builder.set_version(1002)
|
28
|
+
@context_builder.set_android_id("0000000000000000")
|
29
|
+
@context_builder.set_device_and_sdk_version("sapphire:7")
|
30
|
+
set_locale(JavaUtil::Locale.get_default)
|
31
|
+
set_operator_tmobile
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_locale(locale)
|
35
|
+
@context_builder.set_user_language(locale.language.downcase)
|
36
|
+
@context_builder.set_user_country(locale.country.downcase)
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_operator(alpha, sim_alpha, numeric, sim_numeric)
|
40
|
+
@context_builder.set_operator_alpha(alpha)
|
41
|
+
@context_builder.set_sim_operator_alpha(sim_alpha)
|
42
|
+
@context_builder.set_operator_numeric(numeric)
|
43
|
+
@context_builder.set_sim_operator_numeric(sim_numeric)
|
44
|
+
end
|
45
|
+
|
46
|
+
def set_operator_tmobile
|
47
|
+
set_operator("T-Mobile", "T-Mobile", "310260", "310260")
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_operator_sfr
|
51
|
+
set_operator("F SFR", "F SFR", "20810", "20810")
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_operator_o2
|
55
|
+
set_operator("o2 - de","o2 - de", "26207", "26207")
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_operator_simyo
|
59
|
+
set_operator("E-Plus", "simyo", "26203", "26203")
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_operator_sunrise
|
63
|
+
set_operator("sunrise", "sunrise", "22802", "22802")
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_auth_sub_token(auth_sub_token)
|
67
|
+
@context_builder.set_auth_sub_token(auth_sub_token)
|
68
|
+
self.auth_sub_token = auth_sub_token
|
69
|
+
end
|
70
|
+
|
71
|
+
def login(email, password, account_type = ACCOUNT_TYPE[:both])
|
72
|
+
params = { 'Email' => email,
|
73
|
+
'Passwd' => password,
|
74
|
+
'service' => SERVICE,
|
75
|
+
'accountType' => account_type }
|
76
|
+
Tools.post_url(URL_LOGIN, params)[/Auth=(.{200,204})$/i]
|
77
|
+
if auth_key = $1
|
78
|
+
set_auth_sub_token(auth_key)
|
79
|
+
else
|
80
|
+
raise RuntimeError, "auth_key not found"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def append(request_group, &block)
|
86
|
+
case request_group
|
87
|
+
when Market::AppsRequest
|
88
|
+
@request_builder.add_request_group(RequestGroup.new_builder.set_apps_request(request_group))
|
89
|
+
when Market::GetImageRequest
|
90
|
+
@request_builder.add_request_group(RequestGroup.new_builder.set_image_request(request_group))
|
91
|
+
when Market::CommentsRequest
|
92
|
+
@request_builder.add_request_group(RequestGroup.new_builder.set_comments_request(request_group))
|
93
|
+
when Market::CategoriesRequest
|
94
|
+
@request_builder.add_request_group(RequestGroup.new_builder.set_categories_request(request_group))
|
95
|
+
end
|
96
|
+
@callbacks << block if block_given?
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def flush
|
101
|
+
context = @context_builder.build
|
102
|
+
@context_builder = RequestContext.new_builder(context)
|
103
|
+
@request_builder.set_context(context)
|
104
|
+
|
105
|
+
response = execute_protobuf(@request_builder.build)
|
106
|
+
response.get_response_group_list.to_a.each do |res|
|
107
|
+
value = res.get_apps_response if res.has_apps_response
|
108
|
+
value = res.get_categories_response if res.has_categories_response
|
109
|
+
value = res.get_comments_response if res.has_comments_response
|
110
|
+
value = res.get_image_response if res.has_image_response
|
111
|
+
@callbacks.first.call(context, value)
|
112
|
+
end
|
113
|
+
|
114
|
+
@request_builder = Request.new_builder
|
115
|
+
@callbacks.clear
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# def execute(request_group, &block)
|
120
|
+
# case request_group
|
121
|
+
# when Market::AppsRequest
|
122
|
+
# @request_builder.add_request_group(RequestGroup.new_builder.set_apps_request(request_group))
|
123
|
+
# when Market::GetImageRequest
|
124
|
+
# @request_builder.add_request_group(RequestGroup.new_builder.set_image_request(request_group))
|
125
|
+
# when Market::CommentsRequest
|
126
|
+
# @request_builder.add_request_group(RequestGroup.new_builder.set_comments_request(request_group))
|
127
|
+
# when Market::CategoriesRequest
|
128
|
+
# @request_builder.add_request_group(RequestGroup.new_builder.set_categories_request(request_group))
|
129
|
+
# end
|
130
|
+
# context = @context_builder.build
|
131
|
+
# @context_builder = RequestContext.new_builder(context)
|
132
|
+
# @request_builder.set_context(context)
|
133
|
+
# response = execute_protobuf(@request_builder.build)
|
134
|
+
#
|
135
|
+
#
|
136
|
+
# block.call(ctxt, resp) if block_given?
|
137
|
+
#
|
138
|
+
# @request_builder = Request.new_builder
|
139
|
+
#
|
140
|
+
# return resp
|
141
|
+
# end
|
142
|
+
|
143
|
+
|
144
|
+
def execute_protobuf(request)
|
145
|
+
request_string = String.from_java_bytes(request.to_byte_array)
|
146
|
+
response_bytes = execute_raw_http_query(request_string)
|
147
|
+
begin
|
148
|
+
return Response.parse_from(response_bytes)
|
149
|
+
rescue => ex
|
150
|
+
raise RuntimeError, ex.message
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def execute_raw_http_query(request)
|
156
|
+
url = JavaNet::URL.new("http://android.clients.google.com/market/api/ApiRequest")
|
157
|
+
connection = url.open_connection
|
158
|
+
connection.set_do_output(true)
|
159
|
+
connection.set_request_method('POST')
|
160
|
+
connection.set_request_property('Cookie','ANDROID=' + @auth_sub_token)
|
161
|
+
connection.set_request_property('User-Agent', 'Android-Market/2 (sapphire PLAT-RC33); gzip')
|
162
|
+
connection.set_request_property('Content-Type', 'application/x-www-form-urlencoded')
|
163
|
+
connection.set_request_property('Accept-Charset','ISO-8859-1,utf-8;q=0.7,*;q=0.7')
|
164
|
+
|
165
|
+
request64 = Tools.urlsafe_encode64(request)
|
166
|
+
request_data = "version=#{PROTOCOL_VERSION}&request=#{request64}".to_java
|
167
|
+
|
168
|
+
connection.set_fixed_length_streaming_mode(request_data.get_bytes("UTF-8").length)
|
169
|
+
os = connection.get_output_stream
|
170
|
+
os.write(request_data.get_bytes)
|
171
|
+
os.close
|
172
|
+
|
173
|
+
if connection.get_response_code >= 400
|
174
|
+
raise RuntimeError, "Response Code = #{connection.get_response_code}, " +
|
175
|
+
"Message = #{connection.get_response_message}"
|
176
|
+
end
|
177
|
+
|
178
|
+
is = connection.get_input_stream
|
179
|
+
gz_is = java.util.zip::GZIPInputStream.new(is)
|
180
|
+
ba_os = java.io::ByteArrayOutputStream.new
|
181
|
+
buff = Java::byte[1024].new #"a buffer string".to_java_bytes
|
182
|
+
while(true) do
|
183
|
+
nb = gz_is.read(buff)
|
184
|
+
nb < 0 ? break : ba_os.write(buff, 0, nb)
|
185
|
+
end
|
186
|
+
is.close
|
187
|
+
connection.disconnect
|
188
|
+
|
189
|
+
return ba_os.to_byte_array
|
190
|
+
end
|
191
|
+
|
192
|
+
end # end of class
|
193
|
+
end # end of module
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module AndroidMarket
|
2
|
+
module Tools
|
3
|
+
|
4
|
+
#module_function :urlsafe_encode64, :post_url
|
5
|
+
|
6
|
+
def self.urlsafe_encode64(bin)
|
7
|
+
[bin].pack("m0").tr("+/", "-_").gsub("\n","")
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def self.post_url(url, params)
|
12
|
+
data = params.map { |key, val|
|
13
|
+
java.net::URLEncoder.encode(key, "UTF-8") + "=" +
|
14
|
+
java.net::URLEncoder.encode(val, "UTF-8")
|
15
|
+
}.join("&")
|
16
|
+
connection = java.net::URL.new(url).open_connection
|
17
|
+
connection.set_do_output(true)
|
18
|
+
connection.set_do_input(true)
|
19
|
+
connection.set_request_method("POST")
|
20
|
+
|
21
|
+
stream_to_authorize = java.io::OutputStreamWriter.new(connection.get_output_stream)
|
22
|
+
stream_to_authorize.write(data)
|
23
|
+
stream_to_authorize.flush
|
24
|
+
stream_to_authorize.close
|
25
|
+
|
26
|
+
result_stream = connection.get_input_stream
|
27
|
+
reader = java.io::BufferedReader.new(java.io::InputStreamReader.new(result_stream))
|
28
|
+
response = java.lang::StringBuffer.new
|
29
|
+
while line = reader.read_line do
|
30
|
+
response.append(line)
|
31
|
+
end
|
32
|
+
result_stream.close
|
33
|
+
response.to_string
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jruby-am-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Mason Chang
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-14 00:00:00 +08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: a port of android market api from java
|
22
|
+
email:
|
23
|
+
- changmason@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- Gemfile
|
33
|
+
- README
|
34
|
+
- Rakefile
|
35
|
+
- jruby-am-api.gemspec
|
36
|
+
- lib/android_market.rb
|
37
|
+
- lib/android_market/session.rb
|
38
|
+
- lib/android_market/tools.rb
|
39
|
+
- lib/android_market/version.rb
|
40
|
+
- lib/java/am-api-models_20101114.jar
|
41
|
+
- lib/java/protobuf-format-java-1.2.jar
|
42
|
+
- lib/java/protobuf-java-2.2.0.jar
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://rubygems.org/gems/jruby-am-api
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project: jruby-am-api
|
69
|
+
rubygems_version: 1.3.6
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: android market api in jruby
|
73
|
+
test_files: []
|
74
|
+
|