• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javaandroidc++objective-ccocoa誰得c#gamebathyscaphephplinuxrubyqt翻訳pythoncomegatwindowstwitterguiframeworkbtronvb.netdirectxtestdomarduino計画中(planning stage)previewerpukiwiki

Navigation voice changer app for Android


コミットメタ情報

リビジョンde1c4b9ea2570db340bf6a59127889cc57947fab (tree)
日時2013-07-30 06:09:47
作者HMML <hmml3939@gmai...>
コミッターHMML

ログメッセージ

Implement download list.

変更サマリ

差分

--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
1-/gen
2-/bin
3-/libs
1+/gen/
2+/bin/
3+*~
4+*.bak
5+*.orig
6+.*.sw[po]
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,11 @@
11 eclipse.preferences.version=1
2+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
23 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
35 org.eclipse.jdt.core.compiler.compliance=1.6
6+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7+org.eclipse.jdt.core.compiler.debug.localVariable=generate
8+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
411 org.eclipse.jdt.core.compiler.source=1.6
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -43,6 +43,14 @@
4343 android:name="android.support.PARENT_ACTIVITY"
4444 android:value="jp.nekoteki.android.navivoicechanger.MainMenuActivity" />
4545 </activity>
46+ <activity
47+ android:name="jp.nekoteki.android.navivoicechanger.DownloadActivity"
48+ android:label="@string/title_activity_download"
49+ android:parentActivityName="jp.nekoteki.android.navivoicechanger.MainMenuActivity" >
50+ <meta-data
51+ android:name="android.support.PARENT_ACTIVITY"
52+ android:value="jp.nekoteki.android.navivoicechanger.MainMenuActivity" />
53+ </activity>
4654 </application>
4755
4856 </manifest>
--- /dev/null
+++ b/README
@@ -0,0 +1,14 @@
1+= Android Navigation Voice Changer
2+
3+== See Also
4+
5+ * http://productforums.google.com/forum/#!msg/maps/PWmQggbTBFA/9uBHeKxb0egJ
6+ * http://forum.xda-developers.com/showthread.php?t=1828069
7+
8+== Author
9+
10+@gull08 on twitter
11+
12+== License
13+
14+GPLv3 ( http://www.gnu.org/licenses/gpl-3.0.html )
\ No newline at end of file
Binary files /dev/null and b/libs/android-support-v4.jar differ
Binary files /dev/null and b/libs/jsonic-1.3.0.jar differ
--- /dev/null
+++ b/res/drawable/shadow_down.xml
@@ -0,0 +1,8 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<shape xmlns:android="http://schemas.android.com/apk/res/android"
3+ android:shape="rectangle">
4+ <gradient
5+ android:startColor="#0000"
6+ android:endColor="#f000"
7+ android:angle="270" />
8+</shape>
--- /dev/null
+++ b/res/layout/activity_download.xml
@@ -0,0 +1,72 @@
1+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+ android:layout_width="fill_parent"
3+ android:layout_height="fill_parent" >
4+
5+ <TextView
6+ android:id="@+id/text_download_guide"
7+ android:layout_width="match_parent"
8+ android:layout_height="wrap_content"
9+ android:layout_alignParentBottom="true"
10+ android:background="#000"
11+ android:paddingBottom="@dimen/activity_vertical_margin"
12+ android:paddingLeft="@dimen/activity_horizontal_margin"
13+ android:paddingRight="@dimen/activity_horizontal_margin"
14+ android:paddingTop="8dp"
15+ android:text="@string/guide_download"
16+ android:textColor="#fff" />
17+
18+ <LinearLayout
19+ android:layout_width="match_parent"
20+ android:layout_height="20dp"
21+ android:layout_above="@id/text_download_guide"
22+ android:background="@drawable/shadow_down"
23+ android:orientation="vertical" >
24+
25+ </LinearLayout>
26+
27+ <LinearLayout
28+ android:layout_width="wrap_content"
29+ android:layout_height="wrap_content"
30+ android:layout_above="@id/text_download_guide"
31+ android:layout_alignParentTop="true"
32+ android:orientation="vertical"
33+ android:paddingBottom="@dimen/activity_vertical_margin"
34+ android:paddingLeft="@dimen/activity_horizontal_margin"
35+ android:paddingRight="@dimen/activity_horizontal_margin"
36+ android:paddingTop="@dimen/activity_vertical_margin" >
37+
38+ <ListView
39+ android:id="@+id/download_item_list"
40+ android:layout_width="match_parent"
41+ android:layout_height="wrap_content" >
42+ </ListView>
43+ </LinearLayout>
44+
45+ <RelativeLayout
46+ android:id="@+id/download_pregrees"
47+ android:layout_width="match_parent"
48+ android:layout_height="match_parent"
49+ android:background="#8000"
50+ android:clickable="true"
51+ android:orientation="vertical"
52+ android:visibility="gone" >
53+
54+ <ProgressBar
55+ android:id="@+id/progressBar"
56+ style="?android:attr/progressBarStyle"
57+ android:layout_width="wrap_content"
58+ android:layout_height="wrap_content"
59+ android:layout_centerVertical="true"
60+ android:padding="16dp" />
61+
62+ <TextView
63+ android:layout_width="match_parent"
64+ android:layout_height="wrap_content"
65+ android:layout_centerVertical="true"
66+ android:layout_toRightOf="@id/progressBar"
67+ android:text="@string/download_progress"
68+ android:textColor="@android:color/white"
69+ android:textSize="24sp" />
70+ </RelativeLayout>
71+
72+</RelativeLayout>
\ No newline at end of file
--- a/res/layout/activity_install_list.xml
+++ b/res/layout/activity_install_list.xml
@@ -1,6 +1,6 @@
11 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
22 xmlns:tools="http://schemas.android.com/tools"
3- android:id="@+id/RelativeLayout1"
3+ android:id="@+id/download_pregrees"
44 android:layout_width="match_parent"
55 android:layout_height="match_parent"
66 android:orientation="vertical"
--- a/res/layout/activity_maint.xml
+++ b/res/layout/activity_maint.xml
@@ -25,7 +25,7 @@
2525 android:text="@string/btn_purge_installed" />
2626
2727 <TextView
28- android:id="@+id/textView1"
28+ android:id="@+id/text_btm_guide"
2929 android:layout_width="wrap_content"
3030 android:layout_height="wrap_content"
3131 android:text="@string/desc_purge_installed" />
--- /dev/null
+++ b/res/layout/list_progress_footer.xml
@@ -0,0 +1,16 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+ android:id="@+id/LinearLayout1"
4+ android:layout_width="match_parent"
5+ android:layout_height="match_parent"
6+ android:layout_gravity="center"
7+ android:minHeight="?android:attr/listPreferredItemHeight"
8+ android:orientation="vertical" >
9+
10+ <ProgressBar
11+ android:id="@+id/progressBar1"
12+ android:layout_width="wrap_content"
13+ android:layout_height="wrap_content"
14+ android:layout_gravity="center" />
15+
16+</LinearLayout>
--- /dev/null
+++ b/res/menu/download.xml
@@ -0,0 +1,9 @@
1+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
2+
3+ <item
4+ android:id="@+id/text_download_guide"
5+ android:orderInCategory="100"
6+ android:showAsAction="never"
7+ android:title="@string/action_settings"/>
8+
9+</menu>
--- a/res/menu/maint.xml
+++ b/res/menu/maint.xml
@@ -1,7 +1,7 @@
11 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
22
33 <item
4- android:id="@+id/action_settings"
4+ android:id="@+id/text_download_guide"
55 android:orderInCategory="100"
66 android:showAsAction="never"
77 android:title="@string/action_settings"/>
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -27,8 +27,13 @@
2727 <string name="btn_purge_downloaded">Delete all downloaded</string>
2828 <string name="desc_purge_installed">Voice setting on Navigation will be reset. This action removes installed voice data and all cache files from data directory of Maps.</string>
2929 <string name="desc_purge_downloaded">Delete all downloaded voice data from THIS APPLICATION (NOT Navigation).</string>
30+
3031 <color name="maint_bg">#fff3f3f3</color>
32+
3133 <string name="msg_installed_removed">Installed data has been removed.</string>
3234 <string name="msg_downloaded_removed">Downloaded data has been removed.</string>
35+ <string name="title_activity_download">DownloadActivity</string>
36+ <string name="guide_download">Tap to download. Then push back button to move to install view to install.</string>
37+ <string name="download_progress">Donwloading...</string>
3338
3439 </resources>
--- /dev/null
+++ b/src/jp/nekoteki/android/navivoicechanger/DownloadActivity.java
@@ -0,0 +1,245 @@
1+package jp.nekoteki.android.navivoicechanger;
2+
3+import java.io.IOException;
4+import java.io.InputStream;
5+import java.util.ArrayList;
6+import java.util.LinkedHashMap;
7+import java.util.List;
8+
9+import net.arnx.jsonic.JSON;
10+
11+import org.apache.http.HttpResponse;
12+import org.apache.http.client.methods.HttpGet;
13+
14+import android.net.http.AndroidHttpClient;
15+import android.os.AsyncTask;
16+import android.os.Bundle;
17+import android.app.Activity;
18+import android.util.Log;
19+import android.view.Menu;
20+import android.view.MenuItem;
21+import android.view.View;
22+import android.view.ViewGroup;
23+import android.view.ViewGroup.LayoutParams;
24+import android.widget.AbsListView.OnScrollListener;
25+import android.widget.AbsListView;
26+import android.widget.BaseAdapter;
27+import android.widget.LinearLayout;
28+import android.widget.ListView;
29+import android.widget.RelativeLayout;
30+import android.widget.TextView;
31+import android.support.v4.app.NavUtils;
32+import android.annotation.TargetApi;
33+import android.content.Context;
34+import android.graphics.Color;
35+import android.os.Build;
36+
37+public class DownloadActivity extends Activity {
38+
39+ public class RemoteVoiceDataAdapter extends BaseAdapter {
40+ final static String SERVER_BASE_URL = "http://tempest.private.nemui.org:3000";
41+
42+ protected boolean eol = false;
43+ protected Context context;
44+ protected List<RemoteVoiceData> list;
45+ protected int cur_page = 1;
46+ protected boolean loading = false;
47+
48+ public RemoteVoiceDataAdapter(Context context) {
49+ super();
50+ this.context = context;
51+ this.reset();
52+ }
53+
54+ @Override
55+ public int getCount() {
56+ return this.list.size();
57+ }
58+
59+ @Override
60+ public Object getItem(int position) {
61+ return this.list.get(position);
62+ }
63+
64+ @Override
65+ public long getItemId(int position) {
66+ return ((RemoteVoiceData) this.getItem(position)).getId();
67+ }
68+
69+ public void reset() {
70+ this.cur_page = 1;
71+ this.list = new ArrayList<RemoteVoiceData>();
72+ this.notifyDataSetChanged();
73+ }
74+
75+ public void add(RemoteVoiceData vd) {
76+ this.list.add(vd);
77+ }
78+
79+ public void loadList(AbsListView view) {
80+ if (this.loading || this.eol) return;
81+ this.loading = true;
82+ String url = SERVER_BASE_URL+"/navi_voices.json?page="+Integer.toString(this.cur_page);
83+
84+ new AsyncTask<Object, Void, RemoteVoiceData[]>() {
85+ protected RemoteVoiceDataAdapter adapter;
86+ protected ListView view;
87+
88+ @Override
89+ protected RemoteVoiceData[] doInBackground(Object... params) {
90+ try {
91+ String url = (String) params[0];
92+ this.view = (ListView) params[1];
93+ this.adapter = (RemoteVoiceDataAdapter) params[2];
94+ AndroidHttpClient client = AndroidHttpClient.newInstance("NaviVoiceChange");
95+ Log.i(this.getClass().toString(), "Loading URL: "+url);
96+ HttpResponse res;
97+ res = client.execute(new HttpGet(url));
98+ this.adapter.cur_page += 1;
99+ InputStream json_stream = res.getEntity().getContent();
100+ RemoteVoiceData[] vdlist = JSON.decode(json_stream, RemoteVoiceData[].class);
101+ json_stream.close();
102+ client.close();
103+ return vdlist;
104+ } catch (IOException e) {
105+ Log.d(this.getClass().toString(), "Failed to load from server.");
106+ e.printStackTrace();
107+ return null;
108+ } catch (Exception e) {
109+ Log.e(this.getClass().toString(), "Unknwon Exception in AsyncTask!!");
110+ e.printStackTrace();
111+ return null;
112+ }
113+ }
114+
115+ protected void onPostExecute(RemoteVoiceData[] vdlist) {
116+ if (vdlist == null || vdlist.length == 0) {
117+ Log.i(this.getClass().toString(),"EOL detected.");
118+ this.adapter.eol = true;
119+ this.view.removeFooterView(((DownloadActivity) this.view.getContext()).list_footer_marker);
120+ this.adapter.loading = false;
121+ this.adapter.notifyDataSetChanged();
122+ this.view.invalidateViews();
123+ return;
124+ }
125+
126+ Log.d(this.getClass().toString(), "Checking items...");
127+ for (RemoteVoiceData rvd: vdlist) {
128+ Log.d(this.getClass().toString(), "Item #" + Integer.toString(rvd.getId())+": "+rvd.getTitle());
129+ this.adapter.list.add(rvd);
130+ }
131+ Log.d(this.getClass().toString(), "Item load done.");
132+ this.adapter.notifyDataSetChanged();
133+ this.view.invalidateViews();
134+ this.adapter.loading = false;
135+ }
136+ }.execute(url, view, this);
137+ }
138+
139+ @Override
140+ public View getView(int position, View convertView, ViewGroup parent) {
141+ RemoteVoiceData rvd = (RemoteVoiceData) getItem(position);
142+
143+ RelativeLayout container = new RelativeLayout(context);
144+
145+ LinearLayout textlayout = new LinearLayout(context);
146+ textlayout.setOrientation(LinearLayout.VERTICAL);
147+ textlayout.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
148+ textlayout.setFocusable(false);
149+ textlayout.setFocusableInTouchMode(false);
150+
151+ TextView title = new TextView(context);
152+ title.setText(rvd.getTitle());
153+ title.setTextColor(Color.BLACK);
154+ title.setTextSize(16);
155+ textlayout.addView(title);
156+
157+ TextView description = new TextView(context);
158+ description.setTextSize(13);
159+ description.setText(rvd.getDescription());
160+ textlayout.addView(description);
161+
162+ container.addView(textlayout);
163+
164+ convertView = container;
165+ return convertView;
166+ }
167+
168+ }
169+
170+ public View list_footer_marker = null;
171+ public RemoteVoiceDataAdapter vd_list_adapter;
172+
173+ @Override
174+ protected void onCreate(Bundle savedInstanceState) {
175+ super.onCreate(savedInstanceState);
176+ setContentView(R.layout.activity_download);
177+ // Show the Up button in the action bar.
178+ setupActionBar();
179+
180+ this.vd_list_adapter = new RemoteVoiceDataAdapter(this);
181+ this.list_footer_marker = getLayoutInflater().inflate(R.layout.list_progress_footer, null);
182+
183+ ListView lv = (ListView) findViewById(R.id.download_item_list);
184+ lv.addFooterView(this.list_footer_marker);
185+ lv.setAdapter(this.vd_list_adapter);
186+ lv.setOnScrollListener(new OnScrollListener() {
187+ @Override
188+ public void onScrollStateChanged(AbsListView view, int scrollState) {
189+ // nothing to do...
190+ }
191+
192+ @Override
193+ public void onScroll(AbsListView view, int firstVisibleItem,
194+ int visibleItemCount, int totalItemCount) {
195+ if (totalItemCount == firstVisibleItem + visibleItemCount)
196+ ((DownloadActivity) view.getContext()).vd_list_adapter.loadList(view);
197+ }
198+ });
199+ }
200+
201+ /**
202+ * Set up the {@link android.app.ActionBar}, if the API is available.
203+ */
204+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
205+ private void setupActionBar() {
206+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
207+ getActionBar().setDisplayHomeAsUpEnabled(true);
208+ }
209+ }
210+
211+ @Override
212+ public boolean onCreateOptionsMenu(Menu menu) {
213+ // Inflate the menu; this adds items to the action bar if it is present.
214+ getMenuInflater().inflate(R.menu.download, menu);
215+ return true;
216+ }
217+
218+ @Override
219+ public boolean onOptionsItemSelected(MenuItem item) {
220+ switch (item.getItemId()) {
221+ case android.R.id.home:
222+ // This ID represents the Home or Up button. In the case of this
223+ // activity, the Up button is shown. Use NavUtils to allow users
224+ // to navigate up one level in the application structure. For
225+ // more details, see the Navigation pattern on Android Design:
226+ //
227+ // http://developer.android.com/design/patterns/navigation.html#up-vs-back
228+ //
229+ NavUtils.navigateUpFromSameTask(this);
230+ return true;
231+ }
232+ return super.onOptionsItemSelected(item);
233+ }
234+
235+ protected void setDownloadState(boolean flag) {
236+ View view = findViewById(R.id.download_pregrees);
237+ if (flag) {
238+ view.setVisibility(View.VISIBLE);
239+ } else {
240+ view.setVisibility(View.GONE);
241+ }
242+ }
243+
244+
245+}
--- a/src/jp/nekoteki/android/navivoicechanger/MainMenuActivity.java
+++ b/src/jp/nekoteki/android/navivoicechanger/MainMenuActivity.java
@@ -28,7 +28,13 @@ public class MainMenuActivity extends Activity {
2828 }
2929 });
3030
31- findViewById(R.id.btn_download).setEnabled(false);
31+ findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
32+ @Override
33+ public void onClick(View v) {
34+ startActivity(new Intent(MainMenuActivity.this, DownloadActivity.class));
35+
36+ }
37+ });
3238 }
3339
3440 @Override
--- /dev/null
+++ b/src/jp/nekoteki/android/navivoicechanger/RemoteVoiceData.java
@@ -0,0 +1,69 @@
1+package jp.nekoteki.android.navivoicechanger;
2+
3+public class RemoteVoiceData {
4+ protected int id;
5+ protected String ini_url;
6+ protected String archive_url;
7+ protected String preview_url;
8+ protected float rating;
9+ protected String title;
10+ protected String unit;
11+ protected String author;
12+ protected String description;
13+ public int getId() {
14+ return id;
15+ }
16+ public void setId(int id) {
17+ this.id = id;
18+ }
19+ public String getIni_url() {
20+ return ini_url;
21+ }
22+ public void setIni_url(String ini_url) {
23+ this.ini_url = ini_url;
24+ }
25+ public String getArchive_url() {
26+ return archive_url;
27+ }
28+ public void setArchive_url(String archive_url) {
29+ this.archive_url = archive_url;
30+ }
31+ public String getPreview_url() {
32+ return preview_url;
33+ }
34+ public void setPreview_url(String preview_url) {
35+ this.preview_url = preview_url;
36+ }
37+ public float getRating() {
38+ return rating;
39+ }
40+ public void setRating(float rating) {
41+ this.rating = rating;
42+ }
43+ public String getTitle() {
44+ return title;
45+ }
46+ public void setTitle(String title) {
47+ this.title = title;
48+ }
49+ public String getUnit() {
50+ return unit;
51+ }
52+ public void setUnit(String unit) {
53+ this.unit = unit;
54+ }
55+ public String getAuthor() {
56+ return author;
57+ }
58+ public void setAuthor(String author) {
59+ this.author = author;
60+ }
61+ public String getDescription() {
62+ return description;
63+ }
64+ public void setDescription(String description) {
65+ this.description = description;
66+ }
67+
68+
69+}
--- a/src/jp/nekoteki/android/navivoicechanger/VoiceData.java
+++ b/src/jp/nekoteki/android/navivoicechanger/VoiceData.java
@@ -4,6 +4,7 @@ import java.io.BufferedInputStream;
44 import java.io.File;
55 import java.io.FileFilter;
66 import java.io.FileInputStream;
7+import java.io.FileNotFoundException;
78 import java.io.FileOutputStream;
89 import java.io.IOException;
910 import java.io.InputStream;
@@ -210,6 +211,10 @@ public class VoiceData {
210211 vd.delete();
211212 }
212213 }
214+
215+ public VoiceData(Context context) {
216+ /// nothing to do...
217+ }
213218
214219 public VoiceData(File file, Context context) {
215220 if (!file.exists() || !file.isDirectory())
@@ -218,19 +223,38 @@ public class VoiceData {
218223 if (!ini.exists())
219224 throw new IllegalArgumentException("Ini file not found");
220225
226+ this.path = file.getAbsolutePath();
227+ try {
228+ this.loadIniStream(new FileInputStream(ini), context);
229+ } catch (IOException e) {
230+ e.printStackTrace();
231+ throw new IllegalArgumentException("Specified ini file not found: "+file.getAbsolutePath());
232+ }
233+ }
234+
235+ public VoiceData(InputStream ini_stream, Context context) {
236+ this.loadIniStream(ini_stream, context);
237+ }
238+
239+ public void loadIniStream(InputStream ini_stream, Context context) {
221240 Properties prop = new Properties();
222241 try {
223- prop.load(new InputStreamReader(new FileInputStream(ini), "UTF-8"));
242+ prop.load(new InputStreamReader(ini_stream, "UTF-8"));
224243 } catch (IOException e) {
244+ e.printStackTrace();
225245 throw new IllegalArgumentException("Failed to load ini file");
226246 }
247+ try {
248+ ini_stream.close();
249+ } catch (IOException e) {
250+ // ignore
251+ }
227252
228253 this.context = context;
229254 this.id = Integer.parseInt(prop.getProperty("id"));
230255 this.archive_md5 = prop.getProperty("archive_md5");
231256 this.title = prop.getProperty("title");
232257 this.description = prop.getProperty("description");
233- this.path = file.getAbsolutePath();
234258 this.lang = prop.getProperty("lang");
235259 this.unit = prop.getProperty("unit");
236260 try {