-->

开启Android在互联网上睡眠时(Turn on the Internet on Android

2019-07-30 22:36发布

我有一个Android应用程序需要同步到互联网,但只要手机进入睡眠状态,我不能访问互联网。 它仅当用户使用“电池模式”时,它在15分钟后关闭数据时发生的情况。 我写了一个测试程序,并在其打开后的数据,但它仍然无法连接到服务器。

我的尝试:

  • 当我把数据手工关闭,然后应用程序被打开它和它的工作原理
  • 我也试着唤醒锁定,但它并没有帮助。
  • 报警按预期工作,甚至当手机进入睡眠小时

在测试了摩托罗拉Atrix的Android 2.3.3。 我不能依靠无线网络连接。 在现实生活中,每个礼拜都会同步。 我们怎样才能使这可能吗?

报警管理:

alarm_manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(this, 0, intent, 
                        PendingIntent.FLAG_UPDATE_CURRENT);
alarm_manager.setRepeating(AlarmManager.RTC_WAKEUP, 
                        System.currentTimeMillis(), 15000, pending);

AlarmReceiver:

public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("MYTAG", "RECEIVED getMobileDataEnabled: " + getMobileDataEnabled(context));  
        if (!isOnline(context)) {
            Log.d("MYTAG", "NO INET");
            if (turnOnInet(context)) {
                Log.d("MYTAG", "INET IS ON");
            }
        }

        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://xxx.xxx.xxx.xxx/ping/pong/moto/");
            try {
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
                nameValuePairs.add(new BasicNameValuePair("short_code", "ROFL"));
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                httpclient.execute(httppost);
                Log.d("MYTAG", "POST FINISHED");
            }
            catch (Exception e) {
                Log.e("MYTAG", "MYTAG", e);
            }
    }

    public boolean isOnline(Context context) {
        ConnectivityManager cm = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null){
            Log.d("MYTAG", "isAvailable: "+netInfo.isAvailable());
        }
        if (netInfo != null && netInfo.isConnectedOrConnecting()) {
            return true;
        }
        return false;
    }

    public boolean turnOnInet(Context context) {
        ConnectivityManager mgr = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        if (mgr == null) {
            Log.d("MYTAG", "ConnectivityManager == NULL");
            return false;
        }
        try {
            Method setMobileDataEnabledMethod = mgr.getClass().getDeclaredMethod("setMobileDataEnabled", boolean.class);
            if (null == setMobileDataEnabledMethod) {
                Log.d("MYTAG", "setMobileDataEnabledMethod == null");
                return false;
            }    
            setMobileDataEnabledMethod.invoke(mgr, true);
        }
        catch(Exception e) {
            Log.e("MYTAG", "MYTAG", e);
            return false;
        }
        return true;
    }   


    private boolean getMobileDataEnabled(Context context) {
        ConnectivityManager mgr = (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        if (mgr == null) {
            Log.d("MYTAG", "getMobileDataEnabled ConnectivityManager == null");
            return false;
        }
        try {
            Method method = mgr.getClass().getMethod("getMobileDataEnabled");
            return (Boolean) method.invoke(mgr);
        } catch (Exception e) {
            Log.e("MYTAG", "MYTAG", e);
            return false;
        }
    }
}

AndroidManifest.xml中

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

Answer 1:

首先,你需要获得HttpPost码出的BroadcastReceiver和成IntentService永远不要做网络我的主应用程序线程/ O,和onReceive()被称为主应用程序线程。 例如,如果你花费太长时间,Android将中途通过Internet操作终止你的代码。

其次,鉴于IntentService ,您需要使用WakeLock 。 这可能会引导你使用我的WakefulIntentService ,它处理这两个问题。 或者,使用WakefulBroadcastReceiver ,其中有异曲同工之妙。

三,删除turnOnInet()getMobileDataEnabled() 你不需要他们,他们是不可靠的,特别是turnOnInet()是用户敌对-如果用户希望,他们就会把它移动数据。

现在,考虑到所有这一切,在你的onHandleIntent()您的IntentService()或您的doWakefulWork()您的WakefulIntentService ),如果你没有互联网连接的时候了,作为临时解决方法, SystemClock.sleep()为第二,然后再试一次,在一个循环中重复几次。 如果你发现你是后一点让上网,那么你可以考虑越来越复杂(例如,侦听连接变化的广播,而不是投票,尽管这将推动你远离WakefulIntentService并为常规Service与自己的后台线程和状态机来WakeLock管理)。 或者,只是坚持与sleep() -它不可能是世界的末日,如果你配合了这个后台线程几秒钟。 如果你没有时间适量后得到的连接,但是,请不要无限期地努力,因为有任意数量的原因,你可能无法得到的连接,包括在Android 4.0以上版本的用户驱动的带宽管理。



Answer 2:

我建议改变了一下这种做法,这是不坏的,它甚至好的,以确保您始终保持同步,与你不给用户决定的机会,因为如果我唯一的问题,作为一个用户,决定关闭我的数据我不希望任何人将其打开。 可能有几个原因,任何人应该是足够的,但说,你出了国,你有没有国际数据计划和意外或默认你有数据漫游激活。 如果我发现一些特定的应用程序打开我的数据上,并花了大量资金我会很生气敏感的量,我是个人。

更合适的方法,并直接解决方案,以及将适时做出硬/完全同步时间,每当用户打开应用程序或访问一些wifi连接( ConnectivityManager是你的朋友 )基于一些简单的条件(上次同步超过一个星期,过时保存的数据,不一致等),并在案件的其他软同步(在后台更新数据)。

此外同步周期性地指情况下该用户不使用该应用浪费用户数据。 最终,这将您的应用程序到完美的候选人,由系统每过一段时间被关闭。

希望能帮助到你。 让我们与您的最新进展。

相关阅读: 优化的下载高效的网络接入



Answer 3:

没有一个确切的答案 - 但这种做法会毁掉绝对的电池寿命。 睡眠的意义就在于节省电池电量和这个程序会做无非是为客户的烦恼,无论功能多么有用。

我的建议是,如果它是绝对必要的连接到互联网,而应用程序不使用 - 设置一个触发的时候,手机醒来。 如果不是完全必要的,它可能是最好每次应用程序被打开时简单地重新连接到互联网。



文章来源: Turn on the Internet on Android when in sleep