android计时与系统休眠

android计时与系统休眠

TIP:可能写的有点仓促,具体的可以联系我(*^__^*)

摘要:之前做项目的时候,修改一个倒计时秒表,本来以为比较简单,但是发现很多有趣的东西。我们项目里面用的是Timer计时的方法,但是,当系统休眠的时候,Timer也是处于休眠状态的。后来,我改进了几个方法,一个是handle+message的方法,还有一个是handle+runnable的方法,还有handle+Thread的方法。但是同样发现系统休眠的时候,这些同样是处于休眠状态的。后来上网查找了一下,这和android的架构有关:

原理

Android手机有两个处理器,一个叫Application Processor(AP),一个叫Baseband Processor(BP)。AP是ARM架构的处理器,用于运行Linux+Android系统;BP用于运行实时操作系统(RTOS),通讯协议栈运行于BP的RTOS之上。非通话时间,BP的能耗基本上在5mA左右,而AP只要处于非休眠状态,能耗至少在50mA以上,执行图形运算时会更高。另外LCD工作时功耗在100mA左右,WIFI也在100mA左右。一般手机待机时,AP、LCD、WIFI均进入休眠状态,这时Android中应用程序的代码也会停止执行。Android为了确保应用程序中关键代码的正确执行,提供了Wake
Lock的API,AlarmManager这个类使用的是BP的芯片,使得应用程序有权限通过代码阻止AP进入休眠状态。但如果不领会Android设计者的意图而滥用Wake Lock API,为了自身程序在后台的正常工作而长时间阻止AP进入休眠状态,就会成为待机电池杀手。

首先,完全没必要担心AP休眠会导致收不到消息推送。通讯协议栈运行于BP,一旦收到数据包,BP会将AP唤醒,唤醒的时间足够AP执行代码完成对收到的数据包的处理过程。其它的如Connectivity事件触发时AP同样会被唤醒。那么唯一的问题就是程序如何执行向服务器发送心跳包的逻辑。你显然不能靠AP来做心跳计时。Android提供的Alarm Manager就是来解决这个问题的。Alarm应该是BP计时(或其它某个带石英钟的芯片,不太确定,但绝对不是AP),触发时唤醒AP执行程序代码。那么Wake
Lock API有啥用呢?比如心跳包从请求到应答,比如断线重连重新登陆这些关键逻辑的执行过程,就需要Wake Lock来保护。而一旦一个关键逻辑执行成功,就应该立即释放掉Wake Lock了。两次心跳请求间隔5到10分钟,基本不会怎么耗电。除非网络不稳定,频繁断线重连,那种情况办法不多。

网上有说使用AlarmManager,因为AlarmManager 是Android 系统封装的用于管理 RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,可以在 CPU 休眠时正常运行,在预设的时间到达时,通过中断唤醒 CPU。

实验

后来,本人使用AlarmManager,但是又碰到不准的问题,而且当系统繁忙的时候(比如刚开机前一分钟),更为明显,后来查看官方的API说明。因为我之前使用的方法大致是下面的原理:

[java] view
plain
copyprint?

  1. AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
  2. Intent intent = new Intent("com.liu.alarm.ACTION_SEND");
  3. PendingIntent sendIntent = PendingIntent.getBroadcast(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
  4. am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000,1000, sendIntent);

然后注册一个广播接收器接收

  1. public void onReceive(final Context context, Intent intent) {
  2. 需要的操作;}

我们看看官方给出的API说明:Note: as
of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whosetargetSdkVersion is
earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.意思大概是说19或者19以后,为了优化电池,该计时操作不准确了(可能在定义时间之后响应),但是19之前的任然准确。

If your application has strong ordering requirements there are other APIs
that you can use to get the necessary behavior; see setWindow(int,
long, long, PendingIntent)
 andsetExact(int,
long, PendingIntent)
.意思是虽然19(包括)之后可能不准确,但是android保留了两个接口,这两个接口是准确的。本人于是使用了这其中一个。

方法如下    TIP:前提是确保你的API是19的或更高,否则做下判断

public static boolean isKitKatOrLater() {

return Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2;

}

[java] view
plain
copyprint?

  1. AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
  2. Intent intent = new Intent("com.liu.alarm.ACTION_SEND");
  3. PendingIntent sendIntent = PendingIntent.getBroadcast(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);</span>

[java] view
plain
copyprint?

  1. if(isKitKatOrLater(){
  2. am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);
  3. }else{
  4. am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);

然后注册一个广播接收器接收

[java] view
plain
copyprint?

  1. public void onReceive(final Context context, Intent intent) {
  2. if(isKitKatOrLater(){
  3. am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);
  4. }else{
  5. am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);
  6. }

