문제

I am trying to enable/disable mobile data at specific time of the day. This is what I have so far:

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

        Calendar objCal = Calendar.getInstance();
    objCal.set(Calendar.HOUR_OF_DAY, 11);
    objCal.set(Calendar.MINUTE, 0);
    objCal.set(Calendar.SECOND, 0);
    //
    // Intent intent = new Intent(this, MainActivity.class);
    // intent.setAction("com.sang.mobiledata.ACTION");
    //
     PendingIntent pi = PendingIntent.getActivity(this, 0, new Intent(
     this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
     AlarmManager am = (AlarmManager)
     this.getSystemService(Context.ALARM_SERVICE);
     am.setRepeating(AlarmManager.RTC_WAKEUP, objCal.getTimeInMillis(),
     AlarmManager.INTERVAL_DAY, pi);

Basically, I would like to turn off the data connection say at 10pm. I know this will be achieved by this line:

objNetwork.setMobileDataEnabled(getBaseContext(), false);

and again turn it on at say 6am

objNetwork.setMobileDataEnabled(getBaseContext(), true);

I just dont know how (and where) to give that condition.

EDIT:

public class Network {

public void setMobileDataEnabled(Context context, boolean enabled) {

    try {
        ConnectivityManager conman = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);

        Method setMobileDataEnabledMethod = ConnectivityManager.class
                .getDeclaredMethod("setMobileDataEnabled", boolean.class);

        setMobileDataEnabledMethod.setAccessible(true);
        setMobileDataEnabledMethod.invoke(conman, enabled);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

EDIT 2 (complete code):

ConnBroadCastReceiver.java

public class ConnBroadcastReceiver extends BroadcastReceiver {

private static final String CONN_ACTION = "com.sang.mobiledata.IntentAction.RECEIVE_CONN_UPDATE";
Network objNetwork = new Network();
@Override
public void onReceive(Context context, Intent intent) {
    if(CONN_ACTION.equals(intent.getAction())) {
        boolean enableConn = intent.getBooleanExtra("FLAG_KEY", false);
        objNetwork.setMobileDataEnabled(context, enableConn);
    }
 }

}

MainActivity.java

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    triggerEnable(true, 6);
    triggerEnable(false, 22);
}

private void triggerEnable(boolean enableData, int hourInDay) {
    Calendar calendar = Calendar.getInstance();
    if (enableData) {
        calendar.set(Calendar.HOUR_OF_DAY, hourInDay);
    } else {
        calendar.set(Calendar.HOUR_OF_DAY, hourInDay);
    }
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    Intent broadcastIntent = new Intent("com.sang.mobiledata.IntentAction.RECEIVE_CONN_UPDATE");
    broadcastIntent.putExtra("FLAG_KEY", enableData);
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, broadcastIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, pi);
}

Network.java

 public class Network {

public void setMobileDataEnabled(Context context, boolean enabled) {

    try {
        ConnectivityManager conman = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);

        Method setMobileDataEnabledMethod = ConnectivityManager.class
                .getDeclaredMethod("setMobileDataEnabled", boolean.class);

        setMobileDataEnabledMethod.setAccessible(true);
          setMobileDataEnabledMethod.invoke(conman, enabled);
    } catch (Exception e) {
        e.printStackTrace();
     }

}

manifest.xml

 <application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <receiver
        android:name="com.sang.mobiledata.ConnBroadcastReceiver"
        android:exported="false" >
        <intent-filter>
            <action android:name="com.sang.mobiledata.IntentAction.RECEIVE_CONN_UPDATE" />
        </intent-filter>
    </receiver>
도움이 되었습니까?

해결책

I've never tried to toggle data connection - assuming above will work if you provide proper permissions (if any is supposed to have) and above code doesn't make use of reflection as I have seen other people are shooting themselves in the foot ...

However, if you intend to open an application activity at a specific time, then I would say that's a bad practice at least from user experience point of view. Instead of doing that, you could send a broadcast message through PendingIntent.getBroadcast(...).

That being said:

  1. Construct an intent with an action of your own, add a boolean flag inside that is meaningfull (true to enable connectivity, false otherwise).
  2. Pass that intent to your PendingIntent.getBroadcast
  3. Create a BroadcastReceiver in your class, register it in the Manifest and handle properly that action. Something like:

The BroadcastReceiver class:

public class ConnBroadcastReceiver extends BroadcastReceiver {
    private static final String CONN_ACTION = "my_package_name.IntentAction.RECEIVE_CONN_UPDATE";

    @Override
    public void onReceive(Context context, Intent intent) {
        if(CONN_ACTION.equals(intent.getAction())) {
            boolean enableConn = intent.getBooleanExtra("FLAG_KEY", false);
            objNetwork.setMobileDataEnabled(context, enableConn);
        }
    }
}

register it in the Manifest:

<receiver
    android:name="my_package_name.ConnBroadcastReceiver"
    android:exported="false" >
        <intent-filter>
            <action android:name="my_package_name.IntentAction.RECEIVE_CONN_UPDATE" />
        </intent-filter>
</receiver>

and trigger the broadcast from your above code:

Intent broadcastIntent = new Intent("my_package_name.IntentAction.RECEIVE_CONN_UPDATE");
broadcastIntent.putExtra("FLAG_KEY", enableData);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, objCal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);

EDIT Above onCreate can be re-writen to:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    triggerEnable(true, 6);
    triggerEnable(false, 22);
}

private void triggerEnable(boolean enableData, int hourInDay) {
    Calendar calendar = Calendar.getInstance();
    if (enableData) {
        calendar.set(Calendar.HOUR_OF_DAY, hourInDay);
    } else {
        calendar.set(Calendar.HOUR_OF_DAY, hourInDay);
    }
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    Intent broadcastIntent = new Intent("my_package_name.IntentAction.RECEIVE_CONN_UPDATE");
    broadcastIntent.putExtra("FLAG_KEY", enableData);
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, broadcastIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, pi);
}

다른 팁

You can set two alarms, one for 10pm and another for 6am, and then when the alarms trigger, system will start services for you to do your own works.

   PendingIntent pi = PendingIntent.getService(this, 0, new Intent(
     this, YourOwnerService.class), PendingIntent.FLAG_UPDATE_CURRENT);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top