1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Android variant improved with platform specific services
17 android_manifest_activity
"""android:theme="@android:style/Theme.DeviceDefault" """
18 android_api_min
16 # For BigTextStyle
22 import ::android
::portrait
23 import ::android
::toast
24 import ::android
::wifi
25 import ::android
::service
::at_boot
37 # Launch service with app, if it wasn't already launched at boot
41 # Use Android toasts if there is an activity, otherwise fallback on the log
42 redef fun feedback
(text
)
44 if activities
.not_empty
then
45 app
.toast
(text
.to_s
, false)
49 # Register to callback `async_wifi_scan_available` when a wifi scan is available
50 private fun notify_on_wifi_scan
(context
: NativeContext)
51 import async_wifi_scan_available
in "Java" `{
53 android.content.IntentFilter filter = new android.content.IntentFilter();
54 filter.addAction(android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
55 final int final_self = self;
57 context.registerReceiver(
58 new android.content.BroadcastReceiver() {
60 public void onReceive(android.content.Context context, android.content.Intent intent) {
61 if (intent.getAction().equals(android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
62 App_async_wifi_scan_available(final_self);
68 private fun async_wifi_scan_available
do run_on_ui_thread task_on_wifi_scan_available
70 private var task_on_wifi_scan_available
= new WifiScanAvailable is lazy
74 redef fun on_start_command
(intent
, flags
, id
)
76 app
.notify_on_wifi_scan native
78 # Check token validity
79 (new PushHttpRequest("push/check_token?token={app.token}")).start
85 # Task ran on the UI thread when a wifi scan is available
86 private class WifiScanAvailable
91 jni_env
.push_local_frame
4
92 var manager
= app
.native_context
.wifi_manager
93 var networks
= manager
.get_scan_results
95 for i
in networks
.length
.times
do
96 jni_env
.push_local_frame
4
98 var ssid
= net
.ssid
.to_s
100 # TODO use BSSID instead
101 #var bssid = net.bssid.to_s
102 var target_ssids
= ["Benelux"]
103 if target_ssids
.has
(ssid
) then # and bssid == "C8:F7:33:81:B0:E6" then
107 jni_env
.pop_local_frame
109 jni_env
.pop_local_frame
113 else app
.on_check_out
117 redef class SectionTitle
118 init do set_text_style
(native
, app
.native_context
)
120 private fun set_text_style
(view
: NativeTextView, context
: NativeContext) in "Java" `{
121 view.setTextAppearance(context, android.R.style.TextAppearance_Large);
126 init do set_backgroud
(native
, app
.native_context
)
128 private fun set_backgroud
(view
: NativeView, context
: NativeContext) in "Java" `{
129 int color = context.getResources().getIdentifier("item_background", "color", context.getPackageName());
130 view.setBackgroundResource(color);
134 # Use Android notifications
135 redef fun notify
(title
, content
, id
)
137 var service
= app
.service
138 assert service
!= null
139 native_notify
(service
.native
, id
, title
.to_java_string
, content
.to_java_string
)
142 private fun native_notify
(context
: NativeService, id
: Int, title
, content
: JavaString)
144 int icon = context.getResources().getIdentifier(
145 "notif", "drawable", context.getPackageName());
147 android.app.Notification.BigTextStyle style =
148 new android.app.Notification.BigTextStyle();
149 style.bigText(content);
151 android.content.Intent intent = new android.content.Intent(
152 context, nit.app.NitActivity.class);
153 android.app.PendingIntent pendingIntent = android.app.PendingIntent.getActivity(
154 context, 0, intent, android.app.PendingIntent.FLAG_UPDATE_CURRENT);
156 android.app.Notification notif = new android.app.Notification.Builder(context)
157 .setContentTitle(title)
158 .setContentText(content)
163 .setContentIntent(pendingIntent)
164 .setDefaults(android.app.Notification.DEFAULT_SOUND |
165 android.app.Notification.DEFAULT_LIGHTS)
168 android.app.NotificationManager notificationManager =
169 (android.app.NotificationManager)context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
171 notificationManager.notify((int)id, notif);
175 # Use `RatingBar` as the beer rating control
177 redef fun setup_stars
(rating
)
179 var title
= "Review %0".t
.format
(beer_info
.beer
.name
).to_java_string
180 native_setup_stars
(app
.native_context
, top_line_layout
.native
, rating
, title
, app
.user
!= null)
183 private fun native_setup_stars
(context
: NativeContext, layout
: NativeViewGroup, rating
: Int, title
: JavaString, loggedin
: Bool)
184 import on_review
in "Java" `{
185 // Set an indicator/non-interactive display
186 final android.widget.RatingBar view = new android.widget.RatingBar(
187 context, null, android.R.attr.ratingBarStyleIndicator);
189 view.setRating(rating);
190 view.setIsIndicator(true);
192 final android.view.ViewGroup.MarginLayoutParams params = new android.view.ViewGroup.MarginLayoutParams(
193 android.widget.LinearLayout.LayoutParams.WRAP_CONTENT,
194 android.widget.LinearLayout.LayoutParams.FILL_PARENT);
195 layout.addView(view, params);
197 // Make some variables final to used in anonymous class and delayed methods
198 final android.content.Context final_context = context;
199 final long final_rating = rating;
200 final String final_title = title;
201 final boolean final_loggedin = loggedin;
203 final int final_self = self;
204 BeerView_incr_ref(self); // Nit GC
206 view.setOnTouchListener(new android.view.View.OnTouchListener() {
208 public boolean onTouch(android.view.View v, android.view.MotionEvent event) {
209 if (event.getAction() != android.view.MotionEvent.ACTION_UP) return true;
211 // Don't show dialog if not logged in
212 if (!final_loggedin) {
213 android.widget.Toast toast = android.widget.Toast.makeText(
214 final_context, "You must login first to post reviews",
215 android.widget.Toast.LENGTH_SHORT);
220 // Build dialog with a simple interactive RatingBar
221 final android.app.AlertDialog.Builder dialog_builder = new android.app.AlertDialog.Builder(final_context);
222 final android.widget.RatingBar rating = new android.widget.RatingBar(final_context);
223 rating.setNumStars(5);
224 rating.setStepSize(1.0f);
225 rating.setRating(final_rating);
228 int icon = final_context.getResources().getIdentifier("notif", "drawable", final_context.getPackageName());
229 dialog_builder.setIcon(icon);
230 dialog_builder.setTitle(final_title);
233 android.widget.LinearLayout l = new android.widget.LinearLayout(final_context);
234 l.addView(rating, params);
235 l.setHorizontalGravity(android.view.Gravity.CENTER_HORIZONTAL);
236 dialog_builder.setView(l);
239 dialog_builder.setPositiveButton(android.R.string.ok,
240 new android.content.DialogInterface.OnClickListener() {
241 public void onClick(android.content.DialogInterface dialog, int which) {
244 long r = (long)rating.getRating();
245 view.setRating(r); // Update static control
246 view.invalidate(); // For not refreshing bug
248 BeerView_on_review(final_self, r); // Callback
249 BeerView_decr_ref(final_self); // Nit GC
254 dialog_builder.setNegativeButton(android.R.string.cancel,
255 new android.content.DialogInterface.OnClickListener() {
256 public void onClick(android.content.DialogInterface dialog, int id) {
258 BeerView_decr_ref(final_self); // Nit GC
262 dialog_builder.create();
263 dialog_builder.show();