[java] view
plain
copyprint?

  1. if(isKitKatOrLater(){
  2. am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + 1000, sendIntent);
  3. 需要的操作;}

但是后来有发现,即使使用了精确的时间计时,但是在系统刚开机的一分钟内计时,仍然会有不及时响应的情况,所以,后来自己想了一下,毕竟是两块芯片,多进程多线程还要考虑好多同步的问题,两块芯片也不可能配合的那么天衣无缝,假如一块特别繁忙的时候。所以,后来我参考源码的方法:正常情况下使用线程或者Timer计时,并且使用AlarmManager设定一个计时结束的时间,当执行Activity的Onpause的时候使用AlarmManager的计时响应。当Onresume的时候,根据走过的时间刷新界面。下面是我全部的代码

/**
 * 2014-12-05 BenMin FEIXUN_DESKCLOCK_BENMIN_001
 *     modify PWEUN-4141 to remind the user when the timing is over.
 * 2014-12-17 BenMin FEIXUN_DESKCLOCK_BENMIN_002
 *     modify to ensure the fragment attached to Activity when using getResources() function.
 * 2014-12-26 BenMin FEIXUN_DESKCLOCK_BENMIN_003
 *     modify PLGN-489 to stop the ring when press the back menu.
 */
package com.phicomm.keyer;

import java.util.Timer;
import java.util.TimerTask;

import android.R.integer;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.NumberPicker.Formatter;
import android.widget.NumberPicker.OnValueChangeListener;
import android.widget.TextView;

import com.phicomm.deskclock.DeskClockFragment;
import com.phicomm.deskclock.FxDeskClock;
import com.phicomm.deskclock.R;

