Android应用退出功能实现方法
虽然文档里没有明确说明,但假如这是常用功能,应该有简便的方法实现,而实际上要靠代码"退出"一个应用并非易事。以下总结了能够模拟退出效果的两个方案:
方案1:打开系统主屏来模拟应用退出的效果,这和用户按Home键没有什么区别。
代码如下 | 复制代码 |
Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); |
方案2:直接杀掉当前应用进程。这个方法太暴力了,我找到一段iOS开发文档,上面强烈不建议使用杀进程的方式来退出应用,原因也适用于Android系统:这样退出的效果容易让用户以为应用崩溃了。
代码如下 | 复制代码 |
int pid=android.os.Process.myPid(); android.os.Process.killProcess(pid); |
此外,有人建议调用System.exit(0)退出应用,实际测试发现这个方法常常只能关闭当前Activity,或是根本不起作用。
由此可以看出,Android系统的设计里本来就没有"退出应用"的机制,当用户按下Home键或在应用首页里按下Back键后,应用被置于后台,而何时要彻底杀掉应用进程则由系统决定。Android和iOS都已抛弃了"退出应用"这个概念,对手机用户来讲,他只需要知道"启动应用"——概念越少越简单。
但作为一个好的应用,应该有自己的退出功能。
"应用退出"一般有以下几种方式:
一、退出起始的Activity,这样后面的Activity系统会自己destory。(通常需要很长时间)
二、为每一个Activity覆写OnKeyDown()方法,当每次按返回键的时候,finish掉当前的Activity。(通常所有的Activity都会继承一个BaseActivity,这样,只需要写一遍就好)
三、利用List,每次调用新的Activity时,保存当前的Activity,当应用退出时,一次性finish所有的Activity。(较为理想的解决方案)
今天,我们就利用第三种方式来为我们的应用添加"退出"功能。
1.编写一个class继承Application
代码如下 | 复制代码 |
public class AppClose extends Application {
private List<Activity> mainActivity = new ArrayList<Activity>(); public List<Activity> MainActivity() { return mainActivity; } public void addActivity(Activity act) { mainActivity.add(act); } public void finishAll() { for (Activity act : mainActivity) { if (!act.isFinishing()) { act.finish(); } } mainActivity = null; } } |
2.在Activity 中的oncreate方法中添加
代码如下 | 复制代码 |
AppClose appState = (AppClose)this.getApplication(); appState.addActivity(this); // setContentView(R.layout.main); |
3.//设定点击事件
代码如下 | 复制代码 |
button.setonclick….(){
AppClose appState = (AppClose)getApplicationContext(); appState.finishAll(); }
|
4.在注册清单文件中
给application添加属性 android:name=".AppClose"
昨天在做一个安卓小应用程序,要实现调用系统相机程序实现拍照,然后把拍的照片返回给我的程序进行剪辑功能,我们主要是用到了Camera类,下面我总结了一些操作方法,下面分享给大家。
调用系统照相机拍照并剪辑
在Android开发过程中,很多时候我们都需要调用照相机拍照,尤其在发布微博的时候。
自己继承Camera类写一个拍照功能显然不是最好的方案,因为我们不能考虑的非常全面。
这个时候,调用系统的照相机无疑是一个很好的解决方法。
下面,我们就写一个调用系统照相机拍照并对照片进行剪辑。
代码如下 | 复制代码 |
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/","temp.jpg"))); startActivityForResult(intent, 1); |
上面的代码就是调用系统照相机拍照,并保存到sdcard目录下temp.jpg
但这个时候还不够,因为通常情况,照相机拍的照片尺寸都很大,显然不能用于上传,我们需要对照片进行剪辑。
代码如下 | 复制代码 |
public void startPhotoZoom(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, IMAGE_UNSPECIFIED); intent.putExtra("crop", "true"); // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // outputX, outputY 是裁剪图片宽高 intent.putExtra("outputX", 250); intent.putExtra("outputY", 250); intent.putExtra("return-data", true); startActivityForResult(intent, PHOTORESOULT); }
|
上面的代码实现了图片的剪辑,我们只需要传入相应的Uri即可,接下来我们传入Uri。
代码如下 | 复制代码 |
File picture = new File(Environment.getExternalStorageDirectory()+"/" + "temp.jpg"); startPhotoZoom(Uri.fromFile(picture)); |
当然,剪辑完了,我们肯定要拿到剪辑后的照片。
代码如下 | 复制代码 |
if (requestCode == PHOTORESOULT) { Bundle extras = data.getExtras(); if (extras != null) { Bitmap photo = extras.getParcelable("data"); ByteArrayOutputStream stream = new ByteArrayOutputStream(); if(photo!=null){ photo.compress(Bitmap.CompressFormat.JPEG, 75, stream);// (0 – 100)压缩文件 pic.setImageBitmap(photo); } } }
|
android调用系统照相机拍照并剪辑
这样,我们就通过调用系统照相机,实现拍照并剪辑图片的功能。
1.调用系统的照相机程序
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, TAKE_PHOTO_WITH_DATA);
2.在onActivityResult中处理返回的data
final Bitmap photo = data.getParcelableExtra("data");
如果不需要做剪切处理就可以直接使用图片了,比如输出到ImageView上
imageView.setImageBitmap(photo);
如果需要做剪切处理,就继续向下执行
3.做剪切处理
代码如下 | 复制代码 |
Intent intent = new Intent("com.android.camera.action.CROP"); intent.setType("image/*"); intent.putExtra("data", data); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 128); intent.putExtra("outputY", 128); intent.putExtra("return-data", true); startActivityForResult(intent, PHOTO_PICKED_WITH_DATA); |
4.在onActivityResult中处理
与第二步相同。
完整代码:
代码如下 | 复制代码 |
public class SdCardUriTestActivity extends Activity { 布局文件略 |
实例
代码如下 | 复制代码 |
public String getLocalIpAddress() { public String getLocalMacAddress(Context context) { |
安卓4.0系统的手机,按上面的方法默认会先获取到ipv6的地址,有时候我们只想要ipv4的地址
代码如下 | 复制代码 |
/** * 用来获取手机拨号上网(包括CTWAP和CTNET)时由PDSN分配给手机终端的源IP地址。 * * @return * @author SHANHY */ public static String getPsdnIp() { try { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) { //if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet6Address) { return inetAddress.getHostAddress().toString(); } } } } catch (Exception e) { } return ""; } |
1.消息推送机制
服务器器端需要变被动为主动,通知客户一些开发商认为重要的信息,无论应用程序是否正在运行或者关闭。
我想到了一句话:don't call me,i will call you!
qq今天在右下角弹出了一个对话框:"奥巴马宣布本拉登挂了…",正是如此。
自作聪明,就会带点小聪明,有人喜欢就有人讨厌。
2.独立进程
无论程序是否正在运行,我们都要能通知到客户,我们需要一个独立进程的后台服务。
我们需要一个独立进程的后台服务。
在androidmanifest.xml中注册service时,有一个android:process属性,如果这个属性以"."开头,则为此服务开启一个
全局的独立进程,如果以":"开头则为此服务开启一个为此应用私有的独立进程。举个具体的例子吧,我们新建了一个
application,创建了主进程com.cnblogs.tianxia,那么:
代码如下:
<!–下面会创建一个全局的com.cnblogs.tianxia.message的独立进程–>
<service android:name=".service.messageservice" android:label="消息推送" android:process=".message" />
<!–或者–>
<!–下面会创建一个应用私有的com.cnblogs.tianxia:message的独立进程–>
<service android:name=".service.messageservice" android:label="消息推送" android:process=":message" />
我们没必要建立一个全局的,本文选择第二种方案,创建一个当前应用私有的独立进程。
3.通知用户和点击查看
public class messageservice extends service {
//获取消息线程
private messagethread messagethread = null;
//点击查看
private intent messageintent = null;
private pendingintent messagependingintent = null;
//通知栏消息
private int messagenotificationid = 1000;
private notification messagenotification = null;
private notificationmanager messagenotificatiomanager = null;
public ibinder onbind(intent intent) {
return null;
}
@override
public int onstartcommand(intent intent, int flags, int startid) {
//初始化
messagenotification = new notification();
messagenotification.icon = r.drawable.icon;
messagenotification.tickertext = "新消息";
messagenotification.defaults = notification.default_sound;
messagenotificatiomanager = (notificationmanager)getsystemservice(context.notification_service);
messageintent = new intent(this, messageactivity.class);
messagependingintent = pendingintent.getactivity(this,0,messageintent,0);
//开启线程
messagethread = new messagethread();
messagethread.isrunning = true;
messagethread.start();
return super.onstartcommand(intent, flags, startid);
}
/**
* 从服务器端获取消息
*
*/
class messagethread extends thread{
//运行状态,www.3ppt.com下一步骤有大用
public boolean isrunning = true;
public void run() {
while(isrunning){
try {
//休息10分钟
thread.sleep(600000);
//获取服务器消息
string servermessage = getservermessage();
if(servermessage!=null&&!"".equals(servermessage)){
//更新通知栏
messagenotification.setlatesteventinfo(messageservice.this,"新消息","奥巴马宣布,本拉
登兄弟挂了!"+servermessage,messagependingintent);
messagenotificatiomanager.notify(messagenotificationid, messagenotification);
//每次通知完,通知id递增一下,避免消息覆盖掉
messagenotificationid++;
}
} catch (interruptedexception e) {
e.printstacktrace();
}
}
}
}
/**
* 这里以此方法为服务器demo,仅作示例
* @return 返回服务器要推送的消息,否则如果为空的话,不推送
*/
public string getservermessage(){
return "yes!";
}
}
其中messageactivity是点击跳转的activity,负责处理查看详细信息。
我们在其他activity中调用一下:
代码如下:
boolean ismessagepush = true;//不开启就设置为false;
…
if(ismessagepush){
startservice(new intent(this, messageservice.class))
};
运行一下:
4.停止服务
1 stopservice(new intent(myactivity.this,messageservice.class));
2 setmessagepush(false);//设置配置文件或数据库中flag为false
运行一下,停止服务后,却出乎意料的并没有停下来,怎么回事?是不是代码写错了?
代码没有错,错在我们停止了服务,却没有停止进程,退出线程。
5.退出线程
实践证明,thread的stop()方法并不可靠。但是我们有其他的办法。
在代码面前,程序员就是上帝。
退出线程有两种方法。
第一种方法,强制退出。
//杀死该线程所在的进程,自然就退出了
system.exit(0);
第二种方法,设置isrunning为false。
//前面说到了isrunning这个标志,设置为false后,线程的执行就从while循环中跳出来了,然后自然结束掉了
messagethread.isrunning = false;
综合一下,我们在messageservice中重载ondestroy()方法如下:
代码如下:
@override
public void ondestroy() {
system.exit(0);
//或者,二选一,推荐使用system.exit(0),这样进程退出的更干净
//messagethread.isrunning = false;
super.ondestroy();
}
当控件本身layout_width设置为fill_parent的时候,layout_weight数值越小,所占空间越大,但尽可能大是有限度的,即fill_parent.
当控件本身layout_width设置为wrap_content的时候,layout_weight数值越小,所占空间也越小,但这个小是有限度的,即wrap_content.
例子
看了一下源码,虽说不太懂,但了解了下大概意思,按照自己的理解总结一下,直接写一下简化的代码吧(下面的代码是LinearLayout源文件中一部分的精简,变量名称含义可能不准确,为叙述方便暂作此解释):
代码如下 | 复制代码 |
//Either expand children with weight to take up available space or if (child == null || child.getVisibility() == View.GONE) { float childExtra = lp.weight; |
变量含义
widthSize: LinearLayout的宽度
mTotalLength: 所有子View的宽度的和(还没用考虑layout_weight)
totalWeight: 所有子View的layout_weight的和
mWeihtSUm: LinearLayout的android:weightSum属性
过程分析:
首先计算出额外空间(可以为负)如果额外空间不为0并且有子View的layout_weight不为0的话按layout_weight分配额外空间:
代码如下 | 复制代码 |
int delta = widthSize - mTotalLength; |
如果LinearLayout设置了weightSum则覆盖子View的layout_weight的和:
代码如下 | 复制代码 |
float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight; |
然后遍历LinearLayout的子元素,如果不为null且Visibility不为GONE的话,取得它的LayoutParams,如果它的layout_weight大于0,根据weightSum与它的weight计算出分配给它的额外空间
代码如下 | 复制代码 |
if (childExtra > 0) { int childWidth = child.getMeasuredWidth() + share; |
例子
代码如下 | 复制代码 |
|
相关文章
php 中file_get_contents超时问题的解决方法
file_get_contents超时我知道最多的原因就是你机器访问远程机器过慢,导致php脚本超时了,但也有其它很多原因,下面我来总结file_get_contents超时问题的解决方法总结。...2016-11-25- 相信很多站长都遇到过这样一个问题,访问页面时出现408错误,下面一聚教程网将为大家介绍408错误出现的原因以及408错误的解决办法。 HTTP 408错误出现原因: HTT...2017-01-22
- php如何实现抓取网页图片,相较于手动的粘贴复制,使用小程序要方便快捷多了,喜欢编程的人总会喜欢制作一些简单有用的小软件,最近就参考了网上一个php抓取图片代码,封装了一个php远程抓取图片的类,测试了一下,效果还不错分享...2015-10-30
- 下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
- ps软件是现在非常受大家喜欢的一款软件,有着非常不错的使用功能。这次文章就给大家介绍下ps把文字背景变透明的操作方法,喜欢的一起来看看。 1、使用Photoshop软件...2017-07-06
intellij idea快速查看当前类中的所有方法(推荐)
这篇文章主要介绍了intellij idea快速查看当前类中的所有方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-09-02- 1.在没有设置默认值的情况下: 复制代码 代码如下:SELECT userinfo.id, user_name, role, adm_regionid, region_name , create_timeFROM userinfoLEFT JOIN region ON userinfo.adm_regionid = region.id 结果:...2014-05-31
js导出table数据到excel即导出为EXCEL文档的方法
复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta ht...2013-10-13- 批量更新mysql更新语句很简单,更新一条数据的某个字段,一般这样写:复制代码 代码如下:UPDATE mytable SET myfield = 'value' WHERE other_field = 'other_value';如果更新同一字段为同一个值,mysql也很简单,修改下where即...2013-10-04
- 本文涉及的主题虽然很基础,在许多人看来属于小伎俩,但在JavaScript基础知识中属于一个综合性的话题。这里会涉及到对象属性的封装、原型、构造函数、闭包以及立即执行表达式等知识。公有方法 公有方法就是能被外部访问...2015-11-08
- ps软件是一款非常不错的图片处理软件,有着非常不错的使用效果。这次文章要给大家介绍的是ps怎么制作倒影,一起来看看设计倒影的方法。 用ps怎么做倒影最终效果̳...2017-07-06
安卓手机wifi打不开修复教程,安卓手机wifi打不开解决方法
手机wifi打不开?让小编来告诉你如何解决。还不知道的朋友快来看看。 手机wifi是现在生活中最常用的手机功能,但是遇到手机wifi打不开的情况该怎么办呢?如果手机wifi...2016-12-21- 最近想自学PHP ,做了个验证码,但不知道怎么搞的,总出现一个如下图的小红叉,但验证码就是显示不出来,原因如下 未修改之前,出现如下错误; (1)修改步骤如下,原因如下,原因是apache权限没开, (2)点击打开php.int., 搜索extension=ph...2013-10-04
Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 单个字符分割 string s="abcdeabcdeabcde"; string[] sArray=s.Split('c'); foreach(string i in sArray) Console.WriteLine(i.ToString()); 输出下面的结果: ab de...2020-06-25
- 如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
- javascript控制页面控件隐藏显示的两种方法,方法的不同之处在于控件隐藏后是否还在页面上占位 方法一: 复制代码 代码如下: document.all["panelsms"].style.visibility="hidden"; document.all["panelsms"].style.visi...2013-10-13
连接MySql速度慢的解决方法(skip-name-resolve)
最近在Linux服务器上安装MySql5后,本地使用客户端连MySql速度超慢,本地程序连接也超慢。 解决方法:在配置文件my.cnf的[mysqld]下加入skip-name-resolve。原因是默认安装的MySql开启了DNS的反向解析。如果禁用的话就不能...2015-10-21- 夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
- 本篇文章是对C#方法进行了详细的总结与介绍,需要的朋友参考下...2020-06-25