下面小编来给各位同学介绍一篇关于Android中Movie导入播放GIF图片文件异常IOException.reset的解决办法,希望些方法对你有帮助。
使用Movie播放GIF图片时,能正常导入assets中的gif文件,如:
代码如下 |
复制代码 |
is=context.getResources().openRawResource(R.drawable.mygif);
movie = Movie.decodeStream(is);
|
然而把网络图片加载到本地后,却报以下错误:
代码如下 |
复制代码 |
java.io.IOException
at java.io.InputStream.reset(InputStream.java:218)
at android.graphics.Movie.decodeStream(Native Method)
at android.graphics.Movie.decodeTempStream(Movie.java:74)
at android.graphics.Movie.decodeFile(Movie.java:59)
|
我是在Androidmanifest.xml声明了权限:
代码如下 |
复制代码 |
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
解决办法:
代码如下 |
复制代码 |
InputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(new File(getCacheDir(), "mygif.gif")), 16 * 1024);
is.mark(16 * 1024);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
movie = Movie.decodeStream(is);
|
本文章来给大家介绍在android开发中我们要对EditText限制,只能让用户输入像数字 字母 邮箱地址,电话号之类的,其它的不能输入。
下面以数字、电话为例讲述EditText怎么设置输入类型,其他类型可以参考InputType类。
1) 只能输入数字
代码如下 |
复制代码 |
EditText et = (EditText) findViewById(R.id.etTest);
et.setInputType(InputType.TYPE_CLASS_NUMBER);
|
2) 只能输入电话号码
代码如下 |
复制代码 |
EditText et = (EditText) findViewById(R.id.etTest);
et.setInputType(InputType.TYPE_CLASS_PHONE);//电话
|
3) 邮箱地址
代码如下 |
复制代码 |
EditText et = (EditText) findViewById(R.id.etTest);
et.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
4) 禁止输入任何文本
代码如下 |
复制代码 |
EditText et = (EditText) findViewById(R.id.etTest);
et.setInputType(InputType.TYPE_NULL);
|
// 禁止输入(不弹出输入法)上述也是隐藏输入法的一种方式,还有另外一种隐藏办法,
可查看android隐藏IME(输入法)输入框
不让程序默认升起IME输入框有两种方法:
1.让EditText失去焦点,使用EditText的clearFocus方法
2.强制隐藏Android输入法窗口,在IME类中我们通过实例化输入法控制对象,通过hideSoftInputFromWindow来隐藏IME输入框。
代码
代码如下 |
复制代码 |
Toast.makeText(WindowBackgroundColorActivity.this, "焦点改变", Toast.LENGTH_SHORT).show();
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
//第一种方法
//imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_NOT_ALWAYS);
//第二种方法
imm.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
参考代码:
代码如下 |
复制代码 |
<EditText android:id="@+id/etTest" android:inputType="number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
|
本文章来给各位同学介绍一个关于Android Spinner实现省市区三级联动程序代码,有兴趣的同学可进入参考。
省市区三级联动,采用的是sqlite本地数据库,需要使用SimpleCursorAdapter类来配合下拉列表Spinner实现。关于Spinner和SimpleCursorAdapter的组合请看,
Android使用SimpleCursorAdapter填充下拉列表Spinner用法
先贴上Spinner和SimpleCursorAdapter整合的代码:
代码如下 |
复制代码 |
Cursor c = getContentResolver().query(Table.Region.CONTENT_URI, null, Table.Region.PARENT_ID+"="+parentRegionId, null, Table.Region._ID +" asc");
final String[] columns = new String[] { Table.Region.REGION_NAME };
final int[] to = new int[] { android.R.id.text1 };
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c, columns, to);
mAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
view.setAdapter(mAdapter);
|
下面我们再来看至于省份城市地区三级联动效果
三级联动实现原理:用户选择省份后,根据省份Id加载对应的城市列表,由于Spinner默认选择第一项,即城市列表加载完后,又会加载对应的地区列表信息。
使用Spinner的OnItemSelectedListener监听器类实现三级联动:
代码如下 |
复制代码 |
//加载省份
updateRegionInfo(spinner_province, 1);
spinner_province.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
//加载下一级(城市)
Cursor selectedCursor = (Cursor) parent.getSelectedItem();
updateRegionInfo(spinner_city, CursorUtil.getInt(selectedCursor, Table.Region.REGION_ID));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner_city.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
//加载下一级(地区)
Cursor selectedCursor = (Cursor) parent.getSelectedItem();
updateRegionInfo(spinner_district, CursorUtil.getInt(selectedCursor, Table.Region.REGION_ID));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
|
使用SimpleCursorAdapter绑定Sqlite数据库到Spinner
代码如下 |
复制代码 |
private void updateRegionInfo(Spinner view, int parentRegionId) {
final ListAdapter adapter = (ListAdapter) view.getAdapter();
if(null != adapter && adapter instanceof CursorAdapter) {
final CursorAdapter cursorAdapter = (CursorAdapter) adapter;
cursorAdapter.changeCursor(null);
view.setAdapter(null);
}
Cursor c = getContentResolver().query(Table.Region.CONTENT_URI, null, Table.Region.PARENT_ID+"="+parentRegionId, null, Table.Region._ID +" asc");
final String[] columns = new String[] { Table.Region.REGION_NAME };
final int[] to = new int[] { android.R.id.text1 };
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c, columns, to);
mAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
view.setAdapter(mAdapter);
}
|
今天发现android开发中有一个android:ellipsize=marquee,这个感觉像html中的marquee功能,可以实现滚动效果,于是测试了一下,结果不行呀,后来百度了一下解决办法,下面大家一起来看看。
若要让TextView里的文本滚动,必须满足以下几个因素:
1,TextView里文本宽度超过TextView的宽度
2,android:ellipsize="marquee"
3,只有在TextView获取到焦点时,才会滚动.所以加上android:focusableInTouchMode="true" android:focusable="true"
最容易忽略的是第三条.
滚动重复次数设置:
android:marqueeRepeatLimit="marquee_forever"
看一个TextView属性android:ellipsize实现跑马灯效果
Android系统中TextView实现跑马灯效果,必须具备以下几个条件:
1、android:ellipsize=”marquee”
2、TextView必须单行显示,即内容必须超出TextView大小
3、TextView要获得焦点才能滚动
XML代码:
android:ellipsize="marquee", android:singleLine="true"
Java代码:
mTVText.setText("哼唱接撒砥砺风节雷锋精神http://www.111cn.net/,很长很长很长很长很长很长的数据");
mTVText.setSingleLine(true);
mTVText.setEllipsize(TruncateAt.MARQUEE);
PS: TextView.setHorizontallyScrolling(true); //让文字可以水平滑动
TextView还可以设置跑马灯效果的滚动次数,如下:
XML代码设置:
android:marqueerepeatlimit="1"。1代表1次,-1代表无限循环。
Java代码设置:
mTVText.setMarqueeRepeatLimit(-1);
今天文章来给各位安卓开者提供两个在应用中不错的实例,在安卓一个实例手动更新模块和自动更新模块程序代码,希望此代码对各位有帮助。
这里介绍了实现原理,为了使用方便,简单封装了一个类Updater。用法很简单。好吧,为了支持多语言,其实还是有些繁琐。
用法:
strings.xml 中用到的字符定义
其他语言的自己添加,下面的实例程序中,中英文都有
代码如下 |
复制代码 |
<string name="update">check for update</string>
<string name="help">Help?</string>
<string name="help_content">I am helper,muhaha~~~</string>
<string name="found_newversion">Found a new version</string>
<string name="need_update">need update?</string>
<string name="alertdialog_title">Software Update</string>
<string name="alertdialog_update_button">Update</string>
<string name="alertdialog_cancel_button">Not now</string>
<string name="progressdialog_title">Downloading update</string>
<string name="progressdialog_message">Please wait a moment</string>
|
在AndroidManifest.xml添加更新需要用到的权限
代码如下 |
复制代码 |
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<uses-permission android:name="android.permission.INSTALL_PACKAGES"></uses-permission>
|
检查更新,如发现有新版本会弹出提示
代码如下 |
复制代码 |
private boolean checkUpdate() {
Updater updater = new Updater("http://127.0.0.1/", this);
if (updater.needUpdate())//found update
updater.showNewVersionUpdate();
else {
}
return true;
} |
自动更新
之前帮别人定制的一个android应用需要加个自动更新的功能。在 Market 里的应用是无需操心此事的,但像我这种定制的程序就需要自己实现。
原理相当简单,检查更新的时候,通过指定的URL获取服务器端版本信息。比较版本,如果更新,访问服务器端返回的apk的URL地址,下载,安装。各种 Makert 也是通过类似的机制实现的。原理搞清楚了,代码就相当简单了。
获取apk的VesionName,即AndroidManifest.xml中定义的android:versionName
代码如下 |
复制代码 |
public String getVesionName(Context context) {
String versionName = null;
try {
versionName = context.getPackageManager().getPackageInfo("net.vpntunnel", 0).versionName;
} catch (NameNotFoundException e) {
Log.e(TAG, e.getMessage());
}
return versionName;
}
|
更新以及安装程序需要的权限,在AndroidManifest.xml中添加
代码如下 |
复制代码 |
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<uses-permission android:name="android.permission.INSTALL_PACKAGES"></uses-permission>
|
获取apk的versionCode,即AndroidManifest.xml中定义的android:versionCode
代码如下 |
复制代码 |
public int getVersionCode(Context context) {
int versionCode = 0;
try {
versionCode = context.getPackageManager().getPackageInfo("net.vpntunnel", 0).versionCode;
} catch (NameNotFoundException e) {
Log.e(TAG, e.getMessage());
}
return versionCode;
}
|
服务器端version.JSON,包含apk路径以及版本信息
代码如下 |
复制代码 |
{
"ApkName":"NAME",
"ApkFullName":"NAME_1.0.5.apk",
"VersionName":"1.0.5",
"VersionCode":3
}
|
获取远程服务器的版本信息
代码如下 |
复制代码 |
private void getRemoteJSON(string host) throws ClientProtocolException, IOException, JSONException {
String url = String.format("http://%s/%s", host, VER_JSON);
StringBuilder sb = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpParams httpParams = client.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
HttpResponse response = client.execute(new HttpGet(url));
HttpEntity entity = response.getEntity();
if (entity != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"), 8192);
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "n");
}
reader.close();
}
JSONObject object = (JSONObject) new JSONTokener(sb.toString()).nextValue();
this.apkFullName = object.getString("ApkFullName");
this.versionName = object.getString("VersionName");
this.versionCode = Integer.valueOf(object.getInt("VersionCode"));
}
|
发现更新的提醒窗口,通过AlertDialog实现
代码如下 |
复制代码 |
private void shoVersionUpdate(String newVersion, final String updateURL) {
String message = String.format("%s: %s, %s", mContext.getString(R.string.found_newversion), newVersion, mContext.getString(R.string.need_update));
AlertDialog dialog = new AlertDialog.Builder(mContext).setTitle(mContext.getString(R.string.alertdialog_title)).setMessage(message)
// update
.setPositiveButton(mContext.getString(R.string.alertdialog_update_button), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
pBar = new ProgressDialog(mContext);
pBar.setTitle(mContext.getString(R.string.progressdialog_title));
pBar.setMessage(mContext.getString(R.string.progressdialog_message));
pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.dismiss();
downFile(updateURL);
}
// cancel
}).setNegativeButton(mContext.getString(R.string.alertdialog_cancel_button), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
}).create();
dialog.show();
}
|
下载新版的apk文件,存放地址可以放到SD卡中。通过Environment.getExternalStorageDirectory()获取SD卡中的路径
代码如下 |
复制代码 |
private void downFile(final String url) {
pBar.show();
new Thread() {
public void run() {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse response;
try {
response = client.execute(get);
HttpEntity entity = response.getEntity();
long length = entity.getContentLength();
InputStream is = entity.getContent();
FileOutputStream fileOutputStream = null;
if (is != null) {
File f = new File(UPDATE_DIR);
if (!f.exists()) {
f.mkdirs();
}
fileOutputStream = new FileOutputStream(new File(UPDATE_DIR, updateFileName));
byte[] buf = new byte[1024];
int ch = -1;
int count = 0;
while ((ch = is.read(buf)) != -1) {
fileOutputStream.write(buf, 0, ch);
count += ch;
Log.d(TAG, String.valueOf(count));
if (length > 0) {
}
}
}
fileOutputStream.flush();
if (fileOutputStream != null) {
fileOutputStream.close();
}
handler.post(new Runnable() {
public void run() {
pBar.cancel();
installUpdate();
}
});
} catch (Exception e) {
pBar.cancel();
Log.e(TAG, e.getMessage());
}
}
}.start();
}
|
安装更新
代码如下 |
复制代码 |
private void installUpdate() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(UPDATE_DIR, updateFileName)), "application/vnd.android.package-archive");
mContext.startActivity(intent);
}
|
至此更新需要函数就完成了,根据自己的业务逻辑组合一下,更新功能就搞定了。也可以稍微封装下,写成一个通用类,下次就可以直接用了。
标签:[!--infotagslink--]