public class FxKeyerFragment extends DeskClockFragment implements
        OnClickListener, Formatter, OnValueChangeListener {

    private NumberPicker keyerHour;
    private NumberPicker keyerMinute;
    private NumberPicker keyerSecond;

    private Button kbtnStart;
    private Button kbtnPause;
    private Button kbtnReset;
    private LinearLayout time;
    private TextView hour;
    private TextView minute;
    private TextView second;
    private int hourtime;
    private int minutetime;
    private int secondtime;
    private Timer timer;
    private TimerTask task; 

    private MediaPlayer alarmMusic;
    private AlertDialog dialog = null;

    private static final int originState = 0;   //original state
    private static final int timerState = 1;    //timer state
    private static final int pauseState = 2;    //pause
    private static final int resetState = 3;    //reset
    private static final int overState = 4;     //over

    private int stateNow = originState;

    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {

            if(msg.what == 1){

                if(secondtime > 0) {
                    secondtime --;
                    second.setText(format(secondtime));
                } else if(minutetime > 0) {
                    minutetime --;
                    secondtime = 59;
                    second.setText(format(secondtime));
                    minute.setText(format(minutetime));
                } else if(hourtime > 0) {
                    hourtime --;
                    secondtime = 59;
                    minutetime = 59;
                    second.setText(format(secondtime));
                    minute.setText(format(minutetime));
                    hour.setText(format(hourtime));
                }
                if (hourtime <= 0 && minutetime <= 0 && secondtime <= 0) {

                    startRing();
                }

            }
        }
    };

    private AlarmManager mAlarmManager;
    private PendingIntent sendIntent;
    public static String ALARM_KEYER_ACTION = "com.phicomm.keyer.alarm_keyer_action";
    private BroadcastReceiver mBroadcastReceiver;
    private boolean isRing = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        mAlarmManager = (AlarmManager) this.getActivity().getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent();
        intent.setAction(ALARM_KEYER_ACTION);
        sendIntent = PendingIntent.getBroadcast(getActivity(), 0, intent , PendingIntent.FLAG_UPDATE_CURRENT);
        mBroadcastReceiver = new BroadcastReceiver(){
            @Override
            public void onReceive(Context arg0, Intent arg1) {
                // TODO Auto-generated method stub
                kbtnPause.setEnabled(false);

                startRing();

            }
        };
        IntentFilter filter = new IntentFilter(ALARM_KEYER_ACTION);
        getActivity().registerReceiver(mBroadcastReceiver, filter );
    }

    private void startRing(){
        if (timer != null) {
            timer.cancel();
        }
        stateNow = overState;
        if (isAdded() && isRing == false) {
            kbtnPause.setTextColor(getResources().getColor(R.color.text_summery));
            alarmMusic = MediaPlayer.create(getActivity(), R.raw.in_call_alarm);
            alarmMusic.setLooping(true);
            alarmMusic.start();
            isRing = true;
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
                    .setTitle(R.string.tip)
                    .setMessage(R.string.tip_text)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener()
                    {

                        @Override
                        public void onClick(DialogInterface arg0, int arg1) {
                            // TODO Auto-generated method stub
                            alarmMusic.stop();
                            alarmMusic.release();
                            alarmMusic = null;
                            isRing = false;
                        }

                    });
            dialog = builder.setCancelable(false).create();
            dialog.show();

        }
        mAlarmManager.cancel(sendIntent);
        startTime = 0;
        leftTimeToRun = 0;
        ringTime = 0;
        adjustTime = 0;
        setNumberPicker(0);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View v = inflater.inflate(R.layout.keyer, container, false);

        keyerHour = (NumberPicker) v.findViewById(R.id.keyer_hour);
        keyerHour.setMinValue(0);
        keyerHour.setMaxValue(23);
        keyerHour.setFormatter(this);
        keyerHour.setOnValueChangedListener(this);

        keyerHour.getChildAt(0).setFocusable(false);

        keyerMinute = (NumberPicker) v.findViewById(R.id.keyer_minute);
        keyerMinute.setMinValue(0);
        keyerMinute.setMaxValue(59);
        keyerMinute.setFormatter(this);
        keyerMinute.setOnValueChangedListener(this);

        keyerMinute.getChildAt(0).setFocusable(false);

        keyerSecond = (NumberPicker) v.findViewById(R.id.keyer_second);
        keyerSecond.setMinValue(0);
        keyerSecond.setMaxValue(59);
        keyerSecond.setFormatter(this);
        keyerSecond.setOnValueChangedListener(this);

        keyerSecond.getChildAt(0).setFocusable(false);

        kbtnStart = (Button) v.findViewById(R.id.kbtnStart);
        kbtnStart.setOnClickListener(this);

        kbtnPause = (Button) v.findViewById(R.id.kbtnPause);
        kbtnPause.setOnClickListener(this);

        kbtnReset = (Button) v.findViewById(R.id.kbtnReset);
        kbtnReset.setOnClickListener(this);

        time = (LinearLayout) v.findViewById(R.id.time);
        hour = (TextView) v.findViewById(R.id.hour);
        minute = (TextView) v.findViewById(R.id.minute);
        second = (TextView) v.findViewById(R.id.second);

        TimeAllZero();

        return v;
    }

    @Override
    public void onResume() {
        if (getActivity() instanceof FxDeskClock) {
            ((FxDeskClock) getActivity()).registerPageChangedListener(this);
        }

        long now = SystemClock.elapsedRealtime();
        if(now <= ringTime && stateNow == timerState){
            long leftTime = ringTime - now;
            setNumberPicker(leftTime);
        } 

        if(stateNow == overState) {
            setNumberPicker(0);
        }
        super.onResume();
    }

    private void setNumberPicker(long leftTime){
        long secs = leftTime/1000;
        int hours = (int) (secs/3600);
        int minutes = (int) ((secs%3600)/60);
        int seconds = (int) ((secs%3600)%60);
        secondtime = seconds;
        minutetime = minutes;
        hourtime = hours;
        second.setText(format(seconds));
        minute.setText(format(minutes));
        hour.setText(format(hours));

    }
    @Override
    public void onPause() {
        if (getActivity() instanceof FxDeskClock) {
            ((FxDeskClock) getActivity()).unregisterPageChangedListener(this);
        }

        super.onPause();
    }

    public String format(int value) {
        String tmpStr = String.valueOf(value);
        if (value < 10) {
            tmpStr = "0" + tmpStr;
        }
        return tmpStr;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.kbtnStart:

            TimeAllZero();

            Start();
            break;
        case R.id.kbtnPause:
            Pause();
            break;
        case R.id.kbtnReset:
            Reset();

            kbtnStart.setTextColor(getResources().getColor(R.color.text_summery));

            break;
        }
    }

    public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
        if (picker == keyerHour) {
            hourtime = newVal;
        }
        if (picker == keyerMinute) {
            minutetime = newVal;
        }
        if (picker == keyerSecond) {
            secondtime = newVal;
        }

        TimeAllZero();

    }
    private long startTime = 0;
    private long leftTimeToRun = 0;
    private long ringTime = 0;
    private long adjustTime = 0;

    public void Start() {

        if (kbtnStart.isEnabled()) {
            kbtnStart.setVisibility(View.GONE);

            time.setVisibility(View.VISIBLE);
            hour.setText(format(hourtime));
            minute.setText(format(minutetime));
            second.setText(format(secondtime));

            kbtnPause.setVisibility(View.VISIBLE);
            kbtnPause.setText(R.string.kpause);
            kbtnPause.setEnabled(true);
            kbtnPause.setTextColor(getResources().getColor(R.color.text_gray));

            kbtnReset.setText(R.string.kreset);
            kbtnReset.setVisibility(View.VISIBLE);

            keyerHour.setVisibility(View.GONE);
            keyerMinute.setVisibility(View.GONE);
            keyerSecond.setVisibility(View.GONE);
            timer = null;
            task = null;
            timer = new Timer();
            task = new TimerTask() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    Message message = new Message();
                    message.what = 1;
                    handler.sendMessage(message);
                }
            };
            timer.schedule(task, 1000, 1000);
            startTime = SystemClock.elapsedRealtime();
            leftTimeToRun = (60 * 60 * hourtime + 60 * minutetime + secondtime) * 1000;
            ringTime = startTime + leftTimeToRun;
            mAlarmManager.cancel(sendIntent);
            if (isKitKatOrLater()) {
                mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent);
            } else {
                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent);
            }

            stateNow = timerState;

        }

    }
    public static boolean isKitKatOrLater() {
        return Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2;
    }

    public void Pause() {
        if(kbtnPause.getText().toString().equals(getResources().getString(R.string.kpause))) {
            kbtnPause.setText(R.string.kcontinue);
            timer.cancel();
            adjustTime = (leftTimeToRun - (SystemClock.elapsedRealtime() - startTime)) % 1000;
            mAlarmManager.cancel(sendIntent);
            stateNow = pauseState;
        } else {
            stateNow = timerState;
            kbtnPause.setText(R.string.kpause);
            secondtime = Integer.parseInt(second.getText().toString());
            minutetime = Integer.parseInt(minute.getText().toString());
            hourtime = Integer.parseInt(hour.getText().toString());
            timer = new Timer();
            task = new TimerTask() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    Message message = new Message();
                    message.what = 1;
                    handler.sendMessage(message);
                }
            };
            timer.schedule(task, adjustTime, 1000);

            startTime = SystemClock.elapsedRealtime();
            leftTimeToRun = (60 * 60 * hourtime + 60 * minutetime + secondtime) * 1000 + adjustTime;
            ringTime = startTime + leftTimeToRun;
            mAlarmManager.cancel(sendIntent);
            if (isKitKatOrLater()) {
                mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent);
            } else {
                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, ringTime, sendIntent);
            }
        }
    }
    public void Reset() {
        stateNow = resetState;
        kbtnStart.setVisibility(View.VISIBLE);
        kbtnPause.setVisibility(View.GONE);
        kbtnReset.setVisibility(View.GONE);

        keyerHour.setVisibility(View.VISIBLE);
        keyerHour.setValue(0);
        hourtime = 0;
        keyerMinute.setVisibility(View.VISIBLE);
        keyerMinute.setValue(0);
        minutetime = 0;
        keyerSecond.setVisibility(View.VISIBLE);
        keyerSecond.setValue(0);
        secondtime = 0;

        time.setVisibility(View.GONE);

        timer.cancel();

        startTime = 0;
        leftTimeToRun = 0;
        ringTime = 0;
        adjustTime = 0;
        mAlarmManager.cancel(sendIntent);
    }

    public void TimeAllZero() {
        if (keyerHour.getValue() == 0 && keyerMinute.getValue() == 0 && keyerSecond.getValue() == 0) {
            kbtnStart.setEnabled(false);
            kbtnStart.setTextColor(getResources().getColor(R.color.text_summery));
        } else {
            kbtnStart.setEnabled(true);
            kbtnStart.setTextColor(getResources().getColor(R.color.text_gray));
        }
    }

    @Override
    public void onDestroyView() {
        // TODO Auto-generated method stub
        super.onDestroyView();
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        if (task != null) {
            task = null;
        }

        if (alarmMusic != null) {
            alarmMusic.stop();
            alarmMusic.release();
            alarmMusic = null;

        if(mBroadcastReceiver!= null){
            getActivity().unregisterReceiver(mBroadcastReceiver);
        }
    }

}
时间: 2024-07-30 07:30:20

