Navigation voice changer app for Android
Revision | 225e5fb821e81642e096d2dc578e31aec7b04b75 (tree) |
---|---|
Time | 2013-08-02 17:27:32 |
Author | ![]() |
Commiter | HMML |
Rating handling and cleanup.
@@ -39,6 +39,9 @@ | ||
39 | 39 | <string name="decline">断る!</string> |
40 | 40 | <string name="tos_title">おことわり</string> |
41 | 41 | <string name="tos">ダウンロードありがとうございます。すみませんが使うにあたり、以下に注意してください。\n\nこのアプリはマップと Android OS の現状の挙動に固定的に依存しています。それらは非公開のものであるため、将来の変更時にこのアプリは動作しなくなります。その場合の対応は全く保証できません。</string> |
42 | - | |
43 | - | |
42 | + <string name="send">送信</string> | |
43 | + <string name="rate_sent">評価を送信しました。</string> | |
44 | + <string name="rate_for">評価: </string> | |
45 | + <string name="sent_failed">送信に失敗しました</string> | |
46 | + <string name="download_failed">ダウンロードに失敗しました</string> | |
44 | 47 | </resources> |
\ No newline at end of file |
@@ -41,5 +41,10 @@ | ||
41 | 41 | <string name="decline">Decline</string> |
42 | 42 | <string name="tos_title">Notice</string> |
43 | 43 | <string name="tos">Thank you for downloading! Please keep mind following terms;\n\nThis app is depends on CURRENT behavior of Maps and Android OS statically. These are closed and un-documented, then this app WILL STOP WORKING on future changes. In that case, I can NOT promise to continue to support.</string> |
44 | + <string name="send">Send</string> | |
45 | + <string name="rate_sent">Your rating has been sent.</string> | |
46 | + <string name="rate_for">Rate for</string> | |
47 | + <string name="sent_failed">Send failed.</string> | |
48 | + <string name="download_failed">Download Failed.</string> | |
44 | 49 | |
45 | 50 | </resources> |
@@ -14,10 +14,8 @@ import android.net.http.AndroidHttpClient; | ||
14 | 14 | import android.os.AsyncTask; |
15 | 15 | import android.os.Bundle; |
16 | 16 | import android.app.Activity; |
17 | -import android.text.style.ImageSpan; | |
18 | 17 | import android.util.Log; |
19 | 18 | import android.view.ContextMenu; |
20 | -import android.view.Gravity; | |
21 | 19 | import android.view.Menu; |
22 | 20 | import android.view.MenuItem; |
23 | 21 | import android.view.View; |
@@ -115,7 +113,7 @@ public class DownloadActivity extends Activity { | ||
115 | 113 | json_stream.close(); |
116 | 114 | return vdlist; |
117 | 115 | } catch (IOException e) { |
118 | - Log.d(this.getClass().toString(), "Failed to load from server."); | |
116 | + Log.e(this.getClass().toString(), "Failed to load from server."); | |
119 | 117 | e.printStackTrace(); |
120 | 118 | return null; |
121 | 119 | } catch (Exception e) { |
@@ -133,7 +131,7 @@ public class DownloadActivity extends Activity { | ||
133 | 131 | |
134 | 132 | protected void onPostExecute(RemoteVoiceData[] vdlist) { |
135 | 133 | if (vdlist == null || vdlist.length == 0) { |
136 | - Log.i(this.getClass().toString(),"EOL detected."); | |
134 | + Log.d(this.getClass().toString(),"EOL detected."); | |
137 | 135 | this.adapter.eol = true; |
138 | 136 | this.view.removeFooterView(((DownloadActivity) this.view.getContext()).list_footer_marker); |
139 | 137 | this.adapter.loading = false; |
@@ -370,6 +368,8 @@ public class DownloadActivity extends Activity { | ||
370 | 368 | protected void onPostExecute(Boolean flag) { |
371 | 369 | if (this.rvd.isDownloaded()) |
372 | 370 | context.rvd_list_adapter.notifyDataSetChanged(); |
371 | + if (!flag) | |
372 | + Toast.makeText(context, R.string.download_failed, Toast.LENGTH_LONG).show(); | |
373 | 373 | context.setDownloadOverlay(false); |
374 | 374 | } |
375 | 375 | }.execute(this, rvd); |
@@ -384,8 +384,8 @@ public class DownloadActivity extends Activity { | ||
384 | 384 | Toast.makeText(this, R.string.voice_deleted, Toast.LENGTH_SHORT).show(); |
385 | 385 | break; |
386 | 386 | case C_MENU_RATE: |
387 | - // TODO: implement! | |
388 | - Toast.makeText(this, "Not implemented yet", Toast.LENGTH_SHORT).show(); | |
387 | + if (!rvd.isDownloaded()) return true; | |
388 | + rvd.getVoiceData().promptToRate(this); | |
389 | 389 | break; |
390 | 390 | } |
391 | 391 | return true; |
@@ -1,13 +1,9 @@ | ||
1 | 1 | package jp.nekoteki.android.navivoicechanger; |
2 | 2 | |
3 | -import java.io.IOException; | |
4 | 3 | import java.util.List; |
5 | -import java.util.zip.ZipException; | |
6 | 4 | |
7 | 5 | import android.os.Bundle; |
8 | 6 | import android.app.Activity; |
9 | -import android.app.AlertDialog; | |
10 | -import android.util.Log; | |
11 | 7 | import android.view.ContextMenu; |
12 | 8 | import android.view.ContextMenu.ContextMenuInfo; |
13 | 9 | import android.view.Menu; |
@@ -26,7 +22,6 @@ import android.widget.Toast; | ||
26 | 22 | import android.support.v4.app.NavUtils; |
27 | 23 | import android.annotation.TargetApi; |
28 | 24 | import android.content.Context; |
29 | -import android.content.DialogInterface; | |
30 | 25 | import android.content.Intent; |
31 | 26 | import android.graphics.Color; |
32 | 27 | import android.os.Build; |
@@ -208,8 +203,7 @@ public class InstallListActivity extends Activity { | ||
208 | 203 | Toast.makeText(this, R.string.voice_deleted, Toast.LENGTH_SHORT).show(); |
209 | 204 | break; |
210 | 205 | case C_MENU_RATE: |
211 | - // TODO: implement! | |
212 | - Toast.makeText(this, "Not implemented yet", Toast.LENGTH_SHORT).show(); | |
206 | + vd.promptToRate(this); | |
213 | 207 | break; |
214 | 208 | } |
215 | 209 | return true; |
@@ -1,14 +1,12 @@ | ||
1 | 1 | package jp.nekoteki.android.navivoicechanger; |
2 | 2 | |
3 | -import java.io.IOException; | |
4 | -import java.util.zip.ZipException; | |
3 | +import java.util.UUID; | |
5 | 4 | |
6 | 5 | import android.os.Bundle; |
7 | 6 | import android.app.Activity; |
8 | 7 | import android.app.AlertDialog; |
9 | 8 | import android.content.DialogInterface; |
10 | 9 | import android.content.Intent; |
11 | -import android.util.Log; | |
12 | 10 | import android.view.Menu; |
13 | 11 | import android.view.View; |
14 | 12 |
@@ -62,6 +60,11 @@ public class MainMenuActivity extends Activity { | ||
62 | 60 | dialog.setMessage(R.string.tos); |
63 | 61 | dialog.show(); |
64 | 62 | } |
63 | + | |
64 | + String ident = Config.get(getApplicationContext(), "ident"); | |
65 | + if (ident == null || ident.equals("")) { | |
66 | + Config.set(getApplicationContext(), "ident", "nvcapp:"+UUID.randomUUID().toString()); | |
67 | + } | |
65 | 68 | } |
66 | 69 | |
67 | 70 | @Override |
@@ -111,6 +111,11 @@ public class RemoteVoiceData { | ||
111 | 111 | Log.i(this.getClass().toString(), "Loading URL: "+this.ini_url); |
112 | 112 | HttpResponse res; |
113 | 113 | res = client.execute(new HttpGet(url)); |
114 | + if (res.getStatusLine().getStatusCode() != 200) { | |
115 | + String msg = "Server returns bad status code: "+ Integer.toString(res.getStatusLine().getStatusCode()); | |
116 | + Log.e("VoiceData", msg); | |
117 | + throw new IOException(msg); | |
118 | + } | |
114 | 119 | is = res.getEntity().getContent(); |
115 | 120 | os = new FileOutputStream(file); |
116 | 121 | VoiceData.copyStream(is, os); |
@@ -17,17 +17,25 @@ import java.util.List; | ||
17 | 17 | import java.util.Properties; |
18 | 18 | import java.util.zip.ZipException; |
19 | 19 | |
20 | +import org.apache.http.HttpResponse; | |
21 | +import org.apache.http.NameValuePair; | |
22 | +import org.apache.http.client.entity.UrlEncodedFormEntity; | |
23 | +import org.apache.http.client.methods.HttpPost; | |
24 | +import org.apache.http.message.BasicNameValuePair; | |
25 | + | |
20 | 26 | import android.media.MediaPlayer; |
21 | 27 | import android.net.Uri; |
28 | +import android.net.http.AndroidHttpClient; | |
29 | +import android.os.AsyncTask; | |
22 | 30 | import android.util.Log; |
23 | -import android.app.Activity; | |
24 | -import android.app.ActivityManager; | |
25 | -import android.app.ActivityManager.RunningAppProcessInfo; | |
31 | +import android.view.Gravity; | |
32 | +import android.widget.LinearLayout; | |
33 | +import android.widget.RatingBar; | |
34 | +import android.widget.Toast; | |
26 | 35 | import android.app.AlertDialog; |
27 | 36 | import android.content.Context; |
28 | 37 | import android.content.DialogInterface; |
29 | 38 | import android.content.res.AssetManager; |
30 | -import android.graphics.Paint.Join; | |
31 | 39 | |
32 | 40 | class VoiceDataInstallError extends Exception {}; |
33 | 41 | class DataDirNotFound extends VoiceDataInstallError {}; |
@@ -504,5 +512,93 @@ public class VoiceData { | ||
504 | 512 | if (player != null) |
505 | 513 | player.start(); |
506 | 514 | } |
515 | + | |
516 | + public void rate(int value) throws IOException { | |
517 | + String url = Config.get(this.getContext(), "server_url_base") | |
518 | + + "/navi_voices/" + Integer.toString(this.getId()) + "/ratings.json"; | |
519 | + Log.i(this.getClass().toString(), "Send rating: "+url); | |
520 | + AndroidHttpClient client = AndroidHttpClient.newInstance("NaviVoiceChanger"); | |
521 | + | |
522 | + HttpResponse res; | |
523 | + HttpPost httppost = new HttpPost(url); | |
507 | 524 | |
525 | + List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); | |
526 | + nameValuePairs.add(new BasicNameValuePair("rating[value]", Integer.toString(value))); | |
527 | + nameValuePairs.add(new BasicNameValuePair("rating[ident]", Config.get(this.getContext(), "ident"))); | |
528 | + httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); | |
529 | + | |
530 | + try { | |
531 | + res = client.execute(httppost); | |
532 | + } finally { | |
533 | + client.close(); | |
534 | + } | |
535 | + if (res == null) { | |
536 | + String msg = "Cant get reponse on rating"; | |
537 | + Log.e(this.getClass().getName(), msg); | |
538 | + throw new IOException(msg); | |
539 | + } else if (res.getStatusLine().getStatusCode() != 201) { | |
540 | + String msg = "Server returns bad status code on rating: "+ Integer.toString(res.getStatusLine().getStatusCode()); | |
541 | + Log.e(this.getClass().getName(), msg); | |
542 | + throw new IOException(msg); | |
543 | + } | |
544 | + } | |
545 | + | |
546 | + public void promptToRate(Context context) { | |
547 | + LinearLayout ratelayout = new LinearLayout(context); | |
548 | + RatingBar rating = new RatingBar(context); | |
549 | + rating.setMax(5); | |
550 | + rating.setStepSize(1.0f); | |
551 | + rating.setNumStars(5); | |
552 | + ratelayout.addView(rating); | |
553 | + ratelayout.setGravity(Gravity.CENTER_HORIZONTAL); | |
554 | + | |
555 | + AlertDialog.Builder builder = new AlertDialog.Builder(context); | |
556 | + builder.setTitle(context.getResources().getString(R.string.rate_for) + " " + this.getTitle()); | |
557 | + builder.setView(ratelayout); | |
558 | + | |
559 | + class RateAction implements DialogInterface.OnClickListener { | |
560 | + public VoiceData vd; | |
561 | + public Context context; | |
562 | + public RatingBar ratebar; | |
563 | + | |
564 | + @Override | |
565 | + public void onClick(DialogInterface dialog, int which) { | |
566 | + new AsyncTask<Object, Void, Boolean>() { | |
567 | + protected Context context; | |
568 | + | |
569 | + @Override | |
570 | + protected Boolean doInBackground(Object... params) { | |
571 | + this.context = (Context) params[0]; | |
572 | + VoiceData vd = (VoiceData) params[1]; | |
573 | + RatingBar rating = (RatingBar) params[2]; | |
574 | + try { | |
575 | + vd.rate(Math.round(rating.getRating())); | |
576 | + } catch (Exception e) { | |
577 | + e.printStackTrace(); | |
578 | + return false; | |
579 | + } | |
580 | + return true; | |
581 | + } | |
582 | + protected void onPostExecute(Boolean flag) { | |
583 | + if (flag) { | |
584 | + Toast.makeText(context, R.string.rate_sent, Toast.LENGTH_SHORT).show(); | |
585 | + } else { | |
586 | + Toast.makeText(context, R.string.sent_failed, Toast.LENGTH_SHORT).show(); | |
587 | + } | |
588 | + } | |
589 | + }.execute(context, vd, ratebar); | |
590 | + | |
591 | + } | |
592 | + }; | |
593 | + RateAction rate_action = new RateAction(); | |
594 | + rate_action.vd = this; | |
595 | + rate_action.context = context; | |
596 | + rate_action.ratebar = rating; | |
597 | + builder.setPositiveButton(R.string.send, rate_action); | |
598 | + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { | |
599 | + @Override | |
600 | + public void onClick(DialogInterface dialog, int which) { } | |
601 | + }); | |
602 | + builder.show(); | |
603 | + } | |
508 | 604 | } |
\ No newline at end of file |