• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javaandroidc++linuxc#objective-c誰得cocoaqtpythonrubywindowsphpgameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwitterdombtronvb.nettestarduinodirectxpreviewerゲームエンジン

Navigation voice changer app for Android


Commit MetaInfo

Revision225e5fb821e81642e096d2dc578e31aec7b04b75 (tree)
Time2013-08-02 17:27:32
AuthorHMML <hmml3939@gmai...>
CommiterHMML

Log Message

Rating handling and cleanup.

Change Summary

Incremental Difference

--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -39,6 +39,9 @@
3939 <string name="decline">断る!</string>
4040 <string name="tos_title">おことわり</string>
4141 <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>
4447 </resources>
\ No newline at end of file
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -41,5 +41,10 @@
4141 <string name="decline">Decline</string>
4242 <string name="tos_title">Notice</string>
4343 <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>
4449
4550 </resources>
--- a/src/jp/nekoteki/android/navivoicechanger/DownloadActivity.java
+++ b/src/jp/nekoteki/android/navivoicechanger/DownloadActivity.java
@@ -14,10 +14,8 @@ import android.net.http.AndroidHttpClient;
1414 import android.os.AsyncTask;
1515 import android.os.Bundle;
1616 import android.app.Activity;
17-import android.text.style.ImageSpan;
1817 import android.util.Log;
1918 import android.view.ContextMenu;
20-import android.view.Gravity;
2119 import android.view.Menu;
2220 import android.view.MenuItem;
2321 import android.view.View;
@@ -115,7 +113,7 @@ public class DownloadActivity extends Activity {
115113 json_stream.close();
116114 return vdlist;
117115 } 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.");
119117 e.printStackTrace();
120118 return null;
121119 } catch (Exception e) {
@@ -133,7 +131,7 @@ public class DownloadActivity extends Activity {
133131
134132 protected void onPostExecute(RemoteVoiceData[] vdlist) {
135133 if (vdlist == null || vdlist.length == 0) {
136- Log.i(this.getClass().toString(),"EOL detected.");
134+ Log.d(this.getClass().toString(),"EOL detected.");
137135 this.adapter.eol = true;
138136 this.view.removeFooterView(((DownloadActivity) this.view.getContext()).list_footer_marker);
139137 this.adapter.loading = false;
@@ -370,6 +368,8 @@ public class DownloadActivity extends Activity {
370368 protected void onPostExecute(Boolean flag) {
371369 if (this.rvd.isDownloaded())
372370 context.rvd_list_adapter.notifyDataSetChanged();
371+ if (!flag)
372+ Toast.makeText(context, R.string.download_failed, Toast.LENGTH_LONG).show();
373373 context.setDownloadOverlay(false);
374374 }
375375 }.execute(this, rvd);
@@ -384,8 +384,8 @@ public class DownloadActivity extends Activity {
384384 Toast.makeText(this, R.string.voice_deleted, Toast.LENGTH_SHORT).show();
385385 break;
386386 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);
389389 break;
390390 }
391391 return true;
--- a/src/jp/nekoteki/android/navivoicechanger/InstallListActivity.java
+++ b/src/jp/nekoteki/android/navivoicechanger/InstallListActivity.java
@@ -1,13 +1,9 @@
11 package jp.nekoteki.android.navivoicechanger;
22
3-import java.io.IOException;
43 import java.util.List;
5-import java.util.zip.ZipException;
64
75 import android.os.Bundle;
86 import android.app.Activity;
9-import android.app.AlertDialog;
10-import android.util.Log;
117 import android.view.ContextMenu;
128 import android.view.ContextMenu.ContextMenuInfo;
139 import android.view.Menu;
@@ -26,7 +22,6 @@ import android.widget.Toast;
2622 import android.support.v4.app.NavUtils;
2723 import android.annotation.TargetApi;
2824 import android.content.Context;
29-import android.content.DialogInterface;
3025 import android.content.Intent;
3126 import android.graphics.Color;
3227 import android.os.Build;
@@ -208,8 +203,7 @@ public class InstallListActivity extends Activity {
208203 Toast.makeText(this, R.string.voice_deleted, Toast.LENGTH_SHORT).show();
209204 break;
210205 case C_MENU_RATE:
211- // TODO: implement!
212- Toast.makeText(this, "Not implemented yet", Toast.LENGTH_SHORT).show();
206+ vd.promptToRate(this);
213207 break;
214208 }
215209 return true;
--- a/src/jp/nekoteki/android/navivoicechanger/MainMenuActivity.java
+++ b/src/jp/nekoteki/android/navivoicechanger/MainMenuActivity.java
@@ -1,14 +1,12 @@
11 package jp.nekoteki.android.navivoicechanger;
22
3-import java.io.IOException;
4-import java.util.zip.ZipException;
3+import java.util.UUID;
54
65 import android.os.Bundle;
76 import android.app.Activity;
87 import android.app.AlertDialog;
98 import android.content.DialogInterface;
109 import android.content.Intent;
11-import android.util.Log;
1210 import android.view.Menu;
1311 import android.view.View;
1412
@@ -62,6 +60,11 @@ public class MainMenuActivity extends Activity {
6260 dialog.setMessage(R.string.tos);
6361 dialog.show();
6462 }
63+
64+ String ident = Config.get(getApplicationContext(), "ident");
65+ if (ident == null || ident.equals("")) {
66+ Config.set(getApplicationContext(), "ident", "nvcapp:"+UUID.randomUUID().toString());
67+ }
6568 }
6669
6770 @Override
--- a/src/jp/nekoteki/android/navivoicechanger/RemoteVoiceData.java
+++ b/src/jp/nekoteki/android/navivoicechanger/RemoteVoiceData.java
@@ -111,6 +111,11 @@ public class RemoteVoiceData {
111111 Log.i(this.getClass().toString(), "Loading URL: "+this.ini_url);
112112 HttpResponse res;
113113 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+ }
114119 is = res.getEntity().getContent();
115120 os = new FileOutputStream(file);
116121 VoiceData.copyStream(is, os);
--- a/src/jp/nekoteki/android/navivoicechanger/VoiceData.java
+++ b/src/jp/nekoteki/android/navivoicechanger/VoiceData.java
@@ -17,17 +17,25 @@ import java.util.List;
1717 import java.util.Properties;
1818 import java.util.zip.ZipException;
1919
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+
2026 import android.media.MediaPlayer;
2127 import android.net.Uri;
28+import android.net.http.AndroidHttpClient;
29+import android.os.AsyncTask;
2230 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;
2635 import android.app.AlertDialog;
2736 import android.content.Context;
2837 import android.content.DialogInterface;
2938 import android.content.res.AssetManager;
30-import android.graphics.Paint.Join;
3139
3240 class VoiceDataInstallError extends Exception {};
3341 class DataDirNotFound extends VoiceDataInstallError {};
@@ -504,5 +512,93 @@ public class VoiceData {
504512 if (player != null)
505513 player.start();
506514 }
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);
507524
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+ }
508604 }
\ No newline at end of file