Navigation voice changer app for Android
Revision | de1c4b9ea2570db340bf6a59127889cc57947fab (tree) |
---|---|
Time | 2013-07-30 06:09:47 |
Author | ![]() |
Commiter | HMML |
Implement download list.
@@ -1,3 +1,6 @@ | ||
1 | -/gen | |
2 | -/bin | |
3 | -/libs | |
1 | +/gen/ | |
2 | +/bin/ | |
3 | +*~ | |
4 | +*.bak | |
5 | +*.orig | |
6 | +.*.sw[po] |
@@ -1,4 +1,11 @@ | ||
1 | 1 | eclipse.preferences.version=1 |
2 | +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | |
2 | 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 |
4 | +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve | |
3 | 5 | 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 | |
4 | 11 | org.eclipse.jdt.core.compiler.source=1.6 |
@@ -43,6 +43,14 @@ | ||
43 | 43 | android:name="android.support.PARENT_ACTIVITY" |
44 | 44 | android:value="jp.nekoteki.android.navivoicechanger.MainMenuActivity" /> |
45 | 45 | </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> | |
46 | 54 | </application> |
47 | 55 | |
48 | 56 | </manifest> |
@@ -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 |
@@ -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> |
@@ -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 |
@@ -1,6 +1,6 @@ | ||
1 | 1 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
2 | 2 | xmlns:tools="http://schemas.android.com/tools" |
3 | - android:id="@+id/RelativeLayout1" | |
3 | + android:id="@+id/download_pregrees" | |
4 | 4 | android:layout_width="match_parent" |
5 | 5 | android:layout_height="match_parent" |
6 | 6 | android:orientation="vertical" |
@@ -25,7 +25,7 @@ | ||
25 | 25 | android:text="@string/btn_purge_installed" /> |
26 | 26 | |
27 | 27 | <TextView |
28 | - android:id="@+id/textView1" | |
28 | + android:id="@+id/text_btm_guide" | |
29 | 29 | android:layout_width="wrap_content" |
30 | 30 | android:layout_height="wrap_content" |
31 | 31 | android:text="@string/desc_purge_installed" /> |
@@ -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> |
@@ -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> |
@@ -1,7 +1,7 @@ | ||
1 | 1 | <menu xmlns:android="http://schemas.android.com/apk/res/android" > |
2 | 2 | |
3 | 3 | <item |
4 | - android:id="@+id/action_settings" | |
4 | + android:id="@+id/text_download_guide" | |
5 | 5 | android:orderInCategory="100" |
6 | 6 | android:showAsAction="never" |
7 | 7 | android:title="@string/action_settings"/> |
@@ -27,8 +27,13 @@ | ||
27 | 27 | <string name="btn_purge_downloaded">Delete all downloaded</string> |
28 | 28 | <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> |
29 | 29 | <string name="desc_purge_downloaded">Delete all downloaded voice data from THIS APPLICATION (NOT Navigation).</string> |
30 | + | |
30 | 31 | <color name="maint_bg">#fff3f3f3</color> |
32 | + | |
31 | 33 | <string name="msg_installed_removed">Installed data has been removed.</string> |
32 | 34 | <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> | |
33 | 38 | |
34 | 39 | </resources> |
@@ -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 | +} |
@@ -28,7 +28,13 @@ public class MainMenuActivity extends Activity { | ||
28 | 28 | } |
29 | 29 | }); |
30 | 30 | |
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 | + }); | |
32 | 38 | } |
33 | 39 | |
34 | 40 | @Override |
@@ -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 | +} |
@@ -4,6 +4,7 @@ import java.io.BufferedInputStream; | ||
4 | 4 | import java.io.File; |
5 | 5 | import java.io.FileFilter; |
6 | 6 | import java.io.FileInputStream; |
7 | +import java.io.FileNotFoundException; | |
7 | 8 | import java.io.FileOutputStream; |
8 | 9 | import java.io.IOException; |
9 | 10 | import java.io.InputStream; |
@@ -210,6 +211,10 @@ public class VoiceData { | ||
210 | 211 | vd.delete(); |
211 | 212 | } |
212 | 213 | } |
214 | + | |
215 | + public VoiceData(Context context) { | |
216 | + /// nothing to do... | |
217 | + } | |
213 | 218 | |
214 | 219 | public VoiceData(File file, Context context) { |
215 | 220 | if (!file.exists() || !file.isDirectory()) |
@@ -218,19 +223,38 @@ public class VoiceData { | ||
218 | 223 | if (!ini.exists()) |
219 | 224 | throw new IllegalArgumentException("Ini file not found"); |
220 | 225 | |
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) { | |
221 | 240 | Properties prop = new Properties(); |
222 | 241 | try { |
223 | - prop.load(new InputStreamReader(new FileInputStream(ini), "UTF-8")); | |
242 | + prop.load(new InputStreamReader(ini_stream, "UTF-8")); | |
224 | 243 | } catch (IOException e) { |
244 | + e.printStackTrace(); | |
225 | 245 | throw new IllegalArgumentException("Failed to load ini file"); |
226 | 246 | } |
247 | + try { | |
248 | + ini_stream.close(); | |
249 | + } catch (IOException e) { | |
250 | + // ignore | |
251 | + } | |
227 | 252 | |
228 | 253 | this.context = context; |
229 | 254 | this.id = Integer.parseInt(prop.getProperty("id")); |
230 | 255 | this.archive_md5 = prop.getProperty("archive_md5"); |
231 | 256 | this.title = prop.getProperty("title"); |
232 | 257 | this.description = prop.getProperty("description"); |
233 | - this.path = file.getAbsolutePath(); | |
234 | 258 | this.lang = prop.getProperty("lang"); |
235 | 259 | this.unit = prop.getProperty("unit"); |
236 | 260 | try { |