第一轮考核,7月20号,展示完我的项目后,师兄貌似觉得我还不错的样子(自我感觉良好吧应该- -),同时师兄也提出了几点改进的意见:
1、在定时更新的功能中,我的功能是选择更新的时间,时间到了启动service,将历史记录中所有的城市的天气情况更新到最新,如果我保存了1000个城市,按之前的博客来说就是等于瞬间开了1000条线程,这样很容易造成程序卡死。
2、如果用户狂点击查询广州城市,也开了很多条线程来查询广州,并且提示天气更新成功的Toast会一直弹出来,这样使程序的用户体验不好。
3、如果断开了网络,再试着去查天气,去定位就会有Bug,这是我没有考虑未联网情况的结果。
关于以上3点,这8天来我也有改进:
1、师兄提示给我了线程池这个概念,我就明白了,可以开辟一个线程池,规定此线程池同时工作的线程不能多于5个,由线程池单独管理线程的工作,需要添加线程只需要把线程丢进这个线程池就行了,几行代码搞定:
ExecutorService pool = Executors.newFixedThreadPool(5); //定义一个线程池,同时执行的线程数为5个
Thread t = new Thread(r3);
pool.execute(t);//加入线程池中执行
2、线程的解决方法同上。关于Toast不停弹出,我可以自己定义一个方法,检测Toast有没有makeText,如果没有,则给他添加一个makeText然后让他show()出来,如果已经有就不show(),一旦不show()出来,用户当然看不到。
public void showToast(Context context,String text, int duration) {
//这个方法是定义一个自己的showToast方法,防止按太多次查询广州Toast弹出好多次
if (mToast == null) {
mToast = Toast.makeText(context, text, duration);
mToast.show();
} else {
mToast.setText(text);
mToast.setDuration(duration);
}
}
3、断开网络这种情况我之前其实就又想,能不能定义一个flag来判断是否联网,最后失败了,这几天查了下资料发现有方法来判断是否联网了(哭),接下来就简单了,如果没有联网,就使查询啊,定位啊等等的功能都不能用,加个if条件判断,然后弹个Toast提示用户没联网就好了哈哈。
//判断有无联网
public static boolean checkNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
return false;
} else {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
NetworkInfo netWorkInfo = info[i];
if (netWorkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
return true;
} else if (netWorkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
return true;
}
}
}
}
}
return false;
}
至此解决了以上的问题,8天过去了差不多一半,我又再想能不能再加点功能,于是我就打算在插件上做手脚,然后成功了,具体请看我的博客--插件功能扩展。
然后又过了一天,我就想既然有了语音查天气,何不加个语音播报功能呢,于是我就着手添加功能,做之前还以为很简单的。。可是这个功能搞了我3天才搞定。因为文字转语音(TTS),并没有提供中文的语音包,但是android支持第三方语音包,没办法就下呗,但是别人如果要用这个语音包是没有安装的怎么办- -于是还得把这个apk放在工程文件的assert文件夹里面提示用户安装,然后弄来弄去又知道了从assert文件夹中读出来的东西是流的形式,不可以直接安装,需要将assert文件复制到SD卡上才能使用户安装,这一系列的知识我都是完全陌生的,花了2个通宵去百度去找终于搞定了,这里贴上从assert文件夹copy至SD卡的方法:
//此方法把assert的apk文件通过流的形式复制到SD卡中
public boolean copyApkFromAssets(Context context, String fileName, String path) {
boolean copyIsFinish = false;
try {
InputStream is = context.getAssets().open(fileName);
File file = new File(path);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] temp = new byte[1024];
int i = 0;
while ((i = is.read(temp)) > 0) {
fos.write(temp, 0, i);
}
fos.close();
is.close();
copyIsFinish = true;
} catch (IOException e) {
e.printStackTrace();
}
return copyIsFinish;
}
至于为什么怎么做- -还是渣渣的我是不可能知道的。。我只知道了貌似这样就成功了,然后就通过一个对话框3个选项来引导用户做出选择了:
if(statusTest == TextToSpeech.SUCCESS){
int result = tts.setLanguage(Locale.CHINA);
if(result == TextToSpeech.LANG_NOT_SUPPORTED){
//未安装或者未设置
AlertDialog.Builder builder = new AlertDialog.Builder(MainInterface.instance);
builder.setMessage("此语音功能需要安装科大讯飞语音包支持,若您未曾安装语音包请点击\"安装\",来进行语音包的安装。\n若已安装"
+ "请检查设置-->语言和键盘-->文字转语音(TTS)输出处是否勾选了讯飞语音合成,若没有请勾选。\n"
+ "设置完成后请点击\"重启程序\"来启用语音包。")
.setCancelable(true)
.setTitle("语音支持")
.setPositiveButton("安装", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int id) {
copyApkFromAssets(MainInterface.instance, "iFly_TTS_ICS.apk", Environment.getExternalStorageDirectory().getAbsolutePath()+"/iFly_TTS_ICS.apk");
//如果apk复制成功,则启动intent开始安装程序
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStorageDirectory().getAbsolutePath()+"/iFly_TTS_ICS.apk"),
"application/vnd.android.package-archive");
MainInterface.instance.startActivity(intent);
}
})
.setNegativeButton("设置", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int id){
//跳转到系统设置界面
Intent intent = new Intent("/");
ComponentName cm = new ComponentName("com.android.settings","com.android.settings.LanguageSettings");
intent.setComponent(cm);
intent.setAction("android.intent.action.VIEW");
MainInterface.instance.startActivityForResult(intent , 0);
}
})
.setNeutralButton("重启程序", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainInterface.instance,MainInterface.class);
MainInterface.instance.startActivity(intent);
MainInterface.instance.finish();
MainInterface.instance.overridePendingTransition(R.anim.in_alpha, R.anim.out_alpha);
}
})
.show();
builder.create();
}
if(speechText.indexOf("null") != -1){
speechText = "无记录";
}
tts.speak(speechText,TextToSpeech.QUEUE_FLUSH, null);
}
TextToSpeech.LANG_NOT_SUPPORTED的意思是系统不支持这种语言,原因有可能是未安装或者未设置,因为我现在还不会判断android是否已经安装了语音包这种方法,所以只能在一个if中做处理,以后如果会了,就可以独立判断到底是未安装还是未设置,来做出对应选择,这样用户体验会更加好。
同时这里还有一个Bug,因为我不会判断是否已经安装,所以用户如果一直安装我貌似也没有啥办法- -所以得按着我的提示来做才可以- -这样用户体验好差好差- -如果有会的大大就教一下我把(哭),还有重启程序看得出我这里的重启其实只是个伪重启:关掉再重新启动Activity,没有退出程序。如果我知道有方法可以实现真正的重启程序就好了(笑)。
下午提交了最终项目了,这8天,不,应该说这2个多月过的非常开心,同时也谢谢师兄们带着我这一个刚学完C的菜鸟入门java,android,没啥说的,最后希望我能顺利进研发吧(笑)。