toast源码
⑴ 求助一个Android 文件选择器的源码(用于上传文件时选择并...
打开文件选择器:
private void showFileChooser() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult( Intent.createChooser(intent, "Select a File to Upload"), FILE_SELECT_CODE);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show();
}
}
选择结果:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case FILE_SELECT_CODE:
if (resultCode == RESULT_OK) {
// Get the Uri of the selected file
Uri uri = data.getData();
String path = FileUtils.getPath(this, uri);
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
FileUtils文件
public class FileUtils {
public static String getPath(Context context, Uri uri) {
if ("content".equalsIgnoreCase(uri.getScheme())) {
String[] projection = { "_data" };
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, projection,null, null, null);
int column_index = cursor.getColumnIndexOrThrow("_data");
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
} catch (Exception e) {
// Eat it
}
}
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
}
⑵ 安卓如何实现获取网页源代码
public class GetHtmlCodeActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView textView = (TextView)this.findViewById(R.id.picture_textview);
try {
textView.setText(getPictureData("http://www..com"));
} catch (Exception e) {
Log.e("GetHtmlCodeActivity", e.toString());
Toast.makeText(GetHtmlCodeActivity.this, "网络连接失败", 1).show();
}
}
//得到图片的二进制数据
public String getPictureData(String path) throws Exception{
// 类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。
URL url = new URL("http://www..com/");
// 每个 HttpURLConnection 实例都可用于生成单个请求,
//但是其他实例可以透明地共享连接到 HTTP 服务器的基础网络
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置 URL 请求的方法
conn.setRequestMethod("GET");
//设置一个指定的超时值(以毫秒为单位),
//该值将在打开到此 URLConnection 引用的资源的通信链接时使用。
conn.setConnectTimeout(5 * 1000);
// conn.getInputStream()返回从此打开的连接读取的输入流
InputStream inStream = conn.getInputStream();// 通过输入流获取html数据
byte[] data = readInputStream(inStream);// 得到html的二进制数据
String html = new String(data);
return html;
}
//读取输入流中的数据,返回字节数组byte[]
public byte[] readInputStream(InputStream inStream) throws Exception{
//此类实现了一个输出流,其中的数据被写入一个 byte 数组
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
// 字节数组
byte[] buffer = new byte[1024];
int len = 0;
//从输入流中读取一定数量的字节,并将其存储在缓冲区数组buffer 中
while ((len = inStream.read(buffer)) != -1) {
// 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
outStream.write(buffer, 0, len);
}
inStream.close();
//toByteArray()创建一个新分配的 byte 数组。
return outStream.toByteArray();
}
}
可以看一下这个自己想想哦
⑶ android下打开Web浏览器的几种常见的方法
android下打开Web浏览器的几种常见的方法如下:
一。通过意图实现浏览
//通过下述方法打开浏览器
java">privatevoidopenBrowser(){
//urlText是一个文本输入框,输入网站地址
//Uri是统一资源标识符
Uriuri=Uri.parse(urlText.getText().toString());
Intentintent=newIntent(Intent.ACTION_VIEW,uri);
startActivity(intent);
}
注意:输入URL时,不要忘记“http://”部分。
二。利用视图打开网页,是通过调用WebKit浏览器引擎提供的WebView实现的。
具体源代码如下:
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<LinearLayoutandroid:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<EditText
android:layout_width="240dp"
android:layout_height="wrap_content"
android:id="@+id/etWebSite"
android:hint="输入网址"
android:singleLine="true"
android:layout_marginRight="5dp"
/>
<Button
android:id="@+id/searchBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索"
android:layout_marginRight="5dp"
/>
</LinearLayout>
<LinearLayoutandroid:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/backBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上一页"
android:layout_marginRight="5dp"
/>
<Button
android:id="@+id/nextBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一页"
android:layout_marginRight="5dp"
/>
</LinearLayout>
<WebViewandroid:id="@+id/webView1"android:layout_width="match_parent"
android:layout_height="match_parent"></WebView>
</LinearLayout>
/res/src/com.myandroid
packagecom.myandroid;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.webkit.URLUtil;
importandroid.webkit.WebView;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.Toast;
{
privateButtonschBtn,backBtn,nextBtn;
privateWebViewwebView;
privateEditTextmText;
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
schBtn=(Button)findViewById(R.id.searchBtn);
mText=(EditText)findViewById(R.id.etWebSite);
webView=(WebView)findViewById(R.id.webView1);
backBtn=(Button)findViewById(R.id.backBtn);
nextBtn=(Button)findViewById(R.id.nextBtn);
schBtn.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
//设置可以使用Javascript
webView.getSettings().setJavaScriptEnabled(true);StringstrURI=mText.getText().toString();
//检测网站的合法性
if(URLUtil.isNetworkUrl(strURI)){
webView.loadUrl(strURI);
Toast.makeText(WebViewActivity.this,strURI,Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(WebViewActivity.this,"输入非法网站 "+strURI,Toast.LENGTH_SHORT).show();
}
}
});
backBtn.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
if(webView.canGoBack()){
webView.goBack();
}
}
});
nextBtn.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
if(webView.canGoForward()){
webView.goForward();
}
}
});
}
}
同时还要在AndroidManifest.xml中添加访问因特网的权限:
<uses-permission android:name="android.permission.INTERNET"/>
⑷ 使用系统Toast的问题
记录下在使用系统Toast存在的问题:
1. 当通知洞州乱权限被关闭时华为等手机Toast不显示;
2. Toast队列机制上在不同手机上可能不同;
3. Toast的BadTokenException问题;
当发现系统Toast存在问题时,不少同学使用自定义纳档TYPE_TOAST弹框来实现相同效果.虽然情况下效果都是OK的,但TYPE_TOAST依然会存在问题:
4. Android8.0之后的token null is not valid问题(实测部分机型问题);
5. Android7.1之后,不允许同时展示两个TYPE_TOAST弹窗(实测部分机型问题);
那么解决方案是:
相信不少同学旧项目中封装的ToastUtil都是直接使用的ApplicationContext作为上下文,然后在需要弹窗的时候直接就是ToastUtil.show(str),这样的使用方式对于我们来说是最方便的啦。
当然,使用YToast你也依然可以沿用这种封装方式,但这种方式在下面这个场景中可能会无法成功展示出弹窗(该场景下原生Toast也一样无法弹出),不过请放心不会导致应用崩溃,而且这个场景出现的概率较小,有以下三个必要条件:
1.通知栏权限被关闭(通知栏权限默认都是打开的)
2.非MIUI手机
3.Android8.0以上的部分手机(我最近测试中的几部8.0+设备都不存在该问题)。
不过,如果想要保证在所有场景下都能正常展示弹窗,还是建议在YToast.make(context)时传入Activity作为上下文,这样在该场景下YToast会启用ActivityToast展示出弹窗。
接下来再详细分析下上面提到的五个问题。
看下方Toast源码中的show()方法,通过AIDL获迹纤取到INotificationManager,并将接下来的显示流程控制权交给NotificationManagerService。NMS中会对Toast进行权限校验,当通知权限校验不通过时,Toast将不做展示。
当然不同ROM中NMS可能会有不同,比如MIUI就对这部分内容进行了修改,所以小米手机关闭通知权限不会导致Toast不显示。
如何解决这个问题?只要能够绕过NotificationManagerService即可。
YToast通过使用TYPE_TOAST实现全局弹窗功能,不使用系统Toast,也没有使用NMS服务,因此不受通知权限限制。
我找了四台设备,创建两个Gravity不同的Toast并调用show()方法,结果出现了四种展示效果:
造成这个问题的原因应该是各大厂商ROM中NMS维护Toast队列的逻辑有差异。
同样的,YToast内部也维护着自己的队列逻辑,保证在所有手机上使用DToast的效果相同。
YToast中多个弹窗连续出现时:
相同优先级时,会终止上一个,直接展示后一个;
不同优先级时,如果后一个的优先级更高则会终止上一个,直接展示后一个。
什么情况下windowToken会失效?
UI线程发生阻塞,导致TN.show()没有及时执行,当NotificationManager的检测超时后便会删除WMS中的该token,即造成token失效。
如何解决?
因此对于8.0之前的我们也需要做相同的处理。YToast是通过反射完成这个动作,具体看下方实现:
Android8.0后对WindowManager做了限制和修改,特别是TYPE_TOAST类型的窗口,必须要传递一个token用于校验。
API25:(PhoneWindowManager.java源码)
API26:(PhoneWindowManager.java源码)
为了解决问题一,DovaToast不得不选择绕过NotificationManagerService的控制,但由于windowToken是NMS生成的,绕过NMS就无法获取到有效的windowToken,于是作为TYPE_TOAST的DovaToast就可能陷入第四个问题。
因此,DToast选择在DovaToast出现该问题时引入ActivityToast,在DovaToast无法正常展示时创建一个依附于Activity的弹窗展示出来,不过ActivityToast只会展示在当前Activity,不具有跨页面功能。
如果说有更好的方案,那肯定是去获取悬浮窗权限然后改用TYPE_PHONE等类型,但悬浮窗权限往往不容易获取,目前来看恐怕除了微信其他APP都不能保证拿得到用户的悬浮窗权限。
YToast的弹窗策略就是同一时间最多只展示一个弹窗,逻辑上就避免了此问题。因此仅捕获该异常。
其他建议
如果能够接受Toast不跨界面的话,建议使用SnackBar
⑸ android studio代码问题 怎么读取短信的具体内容。
1.点击一个按钮就会显示系统的联系人列表,当用户点击联系人之后就会看到详细的名字和电话。
2.具体的代码如下:首先在AndroidManifest.xml文件中配置用户权限。
<uses-permission android:name="android.permission.READ_CONTACTS"/>11
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.dragon.testevent.MainActivity">
⑹ android的toast怎么自定义显示时间长度
Android中Toast的显示时间为特定时间且不可更改,但是有时候我们开发设计需要让Toast显示更长时间,或者自己完全控制Toast的显示和关闭。通过查看Toast类的源码,可以看出,这有点难为它了,Toast类本身并没有提供相应方法。
但是通过源码的查看,还是可以看出点眉头。源码分析思路在这里转eoe里的一篇文章,思路较为清晰:
转:
Toast信息提示框之所以在显示一定时间后会自动关闭,是因为在系统中有一个Toast队列。系统会依次从队列中取(出队列)一个Toast,并 显示它。在显示一段时间后,再关闭,然后再显示下一个Toast信息提示框。
直到Toast队列中所有Toast都显示完为止。那么有些时候需要这个Toas t信息提示框长时间显示,直到需要关闭它时通过代码来控制,而不是让系统自动来关闭Toast信息提示框。
不过这个要求对于Toast本身来说有些过 分,因为Toast类并没有提供这个功能。虽然如此,但方法总比问题多。通过一些特殊的处理还是可以实现这个功能的,而且并不复杂。
Toast信息提示框需要调用Toast.show方法来显示。下面来看一下show方法的源代码。
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();
String pkg = mContext.getPackageName();
TN tn = mTN;
try {
// 将当前Toast加入到Toast队列
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
复制代码
show方法的代码并不复杂,可以很容易找到如下的代码。
service.enqueueToast(pkg, tn, mDuration);
复制代码
从上面的代码可以很容易推断出它的功能是将当前的Toast加入到系统的Toast队列中。
看到这里,各位读者应该想到。虽然show方法的表面功能是显示Toast信息提示框,但其实际的功能是将Toast加入到队列中,再由系统根据Toast队列来显示Toast信息提示框。那么我们经过更进一步地思考,可以大胆地做出一个初步的方案。
既然系统的Toast队列可以显示Toast信息提示框,那么我们为什么不可以自己来显示它呢?
这样不是可以自己来控制Toast的信息提示框的显示和关闭了吗!当然,这就不能再调用show方法来显示Toast信息提示框了(因为show方法会将Toast加入队列,这样我们就控制不了Toast了)。
既然初步方案已拟定,现在就来实施它。先在Toast类找一下还有没有其他的show方法。
结果发现了一个TN类,该类是Toast的一个内嵌类。在TN类中有一个show方法。TN是ITransientNotification.Stub的子类。从ITransientNotification和TN类中的show方法初步推断(因为Transient的中文意思是“短暂的”)系统是从Toast队列中获得了Toast对象后,利用TN对象的show方法显示Toast,再利用TN.hide方法来关闭Toast。
首先声明,这只是假设,我们还不知道这么做是否可行!当然,这也是科学研究的一般方法,先推断或假设,然后再证明推断或假设。
现在关键的一步是获得TN对象。遗憾的是TN被声明成private类型,外部无法访问。不过别着急。在Toast类中有一个mTN变量。虽然不是public变量,但仍然可以通过反射技术访问该变量。mTN变量会在创建Toast对象时初始化。
因此,只要获得mTN变量,就获得了TN对象。下面的代码显示了一个永远不会自动关闭的Toast信息提示框。
// 先创建一个Toast对象Toast toast = Toast.makeText(this, "永不消失的Toast", Toast.LENGTH_SHORT);// 设置Toast信息提示框显示的位置(在屏幕顶部水平居中显示)toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);try{
// 从Toast对象中获得mTN变量Field field = toast.getClass().getDeclaredField("mTN");
field.setAccessible(true);
Object obj = field.get(toast);
// TN对象中获得了show方法
Method method = obj.getClass().getDeclaredMethod("show", null);
// 调用show方法来显示Toast信息提示框
method.invoke(obj, null);
}
catch (Exception e)
{
}
复制代码
上面的代码中try{…}catch(…){…}语句中的代码是关键。先利用事先创建好的Toast对象获得了mTN变量。然后再利用反射技术获得了TN对象的show方法。
关闭Toast和显示Toast的方法类似,只是需要获得hide方法,代码如下:
try
{
// 需要将前面代码中的obj变量变成类变量。这样在多个地方就都可以访问了
Method method = obj.getClass().getDeclaredMethod("hide", null);
method.invoke(obj, null);
}
catch (Exception e)
{
}
复制代码
上面的代码已经很完美地实现了通过代码控制Toast信息提示框显示和关闭的功能。
但如果想实现得更完美,可以在Android SDK源代码中找一个叫ITransientNotification.aidl的文件(该文件是AIDL服务定义文件,将在后面详细介绍),并在Android工程的src目录中建一个android.app包,将这个文件放到这个包中。
然后ADT会自动在gen目录中生成了一个android.app包,包中有一个ITransientNotification.java文件。由于Android SDK自带的ItransientNotification接口属于内部资源,外部程序无法访问,因此,只能将从Toast对象中获得的mTN变量转换成刚才生成的ITransientNotification对象了。
这样就不需要使反射技术获得show和hide方法了。
经过改良的显示和关闭Toast信息提示框的代码如下:
ITransientNotification notification = (ITransientNotification) field.get(toast);
// 显示Toast信息提示框
notification.show();
// 关闭Toast信息提示框
notification.hide();
复制代码
最后整理代码如下:
Java代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class TestToastActivity extends Activity {
private Button showtoast,closetoast;
private Toast toast;
private Field field;
private Object obj;
private Method showMethod,hideMethod;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//初始化按钮组件
showtoast = (Button)this.findViewById(R.id.showtoast);
closetoast = (Button)this.findViewById(R.id.closetoast);
//设置组件监听
showtoast.setOnClickListener(new MyOnClickListener());
closetoast.setOnClickListener(new MyOnClickListener());
//创建Toast对象
toast = Toast.makeText(this, "Toast自定义显示时间测试", 1);
toast.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
//利用反射技术拿到mTN对象
reflectionTN();
}
class MyOnClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.showtoast:
try {
showMethod.invoke(obj, null);//调用TN对象的show()方法,显示toast
} catch (Exception e) {
e.printStackTrace();
}
break;
case R.id.closetoast:
try {
hideMethod.invoke(obj, null);//调用TN对象的hide()方法,关闭toast
} catch (Exception e) {
e.printStackTrace();
}
break;
default:
break;
}
}
}
private void reflectionTN() {
try {
field = toast.getClass().getDeclaredField("mTN");
field.setAccessible(true);
obj = field.get(toast);
showMethod = obj.getClass().getDeclaredMethod("show", null);
hideMethod = obj.getClass().getDeclaredMethod("hide", null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
复制代码