android计时与系统休眠的相关文章

Android socket在系统休眠情况下调研

做了3年的IM应用,一直没有确认过socket在系统休眠的情况下会不会就收不到消息了,网上也搜过一些资料说android手机分为AP和BP两个部分,系统休眠的时候AP是休眠的,而BP是不休眠的,网络协议栈是运行在BP层的,所以当BP收到数据包的时候,系统会唤醒AP,但是AP运行的时间是很短的.虽然听起来很有道理的样子,但是没有亲手测试过,还是一块心病~~~,今天又想起这事,索性动手自己写代码测试看看结果. Server端code: public class TestServer { public

Android系统休眠对程序的影响以及处理

Android系统在用户长时间不操作时,为了节省资源,系统会选择休眠.在休眠过程中自定义的Timer.Handler.Thread.Service等都会暂停.而有时候这种机制会影响到我们程序的正常运行.那如何避免系统休眠对我们程序的影响呢? 以下已Service服务为例说明在系统休眠的状态下如何唤醒系统并执行我们自定义的Service服务. 一.单次Service服务的开启 1.方法:在需要执行Service服务时获取电源锁,并在执行完毕释放电源锁. 2.代码举例: public class W

socket在系统休眠情况下调研【转】

做了3年的IM应用,一直没有确认过socket在系统休眠的情况下会不会就收不到消息了,网上也搜过一些资料说android手机分为AP和BP两个部分,系统休眠的时候AP是休眠的,而BP是不休眠的,网络协议栈是运行在BP层的,所以当BP收到数据包的时候,系统会唤醒AP,但是AP运行的时间是很短的.虽然听起来很有道理的样子,但是没有亲手测试过,还是一块心病~~~,今天又想起这事,索性动手自己写代码测试看看结果. Server端code: public class TestServer { public

Android之——利用系统权限实现手机重启

在应用开发时经常会有这样的需求,如何在应用里用代码让手机重启,另外,我们知道在重启之后,我们的应用可以注册广播接收者,以保证我们的应用会第一个将我们的服务开启起来,这样我们的代码就可以第一个接收到接收短信的广播事件.好了,现在就让我们一起来实现一个利用系统权限实现手机重启的示例吧. 一.实现 我们实现很简单,就是给界面一个按钮,然后设置按钮的点击事情,在点击事件里完成手机重启操作. 1.布局文件 布局文件很简单,就是放置了一个Button按钮,设置点击事件. 具体代码如下: <LinearLay

开箱即用!Android四款系统架构工具

开箱即用!Android四款系统架构工具_天极网 一款功能强大且实用的开发工具可以为开发者简化开发流程,提高工作效率,允许开发者在应用开发本身投入更多的时间和精力,从而提高作品质量.本文就为大家分享4款实用的Android应用架构工具. 开发者若想开发出一款高质量的应用,一款功能强大的开发工具想必是不可或缺的.开发工具简化了应用的开发流程,也能使开发者在应用开发本身投入更多的精力.本文就为大家带来4款实用的Android应用架构工具. 1. Spring for Android Spring f

Android如何获取系统高度、标题栏和状态栏高度

在android应用中,有时需要计算个View的位置,导致需要计算状态栏高度,标题栏高度等信息.为以后方便,在此做个简单记录. 晒代码前先了解一下android屏幕区域的划分,如下图(该图引用自此文http://www.iteye.com/topic/828830 ) 1. 屏幕区域的获取 [java] view plaincopy activity.getWindowManager().getDefaultDisplay(); 2.应用区域的获取 [java] view plaincopy R

第8章 Android 4.0系统的下载与编译

第8章  Android 4.0系统的下载与编译 本章首先的准备Android下载与编译环境,内容主要分为:准备Android下载与编译环境.下载源码.编译源码及内核源码.下载Android 4.0及Goldfish源码中包括下载并初始化repo工具.下载Android源码.其他源码下载源.下载模拟器Goldfish内核源码.编译Android及Goldfish内核源码中切换到Android源码目录命令:$cd WORKING_DIRECTORY 执行如下命令,加载编译过程中用到的命令.环境变量

Android应用与系统安全防御

来源:HTTP://WWW.CNBLOGS.COM/GOODHACKER/P/3864680.HTML ANDROID应用安全防御 Android应用的安全隐患包括三个方面:代码安全.数据安全和组件安全. 1. 代码安全 代码安全主要是指Android apk有被篡改.盗版等风险,产生代码安全的主要原因是apk很容易被反编译.重打包.我们可以采用以下方法对apk进行保护: 1.1 代码混淆 代码混淆可以在一定程度上增加apk逆向分析的难度.Android SDK从2.3开始就加入了ProGuar

android中调用系统的发送短信、发送邮件、打电话功能

1 调用发送短信功能: Uri smsToUri = Uri.parse("smsto:"); Intent sendIntent = new Intent(Intent.ACTION_VIEW, smsToUri); sendIntent.putExtra("address", "123456"); //电话号码,这行去掉的话,默认就没有电话 sendIntent.putExtra("sms_body","短信内容