├── example.keystore.jks
├── ic_launcher-web.png
├── proguard-project.txt
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── src
├── main
│ ├── res
│ │ ├── drawable-hdpi
│ │ │ ├── ic_add.png
│ │ │ ├── ic_delete.png
│ │ │ ├── ic_help.png
│ │ │ ├── ic_wifi.png
│ │ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ │ ├── ic_add.png
│ │ │ ├── ic_delete.png
│ │ │ ├── ic_help.png
│ │ │ ├── ic_wifi.png
│ │ │ └── ic_launcher.png
│ │ ├── drawable
│ │ │ ├── icon_black.png
│ │ │ ├── event_wifi_on.xml
│ │ │ ├── event_app_enabled.xml
│ │ │ ├── event_display_on.xml
│ │ │ ├── event_wifi_disconnected.xml
│ │ │ ├── event_ac_connected.xml
│ │ │ ├── event_error.xml
│ │ │ ├── event_display_off.xml
│ │ │ ├── event_location_entered.xml
│ │ │ ├── event_timer.xml
│ │ │ ├── event_wifi_off.xml
│ │ │ ├── event_airplane_mode.xml
│ │ │ ├── event_app_disabled.xml
│ │ │ ├── event_unlock.xml
│ │ │ ├── event_ac_disconnected.xml
│ │ │ └── event_hotspot.xml
│ │ ├── drawable-xhdpi
│ │ │ ├── ic_add.png
│ │ │ ├── ic_help.png
│ │ │ ├── ic_wifi.png
│ │ │ ├── ic_delete.png
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xxhdpi
│ │ │ ├── ic_add.png
│ │ │ ├── ic_help.png
│ │ │ ├── ic_wifi.png
│ │ │ ├── ic_delete.png
│ │ │ └── ic_launcher.png
│ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── styles.xml
│ │ │ └── strings.xml
│ │ ├── values-v21
│ │ │ └── styles.xml
│ │ ├── layout
│ │ │ ├── logitem.xml
│ │ │ └── statepreference.xml
│ │ ├── xml
│ │ │ └── preferences.xml
│ │ ├── xml-v26
│ │ │ └── preferences.xml
│ │ ├── values-pl
│ │ │ └── strings.xml
│ │ ├── values-cs
│ │ │ └── strings.xml
│ │ ├── values-fr
│ │ │ └── strings.xml
│ │ ├── values-it
│ │ │ └── strings.xml
│ │ ├── values-pt
│ │ │ └── strings.xml
│ │ ├── values-ru
│ │ │ └── strings.xml
│ │ ├── values-es
│ │ │ └── strings.xml
│ │ └── values-de
│ │ │ └── strings.xml
│ ├── java
│ │ └── de
│ │ │ └── j4velin
│ │ │ └── wifiAutoOff
│ │ │ ├── NoticePreference.java
│ │ │ ├── Util.java
│ │ │ ├── APILevel14Wrapper.java
│ │ │ ├── APILevel19Wrapper.java
│ │ │ ├── LogDeleteService.java
│ │ │ ├── APILevel23Wrapper.java
│ │ │ ├── APILevel24Wrapper.java
│ │ │ ├── APILevel20Wrapper.java
│ │ │ ├── QSTileService.java
│ │ │ ├── APILevel17Wrapper.java
│ │ │ ├── UnlockReceiver.java
│ │ │ ├── APILevel11Wrapper.java
│ │ │ ├── LogAdapter.java
│ │ │ ├── StartReceiver.java
│ │ │ ├── Logger.java
│ │ │ ├── ScreenChangeDetector.java
│ │ │ ├── StatusPreference.java
│ │ │ ├── APILevel26ForegroundService.java
│ │ │ ├── Log.java
│ │ │ ├── Start.java
│ │ │ └── Receiver.java
│ └── AndroidManifest.xml
├── play
│ ├── res
│ │ ├── layout
│ │ │ ├── map.xml
│ │ │ ├── location.xml
│ │ │ └── locations.xml
│ │ ├── menu
│ │ │ └── menu.xml
│ │ └── raw
│ │ │ └── map.json
│ ├── java
│ │ └── de
│ │ │ └── j4velin
│ │ │ └── wifiAutoOff
│ │ │ ├── Location.java
│ │ │ ├── GeoFenceService.java
│ │ │ ├── Map.java
│ │ │ ├── GeofenceUpdateService.java
│ │ │ └── Database.java
│ ├── AndroidManifest.xml
│ └── aidl
│ │ └── com
│ │ └── android
│ │ └── vending
│ │ └── billing
│ │ └── IInAppBillingService.aidl
└── fdroid
│ ├── java
│ └── de
│ │ └── j4velin
│ │ └── wifiAutoOff
│ │ ├── Locations.java
│ │ ├── GeoFenceService.java
│ │ └── GeofenceUpdateService.java
│ └── res
│ └── menu
│ └── menu.xml
├── NOTICE
├── key.properties.sample
├── .travis.yml
├── .gitignore
├── README.md
├── gradlew.bat
├── gradlew
└── LICENSE.md
/example.keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/example.keystore.jks
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/ic_launcher-web.png
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | -renamesourcefileattribute SourceFile
2 | -keepattributes SourceFile,LineNumberTable
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src/main/res/drawable-hdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-hdpi/ic_add.png
--------------------------------------------------------------------------------
/src/main/res/drawable-mdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-mdpi/ic_add.png
--------------------------------------------------------------------------------
/src/main/res/drawable/icon_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable/icon_black.png
--------------------------------------------------------------------------------
/src/main/res/drawable-hdpi/ic_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-hdpi/ic_delete.png
--------------------------------------------------------------------------------
/src/main/res/drawable-hdpi/ic_help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-hdpi/ic_help.png
--------------------------------------------------------------------------------
/src/main/res/drawable-hdpi/ic_wifi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-hdpi/ic_wifi.png
--------------------------------------------------------------------------------
/src/main/res/drawable-mdpi/ic_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-mdpi/ic_delete.png
--------------------------------------------------------------------------------
/src/main/res/drawable-mdpi/ic_help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-mdpi/ic_help.png
--------------------------------------------------------------------------------
/src/main/res/drawable-mdpi/ic_wifi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-mdpi/ic_wifi.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xhdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xhdpi/ic_add.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xhdpi/ic_help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xhdpi/ic_help.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xhdpi/ic_wifi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xhdpi/ic_wifi.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xxhdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xxhdpi/ic_add.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xxhdpi/ic_help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xxhdpi/ic_help.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xxhdpi/ic_wifi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xxhdpi/ic_wifi.png
--------------------------------------------------------------------------------
/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xhdpi/ic_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xhdpi/ic_delete.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xxhdpi/ic_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xxhdpi/ic_delete.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/j4velin/WiFi-Automatic/HEAD/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #33b5e5
4 | #33b5e5
5 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | WiFi-Automatic
2 | Copyright 2013-2017 Thomas Hoffmann
3 |
4 | This product includes software developed at j4velin development (http://j4velin.de) by Thomas Hoffmann (http://hoffmann-thomas.de)
5 |
--------------------------------------------------------------------------------
/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/key.properties.sample:
--------------------------------------------------------------------------------
1 | # Add your keystore credentials here and rename the file to 'key.properties'
2 |
3 | keyStore=example.keystore.jks
4 |
5 | keyStorePassword=android
6 |
7 | keyAlias=android
8 |
9 | keyAliasPassword=android
10 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Aug 02 09:58:51 CEST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 |
3 | jdk:
4 | - oraclejdk8
5 |
6 | android:
7 | components:
8 | - platform-tools
9 | - tools
10 | - build-tools-29.0.2
11 | - android-29
12 | - extra-google-google_play_services
13 | - extra-google-m2repository
14 | - extra-android-m2repository
15 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_wifi_on.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_app_enabled.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_display_on.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/play/res/layout/map.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_wifi_disconnected.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_ac_connected.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_error.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_display_off.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_location_entered.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_timer.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_wifi_off.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_airplane_mode.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 | key.properties
18 | keys.xml
19 |
20 | # Windows thumbnail db
21 | Thumbs.db
22 |
23 | # OSX files
24 | .DS_Store
25 |
26 | # Eclipse project files
27 | .classpath
28 | .project
29 |
30 | # Android Studio
31 | .idea
32 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
33 | .gradle
34 | build/
35 | *.iml
--------------------------------------------------------------------------------
/src/main/res/drawable/event_app_disabled.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_unlock.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_ac_disconnected.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/NoticePreference.java:
--------------------------------------------------------------------------------
1 | package de.j4velin.wifiAutoOff;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.preference.Preference;
6 | import android.util.AttributeSet;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | public class NoticePreference extends Preference {
11 |
12 | public NoticePreference(final Context context, final AttributeSet attrs) {
13 | super(context, attrs);
14 | }
15 |
16 | @Override
17 | protected View onCreateView(final ViewGroup parent) {
18 | View v = super.onCreateView(parent);
19 | v.setBackgroundColor(Color.parseColor("#66ccff"));
20 | return v;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/res/drawable/event_hotspot.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/Util.java:
--------------------------------------------------------------------------------
1 | package de.j4velin.wifiAutoOff;
2 |
3 | import android.app.AlarmManager;
4 | import android.app.PendingIntent;
5 | import android.content.Context;
6 | import android.os.Build;
7 |
8 | public final class Util {
9 | private Util() {
10 | }
11 |
12 | public static void setTimer(final Context context, int type, long time, PendingIntent intent) {
13 | AlarmManager am = ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
14 | if (Build.VERSION.SDK_INT >= 23) {
15 | APILevel23Wrapper.setAlarmWhileIdle(am, type, time, intent);
16 | } else if (Build.VERSION.SDK_INT >= 19) {
17 | APILevel19Wrapper.setExactTimer(am, type, time, intent);
18 | } else {
19 | am.set(type, time, intent);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/res/layout/logitem.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
16 |
--------------------------------------------------------------------------------
/src/fdroid/java/de/j4velin/wifiAutoOff/Locations.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | /**
19 | * Dummy class, "play" build flavor contains actual implementation
20 | */
21 | public class Locations {
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/fdroid/java/de/j4velin/wifiAutoOff/GeoFenceService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | /**
19 | * Dummy class, "play" build flavor contains actual implementation
20 | */
21 | public class GeoFenceService {
22 | public final static String LOCATION_ENTERED_ACTION = "LOCATION_ENTERED";
23 | }
24 |
--------------------------------------------------------------------------------
/src/fdroid/res/menu/menu.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/play/res/menu/menu.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/play/java/de/j4velin/wifiAutoOff/Location.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import com.google.android.gms.maps.model.LatLng;
19 |
20 | class Location {
21 | final LatLng coords;
22 | final String name;
23 |
24 | public Location(final String name, final LatLng latlon) {
25 | this.coords = latlon;
26 | this.name = name;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel14Wrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.annotation.TargetApi;
19 | import android.net.wifi.p2p.WifiP2pInfo;
20 | import android.os.Build;
21 |
22 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
23 | public class APILevel14Wrapper {
24 | public static boolean groupFormed(final WifiP2pInfo info) {
25 | return info.groupFormed;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel19Wrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.annotation.TargetApi;
19 | import android.app.AlarmManager;
20 | import android.app.PendingIntent;
21 |
22 | @TargetApi(19)
23 | abstract class APILevel19Wrapper {
24 | static void setExactTimer(final AlarmManager am, int type, long time, PendingIntent pi) {
25 | am.setExact(type, time, pi);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/LogDeleteService.java:
--------------------------------------------------------------------------------
1 | package de.j4velin.wifiAutoOff;
2 |
3 | import android.app.AlarmManager;
4 | import android.app.PendingIntent;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.support.annotation.NonNull;
8 | import android.support.v4.app.JobIntentService;
9 |
10 | /**
11 | * Service to call {@link Log#deleteOldLogs(Context, long)} every {@link Log#KEEP_DURATION} ms
12 | */
13 | public class LogDeleteService extends JobIntentService {
14 |
15 | private static final int JOB_ID = 42;
16 |
17 | public static void enqueueJob(Context context) {
18 | enqueueWork(context, LogDeleteService.class, JOB_ID, new Intent());
19 | }
20 |
21 | @Override
22 | protected void onHandleWork(@NonNull Intent intent) {
23 | Log.deleteOldLogs(this, Log.KEEP_DURATION);
24 | ((AlarmManager) getSystemService(Context.ALARM_SERVICE))
25 | .set(AlarmManager.RTC, System.currentTimeMillis() + Log.KEEP_DURATION, PendingIntent
26 | .getService(this, 0, new Intent(this, LogDeleteService.class),
27 | PendingIntent.FLAG_UPDATE_CURRENT));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel23Wrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.annotation.TargetApi;
20 | import android.app.AlarmManager;
21 | import android.app.PendingIntent;
22 | import android.os.Build;
23 |
24 | @TargetApi(Build.VERSION_CODES.M)
25 | public class APILevel23Wrapper {
26 |
27 | public static void setAlarmWhileIdle(AlarmManager am, int type, long time,
28 | PendingIntent intent) {
29 | am.setAndAllowWhileIdle(type, time, intent);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel24Wrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.annotation.TargetApi;
20 | import android.content.ComponentName;
21 | import android.content.Context;
22 | import android.os.Build;
23 | import android.service.quicksettings.TileService;
24 |
25 | @TargetApi(Build.VERSION_CODES.N)
26 | public class APILevel24Wrapper {
27 |
28 | public static void updateTile(final Context context) {
29 | TileService.requestListeningState(context, new ComponentName(context, QSTileService.class));
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/fdroid/java/de/j4velin/wifiAutoOff/GeofenceUpdateService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.content.Context;
19 | import android.content.Intent;
20 | import android.support.annotation.NonNull;
21 | import android.support.v4.app.JobIntentService;
22 |
23 | /**
24 | * Dummy class, "play" build flavor contains actual implementation
25 | */
26 | public class GeofenceUpdateService extends JobIntentService {
27 |
28 | public static void enqueueJob(Context context) {
29 | }
30 |
31 | @Override
32 | protected void onHandleWork(@NonNull Intent intent) {
33 | stopSelf();
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel20Wrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.annotation.TargetApi;
19 | import android.content.Context;
20 | import android.hardware.display.DisplayManager;
21 | import android.view.Display;
22 |
23 | @TargetApi(20)
24 | abstract class APILevel20Wrapper {
25 | static boolean isScreenOn(final Context context) {
26 | DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
27 | for (Display display : dm.getDisplays()) {
28 | if (display.getState() != Display.STATE_OFF) {
29 | return true;
30 | }
31 | }
32 | return false;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/QSTileService.java:
--------------------------------------------------------------------------------
1 | package de.j4velin.wifiAutoOff;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.ComponentName;
5 | import android.content.pm.PackageManager;
6 | import android.os.Build;
7 | import android.service.quicksettings.Tile;
8 | import android.service.quicksettings.TileService;
9 |
10 | @TargetApi(Build.VERSION_CODES.N)
11 | public class QSTileService extends TileService {
12 | @Override
13 | public void onClick() {
14 | if (BuildConfig.DEBUG) Logger.log("QSTile click -> change enable state");
15 | boolean isEnabled = getPackageManager().getComponentEnabledSetting(
16 | new ComponentName(QSTileService.this, Receiver.class)) !=
17 | PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
18 | Preferences.changeEnableState(getApplicationContext(), !isEnabled);
19 | }
20 |
21 | @Override
22 | public void onStartListening() {
23 | super.onStartListening();
24 | boolean isEnabled = getPackageManager().getComponentEnabledSetting(
25 | new ComponentName(QSTileService.this, Receiver.class)) !=
26 | PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
27 | Tile tile = getQsTile();
28 | tile.setState(isEnabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
29 | tile.updateTile();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel17Wrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.annotation.TargetApi;
20 | import android.content.Context;
21 | import android.provider.Settings;
22 | import android.provider.Settings.SettingNotFoundException;
23 |
24 | @TargetApi(17)
25 | abstract class APILevel17Wrapper {
26 |
27 | static boolean sleepPolicySetToNever(final Context c) throws SettingNotFoundException {
28 | return Settings.Global.WIFI_SLEEP_POLICY_NEVER == Settings.Global.getInt(c.getContentResolver(),
29 | Settings.Global.WIFI_SLEEP_POLICY);
30 | }
31 |
32 | static boolean isAirplaneModeOn(final Context c) throws SettingNotFoundException {
33 | return Settings.Global.getInt(c.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON) == 1;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | WiFi Automatic
2 | =============
3 |
4 | [](https://travis-ci.org/j4velin/WiFi-Automatic)
5 |
6 | This simple app can help you increase the standby time of your device: WiFi Automatic automatically disable your WiFi radio when you don't need it and thereby lowers the battery consumption.
7 | It is designed to be used with WiFi-only* tablets - these devices normally don't require a constant internet connection if you're not using them and turning WiFi off can save a lot of battery power.
8 |
9 | You can also specify to automatically turn on WiFi again, if you turn on your device. Also, the app can regularly scan for available networks to connect to and re-disable WiFi if no suitable network is found. This way, you are always connected to your WiFi network when using the device.
10 |
11 | This app has a similiar effect like setting the "WiFi sleep policy" in Android to "always", except that you can now exactly define the timeout between turning the screen off and actually turning off WiFi.
12 |
13 |
14 | *if your device has a cell radio, it might switch to 2G/3G which may consume more power then staying on WiFi
15 |
16 |
17 |
18 |
19 | You can download the app for free from the Play Store or from F-Droid
20 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/UnlockReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.content.BroadcastReceiver;
20 | import android.content.Context;
21 | import android.content.Intent;
22 |
23 | /**
24 | * Class for receiving the USER_PRESENT event. Can be disabled if that option is not required
25 | */
26 | public class UnlockReceiver extends BroadcastReceiver {
27 |
28 | public final static String USER_PRESENT_ACTION = "USER_PRESENT";
29 |
30 | @Override
31 | public void onReceive(final Context context, final Intent intent) {
32 | final String action = intent.getAction();
33 | if (Intent.ACTION_USER_PRESENT.equals(action)) {
34 | context.sendBroadcast(
35 | new Intent(context, Receiver.class).setAction(USER_PRESENT_ACTION));
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/res/layout/statepreference.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
24 |
25 |
33 |
34 |
42 |
--------------------------------------------------------------------------------
/src/play/res/layout/location.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
27 |
28 |
39 |
40 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/main/res/xml/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
11 |
14 |
17 |
22 |
26 |
27 |
28 |
32 |
36 |
39 |
40 |
41 |
46 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/main/res/xml-v26/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
12 |
13 |
14 |
18 |
21 |
24 |
29 |
33 |
34 |
35 |
39 |
43 |
46 |
47 |
48 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel11Wrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.annotation.TargetApi;
20 | import android.app.AlertDialog;
21 | import android.content.Context;
22 | import android.content.DialogInterface;
23 | import android.content.DialogInterface.OnClickListener;
24 | import android.content.SharedPreferences;
25 | import android.os.Build;
26 | import android.preference.Preference;
27 | import android.widget.NumberPicker;
28 |
29 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
30 | abstract class APILevel11Wrapper {
31 |
32 | static void showNumberPicker(final Context c, final SharedPreferences prefs, final Preference p, final int summary, final int min, final int max, final String title, final String setting, final int def, final boolean changeTitle) {
33 | if (c == null) return;
34 | final NumberPicker np = new NumberPicker(c);
35 | np.setMinValue(min);
36 | np.setMaxValue(max);
37 | np.setValue(prefs.getInt(setting, def));
38 | new AlertDialog.Builder(c).setTitle(title).setView(np)
39 | .setPositiveButton(android.R.string.ok, new OnClickListener() {
40 | @Override
41 | public void onClick(DialogInterface dialog, int which) {
42 | np.clearFocus();
43 | prefs.edit().putInt(setting, np.getValue()).apply();
44 | if (changeTitle) p.setTitle(c.getString(summary, np.getValue()));
45 | else p.setSummary(c.getString(summary, np.getValue()));
46 | }
47 | }).create().show();
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/play/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
10 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
31 |
32 |
35 |
38 |
39 |
42 |
45 |
46 |
50 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/LogAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.support.v7.widget.RecyclerView;
19 | import android.view.LayoutInflater;
20 | import android.view.View;
21 | import android.view.ViewGroup;
22 | import android.widget.TextView;
23 |
24 | import java.text.DateFormat;
25 | import java.text.SimpleDateFormat;
26 | import java.util.Date;
27 | import java.util.List;
28 |
29 | public class LogAdapter extends RecyclerView.Adapter {
30 |
31 | private final List items;
32 | private final static DateFormat dateFormat = SimpleDateFormat.getTimeInstance();
33 |
34 | public LogAdapter(final List items) {
35 | this.items = items;
36 | }
37 |
38 | @Override
39 | public Holder onCreateViewHolder(final ViewGroup parent, int viewType) {
40 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.logitem, parent, false);
41 | Holder holder = new Holder(v);
42 | return holder;
43 | }
44 |
45 | @Override
46 | public void onBindViewHolder(final Holder holder, int position) {
47 | Log.Item item = items.get(position);
48 | holder.date.setText(dateFormat.format(new Date(item.date)));
49 | holder.text.setText(item.text);
50 | holder.text.setCompoundDrawablesWithIntrinsicBounds(item.type.drawable, 0, 0, 0);
51 | }
52 |
53 | @Override
54 | public int getItemCount() {
55 | return items.size();
56 | }
57 |
58 | public class Holder extends RecyclerView.ViewHolder {
59 |
60 | private final TextView date, text;
61 |
62 | public Holder(final View itemView) {
63 | super(itemView);
64 | date = (TextView) itemView.findViewById(R.id.date);
65 | text = (TextView) itemView.findViewById(R.id.text);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/StartReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.content.BroadcastReceiver;
20 | import android.content.Context;
21 | import android.content.Intent;
22 | import android.content.IntentFilter;
23 | import android.os.BatteryManager;
24 |
25 | /**
26 | * BroadcastReceiver which receives BOOT_COMPLETE & PACKAGE_REPLACED and then
27 | * starts all necessary timers
28 | *
29 | * @see Start
30 | */
31 | public class StartReceiver extends BroadcastReceiver {
32 |
33 | @Override
34 | public void onReceive(final Context context, final Intent intent) {
35 | if (BuildConfig.DEBUG) Logger.log("received: " + intent.getAction());
36 | if (!Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction()) ||
37 | intent.getDataString().contains(context.getPackageName())) {
38 | LogDeleteService.enqueueJob(context);
39 | }
40 | if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
41 | // AC already connected on boot?
42 | try {
43 | Intent batteryIntent = context.registerReceiver(null,
44 | new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
45 | int plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
46 | if (plugged == BatteryManager.BATTERY_PLUGGED_AC ||
47 | plugged == BatteryManager.BATTERY_PLUGGED_USB) {
48 | context.sendBroadcast(
49 | // we're not allowed to send Intent.ACTION_POWER_CONNECTED, so use our own action
50 | new Intent(context, Receiver.class)
51 | .setAction(Receiver.POWER_CONNECTED));
52 | }
53 | } catch (Throwable t) {
54 | // ReceiverCallNotAllowedException might be thrown on Samsung devices...
55 | if (BuildConfig.DEBUG) Logger.log(t);
56 | }
57 | }
58 | Start.start(context);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/res/values-pl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | przez co najmniej %d minut
5 | codziennie o %s
6 | co każde %s
7 | Zaawansowane ustawienia WiFi
8 | Więcej aplikacji
9 | Darowizna
10 | Uruchom włączenie WiFi…
11 | urządzenie zostanie odblokowane
12 | Uruchom wyłączenie WiFi gdy…
13 | ekran jest wyłączony
14 | nie jest podłączony do żadnej sieci
15 | Twoje ustawienia WiFi są ustawione na automatyczne wyłączenie gdy tylko wyświetlacz zgaśnie. Możesz zmienić te ustawienia w \'Zaawansowane ustawienia WiFi\' Androida
16 | Zaawansowane ustawienia WiFi
17 | Ustawień nie znaleziono!
18 | Minut przed wyłączeniem WiFi:
19 | Uruchom włączenie WiFi o:
20 | Uruchom wyłączenie WiFi o:
21 | Uruchom włączenie WiFi co …
22 | Nieprawidłowy wpis: Liczba musi być >= %1$d i <= %2$d
23 | po podłączeniu do zewnętrznego źródła zasilania
24 |
25 |
26 | - 5 minut
27 | - 15 minut
28 | - 30 minut
29 | - 1 godzine
30 | - 2 godziny
31 | - 5 godzin
32 | - 10 godzin
33 |
34 |
35 | Ustawienia ogólne
36 | Tryb samolotowy
37 | Nie włączaj WiFi w trybie samolotowym
38 | gdy znajdziesz się w określonych miejscach
39 | Tylko jedna lokalizacja jest wspierana w darmowej wersji aplikacjii. Czy chcesz teraz uaktualnić do wersji pro??
40 | Włącz WiFi gdy znajdziesz się w tej lokalizacji:
41 | Użyj informacji o lokalizacji komórki, aby włączyć WiFi w określonych miejscach
42 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/Logger.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.database.Cursor;
20 | import android.os.Environment;
21 |
22 | import java.io.File;
23 | import java.io.FileWriter;
24 | import java.io.IOException;
25 | import java.util.Date;
26 |
27 | abstract class Logger {
28 |
29 | private static FileWriter fw;
30 | private static final Date date = new Date();
31 | private final static String APP = "WiFi-Automatic";
32 |
33 | public static void log(final Throwable ex) {
34 | if (!BuildConfig.DEBUG) return;
35 | log(ex.getMessage());
36 | for (StackTraceElement ste : ex.getStackTrace()) {
37 | log(ste.toString());
38 | }
39 | }
40 |
41 | public static void log(final Cursor c) {
42 | if (!BuildConfig.DEBUG) return;
43 | c.moveToFirst();
44 | String title = "";
45 | for (int i = 0; i < c.getColumnCount(); i++)
46 | title += c.getColumnName(i) + " | ";
47 | log(title);
48 | while (!c.isAfterLast()) {
49 | title = "";
50 | for (int i = 0; i < c.getColumnCount(); i++)
51 | title += c.getString(i) + " | ";
52 | log(title);
53 | c.moveToNext();
54 | }
55 | }
56 |
57 | @SuppressWarnings("deprecation")
58 | public static void log(String msg) {
59 | if (!BuildConfig.DEBUG) return;
60 | android.util.Log.d(APP, msg);
61 | try {
62 | if (fw == null) {
63 | fw = new FileWriter(new File(
64 | Environment.getExternalStorageDirectory().toString() + "/" + APP + ".log"),
65 | true);
66 | }
67 | date.setTime(System.currentTimeMillis());
68 | fw.write(date.toLocaleString() + " - " + msg + "\n");
69 | fw.flush();
70 | } catch (IOException e) {
71 | e.printStackTrace();
72 | }
73 | }
74 |
75 | protected void finalize() throws Throwable {
76 | try {
77 | if (fw != null) fw.close();
78 | } finally {
79 | super.finalize();
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/res/values-cs/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | alespoň %d min
5 | každý den v %s
6 | každé %s
7 | Rozšířené WiFi nastavení
8 | Další aplikace
9 | Podpořit
10 | Zapnout WiFi…
11 | po odemčení přístroje
12 | Vypnout WiFi pokud…
13 | je vypnutý displej
14 | bez připojení k jakékoliv síti
15 | WiFi připojení je nastaveno na automatické vypnutí při vypnutí displeje. Toto nastavení lze změnit v \'Rozšířeném nastavení WiFi\' Androidu
16 | Roz. WiFi nastavení
17 | Nastavení nenalezeno!
18 | Minut před vypnutím WiFi:
19 | Zapnout WiFi v:
20 | Vypnout WiFi v:
21 | Zapnout WiFi každé …
22 | Neplatný vstup: Číslo musí být >= %1$d a <= %2$d
23 | při napájení
24 | Také ignorovat nastavení \"vypnutý displej\" při napájení
25 |
26 |
27 | - 5 min
28 | - 15 min
29 | - 30 min
30 | - 1 hodina
31 | - 2 hodiny
32 | - 5 hodin
33 | - 10 hodin
34 |
35 |
36 | Hlavní nastavení
37 | Mód Letadlo
38 | Nezapínat WiFi v módu Letadlo
39 | při vstupu do těchto lokací
40 | Ve volné verzi této aplikaci je podporována pouze jedna lokace. Chcete nyní aktualizovat na pro verzi?
41 | Zapnout WiFi při vstupu do těchto lokací:
42 | Používat informace telefonních ústředen pro zapnutí WiFi ve specifických lokacích
43 | WiFi odpojeno
44 | Kliknout pro výběr WiFi sítě
45 | WiFi vypnuto
46 | Kliknutím zapnout
47 | Nastavení zamezuje aplikaci detekovat vaše umístění
48 | Interval:
49 | Aktivní skenování umístění
50 | Více informací
51 | Aplikace nemá oprávnění pro zjištění vašeho umístění
52 |
--------------------------------------------------------------------------------
/src/play/java/de/j4velin/wifiAutoOff/GeoFenceService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.app.IntentService;
19 | import android.content.Intent;
20 |
21 | import com.google.android.gms.location.FusedLocationProviderApi;
22 | import com.google.android.gms.location.Geofence;
23 | import com.google.android.gms.location.GeofencingEvent;
24 | import com.google.android.gms.maps.model.LatLng;
25 |
26 | public class GeoFenceService extends IntentService {
27 |
28 | public GeoFenceService() {
29 | super("WiFiAutomaticGeoFenceService");
30 | }
31 |
32 | @Override
33 | protected void onHandleIntent(final Intent intent) {
34 | if (intent == null) return;
35 | if (intent.hasExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED)) {
36 | android.location.Location loc = (android.location.Location) intent.getExtras()
37 | .get(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
38 | if (BuildConfig.DEBUG) Logger.log("Location update received " + loc);
39 | Database db = Database.getInstance(this);
40 | if (db.inRangeOfLocation(loc)) {
41 | sendBroadcast(new Intent(this, Receiver.class)
42 | .setAction(Receiver.LOCATION_ENTERED_ACTION));
43 | }
44 | db.close();
45 | } else {
46 | GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
47 | // First check for errors
48 | if (geofencingEvent.hasError()) {
49 | // Get the error code with a static method
50 | // Log the error
51 | if (BuildConfig.DEBUG) Logger.log("Location Services error: " +
52 | Integer.toString(geofencingEvent.getErrorCode()));
53 | } else {
54 | // Test that a valid transition was reported
55 | if (geofencingEvent.getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_ENTER) {
56 | Database db = Database.getInstance(this);
57 | for (Geofence gf : geofencingEvent.getTriggeringGeofences()) {
58 | if (BuildConfig.DEBUG) Logger.log("geofence entered: " + gf.getRequestId());
59 | String[] data = gf.getRequestId().split("@");
60 | LatLng ll = new LatLng(Double.parseDouble(data[0]),
61 | Double.parseDouble(data[1]));
62 | String name = db.getNameForLocation(ll);
63 | if (name != null) {
64 | sendBroadcast(new Intent(this, Receiver.class)
65 | .setAction(Receiver.LOCATION_ENTERED_ACTION)
66 | .putExtra(Receiver.EXTRA_LOCATION_NAME, name));
67 | break;
68 | }
69 | }
70 | db.close();
71 | }
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
64 |
65 |
66 |
68 |
73 |
74 |
75 |
76 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/src/main/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | depuis au moins %d minutes
5 | tous les jours à %s
6 | toutes les %s
7 | Options avancées
8 | Plus d\'applications
9 | Donation
10 | Activer le Wi-Fi…
11 | au déverrouillage de l\'écran
12 | Éteindre le wi-fi quand…
13 | l\'écran est éteint
14 | connecté à aucun réseau
15 | Votre politique de veille Wi-Fi est configurée pour désactiver automatiquement le Wi-Fi dès que l\'écran s\'éteint. Vous pouvez changer la politique dans Options Wi-Fi avancées
16 | Options Wi-Fi avancées
17 | Paramètres non trouvés !
18 | Min avant désactivation du Wi-Fi :
19 | Activer le Wi-Fi à :
20 | Désactiver le Wi-Fi à :
21 | Activer le Wi-Fi toutes les…
22 | Entrée incorrecte : le nombre doit être >= %1$d et <= %2$d
23 | au chargement de l\'appareil
24 | Ignore aussi le paramètre \"lorsque l\'écran est éteint\" pendant la charge
25 |
26 |
27 | - 5 minutes
28 | - 15 minutes
29 | - 30 minutes
30 | - 1 heure
31 | - 2 heures
32 | - 5 heures
33 | - 10 heures
34 |
35 |
36 | Paramètres généraux
37 | Mode avion
38 | Ne pas activer le Wi-Fi en mode avion
39 | en entrant dans ces lieux
40 | Un seul lieu disponible dans la version gratuite de l\'application. Voulez-vous passer à la version pro maintenant ?
41 | Activer le Wi-Fi en entrant dans ces lieux :
42 | Utiliser la localisation cellulaire pour activer le Wi-Fi à des lieux spécifiés
43 | Le paramètre \"aucun délai réseau\" peut être trop court pour rechercher des localisations. Modifier à 5 min maintenant ?
44 | Wi-Fi déconnecté
45 | Appuyez pour sélectionner un réseau Wi-Fi
46 | Wi-Fi désactivé
47 | Appuyez pour activer
48 | Vos paramètres empêchent de déterminer votre localisation
49 | Intervalle :
50 | Scanne localisation actif
51 | Plus d\'info
52 | L\'application n\'a pas l\'autorisation d\'accéder à votre localisation
53 |
54 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/ScreenChangeDetector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.app.KeyguardManager;
20 | import android.app.Service;
21 | import android.content.BroadcastReceiver;
22 | import android.content.Context;
23 | import android.content.Intent;
24 | import android.content.IntentFilter;
25 | import android.os.Build;
26 | import android.os.IBinder;
27 | import android.os.PowerManager;
28 |
29 | /**
30 | * Background service which detects SCREEN_OFF events.
31 | *
32 | * Necessary for the 'turn wifi off if screen is off' option
33 | */
34 | public class ScreenChangeDetector extends Service {
35 |
36 | final static String SCREEN_ON_ACTION = "SCREEN_ON";
37 | final static String SCREEN_OFF_ACTION = "SCREEN_OFF";
38 |
39 | private static BroadcastReceiver br;
40 |
41 | @Override
42 | public IBinder onBind(final Intent intent) {
43 | return null;
44 | }
45 |
46 | @Override
47 | public int onStartCommand(final Intent intent, int flags, int startId) {
48 | super.onStartCommand(intent, flags, startId);
49 | if (br == null) {
50 | if (BuildConfig.DEBUG) Logger.log("creating screen receiver");
51 | br = new ScreenOffReceiver();
52 | IntentFilter intf = new IntentFilter();
53 | intf.addAction(Intent.ACTION_SCREEN_ON);
54 | intf.addAction(Intent.ACTION_SCREEN_OFF);
55 | registerReceiver(br, intf);
56 | }
57 | if (intent == null) { // service restarted
58 | // is display already off?
59 | if ((Build.VERSION.SDK_INT < 20 &&
60 | !((PowerManager) getSystemService(POWER_SERVICE)).isScreenOn()) ||
61 | (Build.VERSION.SDK_INT >= 20 && !APILevel20Wrapper.isScreenOn(this))) {
62 | sendBroadcast(new Intent(this, Receiver.class).setAction(SCREEN_OFF_ACTION));
63 | }
64 | }
65 |
66 | return START_STICKY;
67 | }
68 |
69 | @Override
70 | public void onDestroy() {
71 | super.onDestroy();
72 | if (BuildConfig.DEBUG) Logger.log("destroying screen receiver");
73 | if (br != null) {
74 | try {
75 | unregisterReceiver(br);
76 | } catch (Exception e) {
77 | e.printStackTrace();
78 | }
79 | }
80 | br = null;
81 | }
82 |
83 | static class ScreenOffReceiver extends BroadcastReceiver {
84 | @Override
85 | public void onReceive(final Context context, final Intent intent) {
86 | if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
87 | context.sendBroadcast(
88 | new Intent(context, Receiver.class).setAction(SCREEN_OFF_ACTION));
89 | } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction()) &&
90 | !((KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE))
91 | .inKeyguardRestrictedInputMode()) {
92 | // SCREEN_ON is only send if there is no lockscreen active! Otherwise the Receiver will get USER_PRESENT
93 | context.sendBroadcast(
94 | new Intent(context, Receiver.class).setAction(SCREEN_ON_ACTION));
95 | }
96 | }
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/StatusPreference.java:
--------------------------------------------------------------------------------
1 | package de.j4velin.wifiAutoOff;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.net.ConnectivityManager;
6 | import android.net.wifi.WifiInfo;
7 | import android.net.wifi.WifiManager;
8 | import android.preference.Preference;
9 | import android.util.AttributeSet;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.ImageView;
14 | import android.widget.TextView;
15 |
16 | public class StatusPreference extends Preference {
17 |
18 | private ImageView image;
19 | private TextView title;
20 | private TextView sub1;
21 | private TextView sub2;
22 |
23 | public StatusPreference(final Context context, final AttributeSet attrs) {
24 | super(context, attrs);
25 | }
26 |
27 | @Override
28 | protected View onCreateView(final ViewGroup parent) {
29 | super.onCreateView(parent);
30 | LayoutInflater li =
31 | (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
32 | View v = li.inflate(R.layout.statepreference, parent, false);
33 | image = v.findViewById(R.id.icon);
34 | title = v.findViewById(R.id.title);
35 | sub1 = v.findViewById(R.id.sub1);
36 | sub2 = v.findViewById(R.id.sub2);
37 | update();
38 | return v;
39 | }
40 |
41 | /**
42 | * Called to update the status preference
43 | */
44 | void update() {
45 | WifiManager wm = (WifiManager) getContext().getApplicationContext()
46 | .getSystemService(Context.WIFI_SERVICE);
47 | boolean connected = ((ConnectivityManager) getContext().getApplicationContext()
48 | .getSystemService(Context.CONNECTIVITY_SERVICE))
49 | .getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();
50 | if (title == null) return;
51 | if (wm.isWifiEnabled()) {
52 | if (!connected) {
53 | title.setText(R.string.no_connected);
54 | image.setColorFilter(Color.DKGRAY);
55 | sub1.setText(R.string.click_to_select_network);
56 | sub2.setVisibility(View.GONE);
57 | } else {
58 | WifiInfo wi = wm.getConnectionInfo();
59 | String ssid = wi.getSSID();
60 | if (ssid.contains("unknown ssid")) {
61 | // retrieve the SSID might require location permission on some Android versions
62 | ssid = getContext().getString(R.string.event_connected);
63 | }
64 | title.setText(ssid);
65 | image.setColorFilter(getContext().getResources().getColor(R.color.colorAccent));
66 | updateSignal();
67 | int ip = wi.getIpAddress();
68 | sub2.setText(String.format("%d.%d.%d.%d", (ip & 0xff), (ip >> 8 & 0xff),
69 | (ip >> 16 & 0xff), (ip >> 24 & 0xff)));
70 | sub2.setVisibility(View.VISIBLE);
71 | }
72 | } else {
73 | title.setText(R.string.wifi_not_enabled);
74 | image.setColorFilter(Color.LTGRAY);
75 | sub1.setText(R.string.click_to_turn_on);
76 | sub2.setVisibility(View.GONE);
77 | }
78 | }
79 |
80 | /**
81 | * Called to update the WiFi signal text
82 | *
83 | * @return true, if connected to a WiFi network
84 | */
85 | boolean updateSignal() {
86 | WifiManager wm = (WifiManager) getContext().getApplicationContext()
87 | .getSystemService(Context.WIFI_SERVICE);
88 | boolean connected = ((ConnectivityManager) getContext().getApplicationContext()
89 | .getSystemService(Context.CONNECTIVITY_SERVICE))
90 | .getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();
91 | if (sub1 == null) return wm.isWifiEnabled() && connected;
92 | if (wm.isWifiEnabled() && connected) {
93 | WifiInfo wi = wm.getConnectionInfo();
94 | try {
95 | sub1.setText(WifiManager.calculateSignalLevel(wi.getRssi(), 100) + "% - " +
96 | wi.getLinkSpeed() + " Mbps");
97 | } catch (ArithmeticException e) {
98 | // might happen on Android 2.3 devices: https://code.google.com/p/android/issues/detail?id=2555
99 | sub1.setText(wi.getLinkSpeed() + " Mbps");
100 | }
101 | return true;
102 | } else {
103 | return false;
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/play/res/raw/map.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "elementType": "geometry",
4 | "stylers": [
5 | {
6 | "color": "#33b5e5"
7 | }
8 | ]
9 | },
10 | {
11 | "elementType": "labels.text.fill",
12 | "stylers": [
13 | {
14 | "color": "#72cdef"
15 | }
16 | ]
17 | },
18 | {
19 | "elementType": "labels.text.stroke",
20 | "stylers": [
21 | {
22 | "color": "#0c4256"
23 | }
24 | ]
25 | },
26 | {
27 | "featureType": "administrative.country",
28 | "elementType": "geometry.stroke",
29 | "stylers": [
30 | {
31 | "color": "#4b6878"
32 | }
33 | ]
34 | },
35 | {
36 | "featureType": "administrative.land_parcel",
37 | "elementType": "labels.text.fill",
38 | "stylers": [
39 | {
40 | "color": "#64779e"
41 | }
42 | ]
43 | },
44 | {
45 | "featureType": "administrative.province",
46 | "elementType": "geometry.stroke",
47 | "stylers": [
48 | {
49 | "color": "#4b6878"
50 | }
51 | ]
52 | },
53 | {
54 | "featureType": "landscape.man_made",
55 | "elementType": "geometry.stroke",
56 | "stylers": [
57 | {
58 | "color": "#72cdef"
59 | }
60 | ]
61 | },
62 | {
63 | "featureType": "landscape.natural",
64 | "elementType": "geometry",
65 | "stylers": [
66 | {
67 | "color": "#72cdef"
68 | }
69 | ]
70 | },
71 | {
72 | "featureType": "poi",
73 | "elementType": "geometry",
74 | "stylers": [
75 | {
76 | "color": "#14789e"
77 | }
78 | ]
79 | },
80 | {
81 | "featureType": "poi",
82 | "elementType": "labels.text.fill",
83 | "stylers": [
84 | {
85 | "color": "#6f9ba5"
86 | }
87 | ]
88 | },
89 | {
90 | "featureType": "poi",
91 | "elementType": "labels.text.stroke",
92 | "stylers": [
93 | {
94 | "color": "#1d2c4d"
95 | }
96 | ]
97 | },
98 | {
99 | "featureType": "poi.park",
100 | "elementType": "geometry.fill",
101 | "stylers": [
102 | {
103 | "color": "#023e58"
104 | }
105 | ]
106 | },
107 | {
108 | "featureType": "poi.park",
109 | "elementType": "labels.text.fill",
110 | "stylers": [
111 | {
112 | "color": "#1582aa"
113 | }
114 | ]
115 | },
116 | {
117 | "featureType": "road",
118 | "elementType": "geometry",
119 | "stylers": [
120 | {
121 | "color": "#304a7d"
122 | }
123 | ]
124 | },
125 | {
126 | "featureType": "road",
127 | "elementType": "labels.text.fill",
128 | "stylers": [
129 | {
130 | "color": "#33b5e5"
131 | }
132 | ]
133 | },
134 | {
135 | "featureType": "road",
136 | "elementType": "labels.text.stroke",
137 | "stylers": [
138 | {
139 | "color": "#1d2c4d"
140 | }
141 | ]
142 | },
143 | {
144 | "featureType": "road.highway",
145 | "elementType": "geometry",
146 | "stylers": [
147 | {
148 | "color": "#72cdef"
149 | }
150 | ]
151 | },
152 | {
153 | "featureType": "road.highway",
154 | "elementType": "geometry.stroke",
155 | "stylers": [
156 | {
157 | "color": "#0c516b"
158 | }
159 | ]
160 | },
161 | {
162 | "featureType": "road.highway",
163 | "elementType": "labels.text.fill",
164 | "stylers": [
165 | {
166 | "color": "#b0d5ce"
167 | }
168 | ]
169 | },
170 | {
171 | "featureType": "road.highway",
172 | "elementType": "labels.text.stroke",
173 | "stylers": [
174 | {
175 | "color": "#023e58"
176 | }
177 | ]
178 | },
179 | {
180 | "featureType": "transit",
181 | "elementType": "labels.text.fill",
182 | "stylers": [
183 | {
184 | "color": "#b3e3f7"
185 | }
186 | ]
187 | },
188 | {
189 | "featureType": "transit.line",
190 | "elementType": "geometry.fill",
191 | "stylers": [
192 | {
193 | "color": "#72cdef"
194 | }
195 | ]
196 | },
197 | {
198 | "featureType": "transit.station",
199 | "elementType": "geometry",
200 | "stylers": [
201 | {
202 | "color": "#0c455a"
203 | }
204 | ]
205 | },
206 | {
207 | "featureType": "water",
208 | "elementType": "geometry",
209 | "stylers": [
210 | {
211 | "color": "#0e1626"
212 | }
213 | ]
214 | },
215 | {
216 | "featureType": "water",
217 | "elementType": "labels.text.fill",
218 | "stylers": [
219 | {
220 | "color": "#4e6d70"
221 | }
222 | ]
223 | }
224 | ]
--------------------------------------------------------------------------------
/src/play/res/layout/locations.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
26 |
27 |
38 |
39 |
47 |
48 |
58 |
59 |
69 |
70 |
82 |
83 |
92 |
93 |
98 |
99 |
108 |
109 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/APILevel26ForegroundService.java:
--------------------------------------------------------------------------------
1 | package de.j4velin.wifiAutoOff;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Notification;
5 | import android.app.NotificationChannel;
6 | import android.app.NotificationManager;
7 | import android.app.PendingIntent;
8 | import android.app.Service;
9 | import android.content.BroadcastReceiver;
10 | import android.content.Context;
11 | import android.content.Intent;
12 | import android.content.IntentFilter;
13 | import android.content.SharedPreferences;
14 | import android.os.Build;
15 | import android.os.IBinder;
16 | import android.preference.PreferenceManager;
17 | import android.provider.Settings;
18 | import android.support.v4.app.NotificationCompat;
19 |
20 | @TargetApi(Build.VERSION_CODES.O)
21 | public class APILevel26ForegroundService extends Service {
22 |
23 | private final static String CHANNEL_ID = "foregroundService";
24 |
25 | public static void start(final Context context) {
26 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
27 | createNotificationChannel(context);
28 | context.startForegroundService(new Intent(context, APILevel26ForegroundService.class));
29 | }
30 | }
31 |
32 | private static void createNotificationChannel(final Context context) {
33 | NotificationManager mNotificationManager =
34 | (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
35 | NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "WiFi Automatic",
36 | NotificationManager.IMPORTANCE_LOW);
37 | channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
38 | channel.setDescription(context.getString(R.string.notification_desc));
39 | mNotificationManager.createNotificationChannel(channel);
40 | }
41 |
42 | private final static BroadcastReceiver RECEIVER = new Receiver();
43 | private final static IntentFilter[] FILTERS =
44 | new IntentFilter[]{new IntentFilter("android.net.wifi.STATE_CHANGE"),
45 | new IntentFilter("android.net.wifi.WIFI_STATE_CHANGED"),
46 | new IntentFilter("android.net.wifi.p2p.CONNECTION_STATE_CHANGE"),
47 | new IntentFilter("android.intent.action.ACTION_POWER_CONNECTED"),
48 | new IntentFilter("android.intent.action.ACTION_POWER_DISCONNECTED")};
49 | private static ScreenChangeDetector.ScreenOffReceiver screenOffReceiver;
50 | private static boolean registered;
51 |
52 | @Override
53 | public IBinder onBind(Intent intent) {
54 | return null;
55 | }
56 |
57 | @Override
58 | public void onCreate() {
59 | super.onCreate();
60 | if (BuildConfig.DEBUG) Logger.log("API26ForegroundService onCreate");
61 | }
62 |
63 | @Override
64 | public int onStartCommand(Intent intent, int flags, int startId) {
65 | startForeground(42,
66 | new NotificationCompat.Builder(this, CHANNEL_ID).setSmallIcon(R.drawable.icon_black)
67 | .setContentTitle("WiFi Automatic")
68 | .setContentText(getString(R.string.hide_notification)).setContentIntent(
69 | PendingIntent.getActivity(this, 1,
70 | new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
71 | .putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName())
72 | .putExtra(Settings.EXTRA_CHANNEL_ID, CHANNEL_ID), 0))
73 | .build());
74 | synchronized (CHANNEL_ID) {
75 | if (!registered) {
76 | for (IntentFilter filter : FILTERS) {
77 | registerReceiver(RECEIVER, filter);
78 | }
79 | registered = true;
80 | }
81 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
82 | if (prefs.getBoolean("off_screen_off", true) || prefs.getBoolean("on_unlock", true)) {
83 | if (screenOffReceiver == null) {
84 | screenOffReceiver = new ScreenChangeDetector.ScreenOffReceiver();
85 | }
86 | registerReceiver(screenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
87 | registerReceiver(screenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
88 | registerReceiver(RECEIVER, new IntentFilter(Intent.ACTION_USER_PRESENT));
89 | } else if (screenOffReceiver != null) {
90 | try {
91 | unregisterReceiver(screenOffReceiver);
92 | } catch (Exception e) {
93 | // ignore
94 | }
95 | screenOffReceiver = null;
96 | }
97 | }
98 | return START_STICKY;
99 | }
100 |
101 | @Override
102 | public void onDestroy() {
103 | super.onDestroy();
104 | if (BuildConfig.DEBUG) Logger.log("API26ForegroundService onDestroy");
105 | synchronized (CHANNEL_ID) {
106 | registered = false;
107 | try {
108 | unregisterReceiver(RECEIVER);
109 | if (screenOffReceiver != null) {
110 | unregisterReceiver(screenOffReceiver);
111 | }
112 | } catch (Throwable t) {
113 | if (BuildConfig.DEBUG) Logger.log(t);
114 | }
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/play/java/de/j4velin/wifiAutoOff/Map.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.Manifest;
19 | import android.graphics.Color;
20 | import android.os.Bundle;
21 | import android.support.v4.app.ActivityCompat;
22 | import android.support.v4.content.PermissionChecker;
23 | import android.support.v7.app.AppCompatActivity;
24 |
25 | import com.google.android.gms.common.api.GoogleApiClient;
26 | import com.google.android.gms.location.LocationServices;
27 | import com.google.android.gms.maps.CameraUpdateFactory;
28 | import com.google.android.gms.maps.GoogleMap;
29 | import com.google.android.gms.maps.OnMapReadyCallback;
30 | import com.google.android.gms.maps.SupportMapFragment;
31 | import com.google.android.gms.maps.model.CircleOptions;
32 | import com.google.android.gms.maps.model.LatLng;
33 | import com.google.android.gms.maps.model.MapStyleOptions;
34 |
35 | public class Map extends AppCompatActivity implements OnMapReadyCallback {
36 |
37 | private final static int REQUEST_PERMISSIONS = 1;
38 |
39 | private GoogleApiClient mGoogleApiClient;
40 |
41 | private void showMap() {
42 | setContentView(R.layout.map);
43 | ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
44 | .getMapAsync(this);
45 | }
46 |
47 | @Override
48 | public void onCreate(final Bundle savedInstanceState) {
49 | super.onCreate(savedInstanceState);
50 |
51 | if (PermissionChecker
52 | .checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) !=
53 | PermissionChecker.PERMISSION_GRANTED || PermissionChecker
54 | .checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) !=
55 | PermissionChecker.PERMISSION_GRANTED) {
56 | ActivityCompat.requestPermissions(Map.this,
57 | new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
58 | Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSIONS);
59 | } else {
60 | showMap();
61 | }
62 | }
63 |
64 | @Override
65 | public void onRequestPermissionsResult(int requestCode, final String[] permissions,
66 | final int[] grantResults) {
67 | if (requestCode == REQUEST_PERMISSIONS) {
68 | if (grantResults.length >= 2 &&
69 | grantResults[0] == PermissionChecker.PERMISSION_GRANTED &&
70 | grantResults[1] == PermissionChecker.PERMISSION_GRANTED) {
71 | showMap();
72 | } else {
73 | finish();
74 | }
75 | } else {
76 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
77 | }
78 | }
79 |
80 | @SuppressWarnings("MissingPermission")
81 | @Override
82 | public void onMapReady(final GoogleMap mMap) {
83 | MapStyleOptions style = MapStyleOptions.loadRawResourceStyle(this, R.raw.map);
84 | mMap.setMapStyle(style);
85 | LatLng location = getIntent().getParcelableExtra("location");
86 | if (location == null) {
87 | mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API)
88 | .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
89 | @Override
90 | public void onConnected(final Bundle bundle) {
91 | android.location.Location l = LocationServices.FusedLocationApi
92 | .getLastLocation(mGoogleApiClient);
93 | if (l != null && mMap.getCameraPosition().zoom <= 2) {
94 | mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
95 | new LatLng(l.getLatitude(), l.getLongitude()), 16));
96 | }
97 | mGoogleApiClient.disconnect();
98 | }
99 |
100 | @Override
101 | public void onConnectionSuspended(int cause) {
102 | if (BuildConfig.DEBUG) Logger.log("connection suspended: " + cause);
103 | }
104 | }).build();
105 |
106 | mGoogleApiClient.connect();
107 |
108 | mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
109 | @Override
110 | public void onMapClick(final LatLng center) {
111 | getIntent().putExtra("location", center);
112 | setResult(RESULT_OK, getIntent());
113 | finish();
114 | }
115 | });
116 | } else {
117 | mMap.addCircle(new CircleOptions().center(location).radius(100).strokeColor(Color.BLUE)
118 | .fillColor(Color.argb(64, 0, 0, 255)));
119 | mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 16));
120 | }
121 |
122 | mMap.setMyLocationEnabled(true);
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | per almeno %d min
6 | ogni giorno alle %s
7 | ogni %s
8 | Impostazioni WiFi avanzate
9 | Altre apps
10 | Donazione
11 | Accendi il WiFi…
12 | quando il device viene sbloccato
13 | Spegni il WiFi quando…
14 | lo schermo e` spento
15 | non sei connesso ad alcuna rete
16 | Le tue impostazioni del WiFi sono impostate per disabilitare automaticamente il WiFi quando lo schermo si spegne. Puoi cambiare le impostazioni nel menu \'Impostazioni avanzate WiFi\' di Android
17 |
18 | Impostazioni WiFi avanzate
19 | Impostazione non trovata!
20 | Minuti prima di spegnere il WiFi:
21 | Accendi il WiFi alle:
22 | Spegni il WiFi alle:
23 | Accendi il WiFi ogni …
24 | Input invalido: il numero deve essere >= %1$d e <=
25 | %2$d
26 |
27 | quando e` in carica
28 | Ignora l\'impostazione \"quando lo schermo e` spento\" mentre e` in carica
29 |
30 |
31 |
32 | - 5 min
33 | - 15 min
34 | - 30 min
35 | - 1 ora
36 | - 2 ore
37 | - 5 ore
38 | - 10 ore
39 |
40 |
41 | Impostazioni Generali
42 | Modalita` aereo
43 | Non abilitare il WiFi in modalita` aereo
44 | quanto ci si trova in queste posizioni
45 | Solo una posizione e` supportata nella versione free dell\'app. Vuoi installare la versione pro ora?
46 |
47 | Accendi il WiFi quando sei in queste posizioni:
48 | Usa le informazioni della posizione della cella per accendere il WiFi in una determinata posizione
49 |
50 | WiFi disconnesso
51 | Clicca per selezionare la rete WiFi
52 | WiFi disabilitato
53 | Clicca per accendere
54 | Le tue impostazioni non permettono all\'app di determinare la tua posizione
55 | Intervallo:
56 | Attiva lo scan della posizione
57 | Altre informazioni
58 | L\'App non ha i permessi per accedere alla tua posizione
59 | Nessun log ancora
60 | Mostra gli ultimi eventi che hanno cambiato lo stato del WiFi
61 | Log
62 | Non accendere il WiFi perche` il device e` in modalita` aereo
63 | Accendi il WiFi
64 | Spegni il WiFi
65 | Posizione inserita: %s
66 | L\'evento schermo spento e` stato ignorato perche` il device e` in carica
67 |
68 | Device sbloccato
69 | WiFi connesso
70 | WiFi disconnesso
71 | WiFi abilitato
72 | WiFi disablitato
73 | Caricabatterie connesso
74 | Caricabatterie disconnesso
75 | Timer dello schermo spento cancellato
76 | Timer senza rete cancellato
77 | Timer dello schermo impostato (%d min)
78 | Timer senza rete impostato (%d min)
79 | Cancella log
80 | Accendi/Spegni
81 | Non accendere il WiFi se l\'hotspot WiFi e` attivo
82 | Impossibile cambiare lo stato del WiFi
83 | Impossibile cambiare lo stato del WiFi: %s
84 | Il device e` in modalita` aereo
85 | Attenzione: Con la tua versione di Android, l\'app non puo` cambiare lo stato del WiFi
86 | mentre il device e` in modalita` aereo!
87 |
88 |
89 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/src/main/res/values-pt/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | por pelo menos %d minutos
6 | todos dias às %s
7 | cada %s
8 | Ajustes avançados de WiFi
9 | Mais apps
10 | Doar
11 | Ligue o WiFi…
12 | ao desbloquear o dispositivo
13 | Desligar WiFi quando…
14 | a tela desliga
15 | não está conectado a ninhuma rede
16 | Sua política de hibernação de Wi-Fi está definida para desativar automaticamente
17 | o WiFi quando a tela é desligada. Você pode alterar a política nos \'ajustes avançados de WiFi\' do Android
18 |
19 | Ajustes av. de WiFi
20 | Nenhuma configuração encontrada!
21 | Minutos antes de desligar o WiFi:
22 | Ligue o WiFi em:
23 | Desligue o WiFi em:
24 | Ligue o WiFi a cada …
25 | Entrada inválida: o número deve ser >= %1$d y <=
26 | %2$d
27 |
28 | durante o carregamento
29 | Ignorar também as configurações \"quando a tela desliga\" durante o carregamento
30 |
31 |
32 |
33 | - 5 minutos
34 | - 15 minutos
35 | - 30 minutos
36 | - 1 hora
37 | - 2 horas
38 | - 5 horas
39 | - 10 horas
40 |
41 |
42 | Configurações Gerais
43 | Modo avião
44 | Não habilitar WiFi ao estrar em modo avião
45 | ao entrar nestas localizações
46 | A versão gratuita do app permite uma só Localização. Deseja
47 | atualizar para a versão pro?
48 |
49 | Ligue o WiFi ao entrar nestes locais:
50 | Use as informações de localização do seu telefone para ligar o WiFi em locais
51 | definidas
52 |
53 | Wi-Fi desconectado
54 | Pressione para selecionar uma rede WiFi
55 | Wifi desativado
56 | Pressione para ligar
57 | Sua configuração atual impede que o aplicativo detecte sua
58 | Localização
59 |
60 | Intervalo:
61 | Verificação de localização ativa
62 | Mais informações
63 | O aplicativo não tem permissão para acessar sua localização
64 | Ainda não há registros
65 | Mostra os últimos eventos que mudaram o status do WiFi
66 | Registro
67 | O WiFi não será ativado porque o dispositivo está no modo avião
68 | Ativando WiFi
69 | Desativando WiFi
70 | Localização inserida: %s
71 | Status da tela ignorado devido ao dispositivo estar conectado
72 | para uma tomada
73 |
74 | Dispositivo desbloqueado
75 | WiFi conectado
76 | Wi-Fi desconectado
77 | Wi-Fi habilitado
78 | Wifi desativado
79 | Conectado a uma tomada externa
80 | Desconectado da tomada
81 | O temporizador de desligamento da tela foi cancelado
82 | Nenhum timer de rede foi cancelado
83 | Temporizador de desligamento de tela atribuído (%d min)
84 | Nenhum temporizador atribuído à rede (%d min)
85 | Apagar registro de logs
86 | Ativar/Desativar
87 | Não ative o WiFi se houver um ponto de acesso WiFi ativo
88 | Não é possível alterar o status do WiFi
89 | Não é possível alterar o status do WiFi: %s
90 | O dispositivo está em modo avião
91 | Aviso: Na sua versão Android, os aplicativos não podem alterar o
92 | Status do WiFi se o dispositivo estiver no modo avião!
93 |
94 |
95 |
--------------------------------------------------------------------------------
/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | по истечении %d мин.
5 | каждый день в %s
6 | каждые %s
7 | Расширенные настройки WiFi
8 | Другие приложения
9 | Пожертвовать
10 | Включать WiFi…
11 | когда устройство разблокировано
12 | Отключать WiFi…
13 | когда экран отключен
14 | когда нет сетевой активности
15 | Ваши настройки спящего режима WiFi, будут отключать WiFi как только погаснет экран. Вы можете изменить это, перейдя в \'Расширенные настройки WiFi\' вашего Android
16 | Расш. настройки WiFi
17 | Настройки не найдены!
18 | Минуты перед отключением WiFi:
19 | Включить WiFi в:
20 | Отключить WiFi в:
21 | Включать WiFi каждые …
22 | Ошибка ввода: Число должно быть >= %1$d и <= %2$d
23 | когда устройство заряжается
24 | Будет проигнорирована настройка \'когда экран отключен\'
25 |
26 |
27 | - 5 мин.
28 | - 15 мин.
29 | - 30 мин.
30 | - 1 час
31 | - 2 часа
32 | - 5 часов
33 | - 10 часов
34 |
35 |
36 | Общие настройки
37 | Режим полета
38 | Не включать WiFi в \'режиме полета\'
39 | при нахождении в этих местах
40 | В бесплатной версии доступна настройка только одного местоположения. Вы хотите перейти на Pro версию сейчас?
41 | Включать WiFi при нахождении в этих местах:
42 | Использовать информацию о своем местоположении, для включения WiFi в определённых местах
43 | WiFi не подключен
44 | Нажмите для выбора WiFi сети
45 | WiFi выключен
46 | Нажмите чтобы включить
47 | Настройки вашего телефона запрещают приложению определять местоположение
48 | Интервал:
49 | Активная проверка местоположения
50 | Подробнее
51 | У приложения нет прав доступа к вашему местоположению
52 | В журнале нет записей
53 | Просмотр последних событий в работе приложения
54 | Журнал
55 | WiFi не был включен, потому что устройство находится в \'режиме полета\'
56 | Включение WiFi
57 | Выключение WiFi
58 | Нахождение в местоположении: %s
59 | Отключение экрана не произошло, так как устройство подключено к зарядке
60 | Устройство разблокировано
61 | WiFi подключен
62 | WiFi отключен
63 | WiFi включен
64 | WiFi выключен
65 | Подключено внешнее питание
66 | Отключено внешнее питание
67 | Таймер отключения экрана отменен
68 | Таймер сетевой активности отменен
69 | Запущен таймер отключения экрана (%d мин)
70 | Запущен таймер сетевой активности (%d мин)
71 | Экран выключен
72 | Экран включен/string>
73 | Очистить
74 | Вкл/Выкл
75 | WiFi не был переключен, так как он находится в режиме \'точка доступа\'
76 | Невозможно переключить WiFi
77 | Невозможно переключить WiFi: %s
78 | Устройство находится в \'режиме полета\'
79 | Внимание: На вашей версии Android нельзя переключать WiFi, если устройство находится в \'режиме полета\'!
80 | Приложение неактивно
81 | Приложение активно
82 | Нажмите сюда, что бы скрыть это уведомление
83 | Это уведомление необходимо для работы WiFi Automatic на устройствах Android 8+. Вы можете без проблем отключить его.
84 | Эта функция не работает без разрешенного доступа к местоположению
85 | Для включения WiFi в зависимости от вашего местоположения требуется разрешение на доступ к местоположению, даже если приложение закрыто или не активно. Вы хотите дать это разрешение сейчас?
86 |
87 |
--------------------------------------------------------------------------------
/src/play/java/de/j4velin/wifiAutoOff/GeofenceUpdateService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.Manifest;
19 | import android.app.PendingIntent;
20 | import android.content.Context;
21 | import android.content.Intent;
22 | import android.content.SharedPreferences;
23 | import android.os.Bundle;
24 | import android.support.annotation.NonNull;
25 | import android.support.v4.app.JobIntentService;
26 | import android.support.v4.content.PermissionChecker;
27 |
28 | import com.google.android.gms.common.ConnectionResult;
29 | import com.google.android.gms.common.api.GoogleApiClient;
30 | import com.google.android.gms.location.Geofence;
31 | import com.google.android.gms.location.GeofencingRequest;
32 | import com.google.android.gms.location.LocationRequest;
33 | import com.google.android.gms.location.LocationServices;
34 |
35 | import java.util.List;
36 |
37 | public class GeofenceUpdateService extends JobIntentService implements
38 | GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
39 |
40 | private final static int LOCATION_RANGE_METER = 200;
41 | private static final int JOB_ID = 4242;
42 | private GoogleApiClient mLocationClient;
43 |
44 | public static void enqueueJob(Context context) {
45 | try {
46 | enqueueWork(context, GeofenceUpdateService.class, JOB_ID, new Intent());
47 | } catch (Exception e) {
48 | if (BuildConfig.DEBUG) Logger.log(e);
49 | }
50 | }
51 |
52 | @Override
53 | protected void onHandleWork(@NonNull Intent intent) {
54 | if (mLocationClient == null) {
55 | mLocationClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API)
56 | .addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
57 | mLocationClient.connect();
58 | }
59 | }
60 |
61 | @Override
62 | public void onConnected(final Bundle bundle) {
63 | if (mLocationClient == null) return; // should not happen?
64 | if (BuildConfig.DEBUG) Logger.log("removing all fences");
65 | PendingIntent pi = PendingIntent
66 | .getService(this, 0, new Intent(this, GeoFenceService.class),
67 | PendingIntent.FLAG_UPDATE_CURRENT);
68 | LocationServices.GeofencingApi.removeGeofences(mLocationClient, pi);
69 | LocationServices.FusedLocationApi.removeLocationUpdates(mLocationClient, pi);
70 | Database database = Database.getInstance(this);
71 | List locations = database.getLocations();
72 | database.close();
73 |
74 | SharedPreferences prefs = getSharedPreferences("locationPrefs", MODE_PRIVATE);
75 |
76 | if (BuildConfig.DEBUG) Logger.log("re-adding all " + locations.size() + " fences");
77 | if (!locations.isEmpty()) {
78 | GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
79 | builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
80 | for (Location l : locations) {
81 | try {
82 | builder.addGeofence(new Geofence.Builder()
83 | .setCircularRegion(l.coords.latitude, l.coords.longitude,
84 | LOCATION_RANGE_METER)
85 | .setRequestId(l.coords.latitude + "@" + l.coords.longitude)
86 | .setExpirationDuration(Geofence.NEVER_EXPIRE)
87 | .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER).build());
88 | } catch (Exception e) {
89 | if (BuildConfig.DEBUG) Logger.log(e);
90 | }
91 | }
92 | try {
93 | if (PermissionChecker
94 | .checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) ==
95 | PermissionChecker.PERMISSION_GRANTED && PermissionChecker
96 | .checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
97 | PermissionChecker.PERMISSION_GRANTED) {
98 | LocationServices.GeofencingApi
99 | .addGeofences(mLocationClient, builder.build(), pi);
100 | if (prefs.getBoolean("active", false)) {
101 | LocationRequest mLocationRequest = new LocationRequest();
102 | mLocationRequest.setInterval(prefs.getInt("interval", 15) * 60000);
103 | mLocationRequest.setFastestInterval(5000);
104 | mLocationRequest.setSmallestDisplacement(50f);
105 | mLocationRequest
106 | .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
107 | LocationServices.FusedLocationApi
108 | .requestLocationUpdates(mLocationClient, mLocationRequest, pi);
109 | }
110 | } else {
111 | if (BuildConfig.DEBUG) Logger.log("no location permission");
112 | }
113 | } catch (Exception iae) {
114 | if (BuildConfig.DEBUG) Logger.log(iae);
115 | }
116 | }
117 | disconnect();
118 | }
119 |
120 | @Override
121 | public void onConnectionSuspended(int i) {
122 | disconnect();
123 | }
124 |
125 | private void disconnect() {
126 | if (BuildConfig.DEBUG) Logger.log("GeofenceUpdateService disconnect");
127 | if (mLocationClient != null) mLocationClient.disconnect();
128 | mLocationClient = null;
129 | stopSelf();
130 | }
131 |
132 | @Override
133 | public void onConnectionFailed(final ConnectionResult connectionResult) {
134 | disconnect();
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | for at least %d min
5 | everyday at %s
6 | every %s
7 | Advanced WiFi settings
8 | More apps
9 | Donate
10 | Turn WiFi on…
11 | when device gets unlocked
12 | Turn WiFi off when…
13 | screen is off
14 | not connected to any network
15 | Your WiFi sleep policy is set to automatically disable WiFi as soon
16 | as the display goes off. You can change the policy in the Android \'Advanced WiFi settings\'
17 |
18 | Adv. WiFi settings
19 | Settings not found!
20 | Minutes before turning off WiFi:
21 | Turn WiFi on at:
22 | Turn WiFi off at:
23 | Turn WiFi on every …
24 | Invalid input: Number has to be >= %1$d and <=
25 | %2$d
26 |
27 | when charging
28 | Also ignores the \"when screen is off\" setting while charging
29 |
30 |
31 |
32 | - 5 min
33 | - 15 min
34 | - 30 min
35 | - 1 hour
36 | - 2 hours
37 | - 5 hours
38 | - 10 hours
39 |
40 |
41 | General settings
42 | Airplane mode
43 | Don\'t enable WiFi when in airplane mode
44 | when entering these locations
45 | Only one location is support in the free version of the app. Do you want
46 | to upgrade to the pro version now?
47 |
48 | Turn on WiFi when entering these locations:
49 | Use cell location information to turn WiFi on at specified
50 | locations
51 |
52 | WiFi disconnected
53 | Click to select WiFi network
54 | WiFi disabled
55 | Click to turn on
56 | Your settings prevent the app from detect your
57 | location
58 |
59 | Interval:
60 | Active location scanning
61 | More info
62 | App does not have permission to access your location
63 | No log entries yet
64 | Shows the last events which triggered a WiFi change
65 | Log
66 | Not turning WiFi on because device is in airplane mode
67 | Turning WiFi on
68 | Turning WiFi off
69 | Location entered: %s
70 | Screen off event ignored because device is connected
71 | to external power
72 |
73 | Device unlocked
74 | WiFi connected
75 | WiFi disconnected
76 | WiFi enabled
77 | WiFi disabled
78 | External power connected
79 | External power disconnected
80 | Screen off timer canceled
81 | No network timer canceled
82 | Screen off timer set (%d min)
83 | No network timer set (%d min)
84 | Display turned off
85 | Display turned on
86 | Delete log
87 | Turn on/off
88 | Not turning WiFi on as WiFi hotspot is active
89 | Unable to change WiFi state
90 | Unable to change WiFi state: %s
91 | Device is in airplane mode
92 | Notice: On your Android version, apps can not change the WiFi
93 | state while the device is in airplane mode!
94 |
95 | App disabled
96 | App enabled
97 | Click here to hide this notification
98 | This notification is necessary to keep WiFi Automatic running
99 | on Android 8+ devices. You can safely disable it from being shown.
100 |
101 | This feature will not work without location permission
102 | Enabling WiFi based on your location requires the permission to access your location,
103 | even when the app is closed or not in use. Do you want to grant this permission now?
104 |
--------------------------------------------------------------------------------
/src/main/res/values-es/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | por al menos %d minutos
6 | cada día a las %s
7 | cada %s
8 | Ajustes avanzados de WiFi
9 | Más aplicaciones
10 | Hacer una donación
11 | Encender WiFi…
12 | al desbloquear el dispositivo
13 | Apagar WiFi cuando…
14 | la pantalla se apague
15 | no está conectado a ningúna red
16 | Su política de suspensión de Wi-Fi está configurada para desactivar
17 | automáticamente el WiFi al apagarse la pantalla. Puede cambiar la política en los
18 | \'Ajustes avanzados de WiFi\' de Android
19 |
20 | Ajustes av. de WiFi
21 | ¡No se han encontrado ajustes!
22 | Minutos antes de apagar el WiFi:
23 | Encender WiFi a las:
24 | Apagar WiFi a las:
25 | Encender WiFi cada …
26 | Entrada no válida: el número debe ser >= %1$d y
27 | <= %2$d
28 |
29 | durante la carga
30 | También ignora la configuración \"cuando la pantalla se apague\"
31 | durante la carga
32 |
33 |
34 |
35 | - 5 minutos
36 | - 15 minutos
37 | - 30 minutos
38 | - 1 hora
39 | - 2 horas
40 | - 5 horas
41 | - 10 horas
42 |
43 |
44 | Ajustes generales
45 | Modo avión
46 | No activar el WiFi al estar en modo avión
47 | al entrar en estas ubicaciones
48 | La versión gratuita de la aplicación permite una única ubicación. ¿Quiere
49 | actualizar a la versión pro?
50 |
51 | Encender el WiFi al entrar en estas ubicaciones:
52 | Usar la información de ubicación del teléfono para encender el
53 | WiFi en las ubicaciones especificadas
54 |
55 | WiFi desconectado
56 | Pulsa para seleccionar una red WiFi
57 | WiFi desactivado
58 | Pulsa para encender
59 | Sus configuraciones impiden que la aplicación detecte
60 | su ubicación
61 |
62 | Intervalo:
63 | Escaneo de ubicación activo
64 | Más info
65 | La app no tiene permiso para acceder a su ubicación
66 | Aún no hay registros
67 | Muestra los últimos eventos que cambiaron el estado del WiFi
68 | Registro
69 | No se activará el WiFi ya que el dispositivo se encuentra en modo avión
70 | Activando WiFi
71 | Desactivando WiFi
72 | Ubicación introducida: %s
73 | No se ha apagado la pantalla debido a que el
74 | dispositivo está conectado a una toma de corriente
75 |
76 | Dispositivo desbloqueado
77 | WiFi conectado
78 | WiFi desconectado
79 | WiFi activado
80 | WiFi desactivado
81 | Conectado a una toma de corriente
82 | Desconectado de la toma de corriente
83 | Se ha cancelado el temporizador de pantalla apagada
84 | Se ha cancelado el temporizador de sin red
85 | Temporizador de pantalla apagada asignado (%d min)
86 | Temporizador de sin red asignado (%d min)
87 | Pantalla apagada
88 | Pantalla encendida
89 | Borrar registro
90 | Activar/Desactivar
91 | No se activará el WiFi ya que hay un punto de acceso WiFi activo
92 | No se puede cambiar el estado del WiFi
93 | No se puede cambiar el estado del WiFi: %s
94 | El dispositivo está en modo avión
95 | Aviso: en su versión de Android, las aplicaciones no pueden
96 | cambiar el estado del WiFi cuando el dispositivo está en modo avión.
97 |
98 | Aplicación desactivada
99 | Aplicación activada
100 | Pulse aquí para ocultar esta notificación
101 | Esta notificación es necesaria para que WiFi Automatic se siga
102 | ejecutando en dispositivos Android 8+. Puede ocultarla sin ningún problema.
103 |
104 | Esta característica no funcionará sin el permiso de ubicación
105 |
106 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/Log.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.content.ContentValues;
19 | import android.content.Context;
20 | import android.database.Cursor;
21 | import android.database.sqlite.SQLiteDatabase;
22 | import android.database.sqlite.SQLiteDatabaseLockedException;
23 | import android.database.sqlite.SQLiteOpenHelper;
24 |
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | public class Log {
29 |
30 | /**
31 | * Time to keep the logs in ms
32 | */
33 | final static long KEEP_DURATION = 3 * 24 * 60 * 60 * 1000; // 3 days
34 |
35 | public enum Type {
36 | WIFI_ON(R.drawable.event_wifi_on), WIFI_CONNECTED(R.drawable.event_wifi_on),
37 | WIFI_OFF(R.drawable.event_wifi_off), WIFI_DISCONNECTED(R.drawable.event_wifi_disconnected),
38 | LOCATION_ENTERED(R.drawable.event_location_entered), TIMER(R.drawable.event_timer),
39 | AIRPLANE_MODE(R.drawable.event_airplane_mode), SCREEN_OFF(R.drawable.event_display_off),
40 | SCREEN_ON(R.drawable.event_display_on), UNLOCKED(R.drawable.event_unlock),
41 | AC_CONNECTED(R.drawable.event_ac_connected),
42 | AC_DISCONNECTED(R.drawable.event_ac_disconnected), HOTSPOT(R.drawable.event_hotspot),
43 | ERROR(R.drawable.event_error), APP_DISABLED(R.drawable.event_app_disabled),
44 | APP_ENABLED(R.drawable.event_app_enabled);
45 |
46 | public final int drawable;
47 |
48 | Type(int drawable) {
49 | this.drawable = drawable;
50 | }
51 | }
52 |
53 | private Log() {
54 | }
55 |
56 | /**
57 | * Inserts an event in the persistent log
58 | *
59 | * @param context the context
60 | * @param text the text describing the event
61 | * @param type the type of the event
62 | */
63 | public static void insert(final Context context, final String text, final Type type) {
64 | ContentValues values = new ContentValues();
65 | values.put("date", System.currentTimeMillis());
66 | values.put("info", text);
67 | values.put("type", type.name());
68 | Database db = new Database(context);
69 | try {
70 | db.getWritableDatabase().insert(Database.DB_NAME, null, values);
71 | } catch (Exception e) {
72 | if (BuildConfig.DEBUG) Logger.log(e);
73 | } finally {
74 | db.close();
75 | }
76 | if (BuildConfig.DEBUG) Logger.log(text);
77 | }
78 |
79 | /**
80 | * Inserts an event in the persistent log
81 | *
82 | * @param context the context
83 | * @param text a string resource id which describes this event
84 | * @param type the type of the event
85 | */
86 | public static void insert(final Context context, int text, final Type type) {
87 | insert(context, context.getString(text), type);
88 | }
89 |
90 | /**
91 | * Gets the log
92 | *
93 | * @param context the context
94 | * @param num the maximum number of log entries to load or a number <= 0 to load all entries
95 | * @return a list containing the log entries in descending date order (newest first)
96 | */
97 | public static List- getLog(final Context context, int num) {
98 | List
- result;
99 | Database db = new Database(context);
100 | Cursor c = db.getReadableDatabase()
101 | .query(Database.DB_NAME, new String[]{"date", "info", "type"}, null, null, null,
102 | null, "date DESC", num > 0 ? String.valueOf(num) : null);
103 | if (c != null) {
104 | result = new ArrayList<>(c.getCount());
105 | if (c.moveToFirst()) {
106 | do {
107 | result.add(new Item(c.getLong(0), c.getString(1), c.getString(2)));
108 | } while (c.moveToNext());
109 | }
110 | c.close();
111 | } else {
112 | result = new ArrayList<>(0);
113 | }
114 | db.close();
115 | return result;
116 | }
117 |
118 | /**
119 | * Deletes all log entries which are older then the given duration
120 | *
121 | * @param context the context
122 | * @param duration the duration in ms
123 | */
124 | public static void deleteOldLogs(final Context context, long duration) {
125 | Database db = new Database(context);
126 | try {
127 | int deleted = db.getWritableDatabase().delete(Database.DB_NAME, "date < ?",
128 | new String[]{String.valueOf(System.currentTimeMillis() - duration)});
129 | if (BuildConfig.DEBUG) Logger.log("deleted " + deleted + " old log entries");
130 | } catch (SQLiteDatabaseLockedException e) {
131 | if (BuildConfig.DEBUG) Logger.log("cant delete log: database locked");
132 | } catch (Throwable t) {
133 | if (BuildConfig.DEBUG) Logger.log("cant delete log: " + t.getMessage());
134 | } finally {
135 | db.close();
136 | }
137 | }
138 |
139 | /**
140 | * Container class describing a log item
141 | */
142 | public static class Item {
143 |
144 | final long date;
145 | final String text;
146 | final Type type;
147 |
148 | public Item(long date, final String text, final String type) {
149 | this.date = date;
150 | this.text = text;
151 | this.type = Type.valueOf(type);
152 | }
153 | }
154 |
155 | private static class Database extends SQLiteOpenHelper {
156 |
157 | private final static String DB_NAME = "log";
158 | private final static int DB_VERSION = 1;
159 |
160 | private Database(final Context context) {
161 | super(context, DB_NAME, null, DB_VERSION);
162 | }
163 |
164 | @Override
165 | public void onCreate(final SQLiteDatabase db) {
166 | db.execSQL("CREATE TABLE " + DB_NAME + " (date INTEGER, info TEXT, type TEXT)");
167 | }
168 |
169 | @Override
170 | public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) {
171 |
172 | }
173 | }
174 |
175 | }
176 |
--------------------------------------------------------------------------------
/src/play/java/de/j4velin/wifiAutoOff/Database.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.j4velin.wifiAutoOff;
17 |
18 | import android.content.ContentValues;
19 | import android.content.Context;
20 | import android.database.Cursor;
21 | import android.database.sqlite.SQLiteDatabase;
22 | import android.database.sqlite.SQLiteOpenHelper;
23 |
24 | import com.google.android.gms.maps.model.LatLng;
25 |
26 | import java.util.ArrayList;
27 | import java.util.List;
28 | import java.util.concurrent.atomic.AtomicInteger;
29 |
30 | public class Database extends SQLiteOpenHelper {
31 |
32 | private static final int DATABASE_VERSION = 1;
33 | private static Database instance;
34 |
35 | private static final AtomicInteger openCounter = new AtomicInteger();
36 |
37 | private Database(final Context context) {
38 | super(context, "wifiautomatic", null, DATABASE_VERSION);
39 | }
40 |
41 | public static synchronized Database getInstance(final Context c) {
42 | if (instance == null) {
43 | instance = new Database(c.getApplicationContext());
44 | }
45 | openCounter.incrementAndGet();
46 | return instance;
47 | }
48 |
49 | @Override
50 | public void close() {
51 | if (openCounter.decrementAndGet() == 0) {
52 | super.close();
53 | }
54 | }
55 |
56 | @Override
57 | public void onCreate(final SQLiteDatabase db) {
58 | db.execSQL("CREATE TABLE IF NOT EXISTS locations (name TEXT, lat DOUBLE, lon DOUBLE);");
59 | }
60 |
61 | @Override
62 | public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) {
63 |
64 | }
65 |
66 | /**
67 | * Gets a list of saved locations
68 | *
69 | * @return the list of locations, might be empty
70 | */
71 | public List getLocations() {
72 | Cursor c = getReadableDatabase()
73 | .query("locations", new String[]{"name", "lat", "lon"}, null, null, null, null,
74 | null);
75 | c.moveToFirst();
76 | List re = new ArrayList<>(c.getCount());
77 | while (!c.isAfterLast()) {
78 | if (BuildConfig.DEBUG)
79 | Logger.log("added location: " + c.getString(0) + " " + c.getDouble(1) + " " +
80 | c.getDouble(2));
81 | re.add(new Location(c.getString(0), new LatLng(c.getDouble(1), c.getDouble(2))));
82 | c.moveToNext();
83 | }
84 | c.close();
85 | return re;
86 | }
87 |
88 | /**
89 | * Saves a location
90 | *
91 | * @param name the name (e.g. address or thelike)
92 | * @param coords the latitude, longitude coordinate
93 | */
94 | public void addLocation(final String name, final LatLng coords) {
95 | ContentValues values = new ContentValues();
96 | values.put("name", name);
97 | values.put("lat", coords.latitude);
98 | values.put("lon", coords.longitude);
99 | getWritableDatabase().insert("locations", null, values);
100 | }
101 |
102 | /**
103 | * Deletes a location
104 | *
105 | * @param coords the coordinates of the location to delete
106 | */
107 | public void deleteLocation(final LatLng coords) {
108 | if (BuildConfig.DEBUG) Logger.log("deleting " + coords.toString() + " contained? " +
109 | (getNameForLocation(coords) != null));
110 | getWritableDatabase().delete("locations", "lat LIKE ? AND lon LIKE ?",
111 | new String[]{String.valueOf(coords.latitude).substring(0, 8) + "%",
112 | String.valueOf(coords.longitude).substring(0, 8) + "%"});
113 | }
114 |
115 | /**
116 | * Gets the saved name for the given coordinates
117 | *
118 | * @param coords the location to check
119 | * @return the name for the given locaiton or null, if that location is not a saved location
120 | */
121 | public String getNameForLocation(final LatLng coords) {
122 | String lat = String.valueOf(coords.latitude);
123 | String lon = String.valueOf(coords.longitude);
124 | if (lat.length() > 9) lat = lat.substring(0, 8);
125 | if (lon.length() > 9) lon = lon.substring(0, 8);
126 | Cursor c = getReadableDatabase()
127 | .query("locations", new String[]{"name"}, "lat LIKE ? AND lon LIKE ?",
128 | new String[]{lat + "%", lon + "%"}, null, null, null);
129 | String result;
130 | if (c.moveToFirst()) {
131 | result = c.getString(0);
132 | } else {
133 | result = null;
134 | if (BuildConfig.DEBUG)
135 | Logger.log("location not in database: " + coords.latitude + "," + coords.longitude);
136 | }
137 | c.close();
138 | return result;
139 | }
140 |
141 | /**
142 | * Checks if the given location is within the given range of any saved location
143 | *
144 | * @param current the location to test
145 | * @return true, if 'current' is within range of any saved location
146 | */
147 | public boolean inRangeOfLocation(final android.location.Location current) {
148 | String lat = String.valueOf(current.getLatitude());
149 | String lon = String.valueOf(current.getLongitude());
150 |
151 | Cursor c = getReadableDatabase().query("locations", new String[]{"lat", "lon"},
152 | "ABS(lat - ?) < 0.1 AND ABS(lon - ?) < 0.1", new String[]{lat, lon}, null, null,
153 | null);
154 | if (BuildConfig.DEBUG)
155 | Logger.log(c.getCount() + " locations found which might be in range");
156 | boolean inRange = false;
157 | if (c.moveToFirst()) {
158 | android.location.Location location = new android.location.Location("tester");
159 | while (!inRange && !c.isAfterLast()) {
160 | location.setLatitude(c.getDouble(0));
161 | location.setLongitude(c.getDouble(1));
162 | inRange = location.distanceTo(current) < current.getAccuracy();
163 | if (BuildConfig.DEBUG) Logger.log("distance to " + location + ": " +
164 | location.distanceTo(current));
165 | c.moveToNext();
166 | }
167 | }
168 | c.close();
169 | return inRange;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | für mindestens %d min
5 | täglich um %s
6 | alle %s
7 | Erweiterte WLAN-Einstellungen
8 | Weitere Apps
9 | Spenden
10 | Schalte WLAN ein…
11 | wenn das Gerät entsperrt wird
12 | Schalte WLAN aus…
13 | wenn das Display aus ist
14 | wenn kein Netzwerk in Reichweite
15 | Die WLAN-Optionen sind momentan so eingestellt, dass das WLAN
16 | automatisch abgeschaltet wird, wenn das Display aus geht. Dieses Verhalten kann in den
17 | \'Erweiterten WLAN-Einstellungen\' von Android geändert werden.
18 |
19 | Erw. WLAN-Einstellungen
20 | Einstellungen nicht gefunden!
21 | Dauer in Minuten bevor WLAN ausgeschaltet werden
22 | soll:
23 |
24 | Uhrzeit, zu welcher WLAN eingeschaltet werden soll:
25 | Uhrzeit, zu welcher WLAN abgeschaltet werden soll:
26 | Schalte WLAN alle … ein
27 | Fehlerhafte Eingabe: Zahl muss zwischen %1$d und
28 | %2$d sein
29 |
30 | beim Laden
31 | Ignoriert während des Ladens auch die \"wenn das Display aus ist\"
32 | Einstellung
33 |
34 |
35 |
36 |
- 5 Minuten
37 | - 15 Minuten
38 | - 30 Minuten
39 | - 1 Stunde
40 | - 2 Stunden
41 | - 5 Stunden
42 | - 10 Stunden
43 |
44 |
45 | Allgemein
46 | Flugmodus
47 | Schalte WLAN nicht ein, wenn sich das Gerät im Flugmodus
48 | befindet
49 |
50 | beim Betreten dieser Orte
51 | In der kostenlosen Version der App wird nur ein Ort unterstützt. Möchtest
52 | du jetzt auf die Pro-Version aufwerten?
53 |
54 | Beim Betreten folgender Orte wird das WLAN eingeschaltet:
55 | Verwende Funkmasten-Informationen um WLAN an festgelegten Orten
56 | einzuschalten
57 |
58 | \'Kein Netz in Reichweite\' Einstellung könnte für die
59 | Standort-Optionen zu kurz sein. Jetzt auf die Einstellung \'5 min\' ändern?
60 |
61 | WLAN nicht verbunden
62 | Hier klicken um WLAN-Netzwerk auszuwählen
63 | WLAN ausgeschaltet
64 | Hier klicken zum einzuschalten
65 | Deine Einstellungen verbieten der App deinen Standort
66 | zu bestimmen, diese Funktion wird daher nicht funktionieren. Klicke hier um die
67 | Standort-Einstellungen zu ändern
68 |
69 | Intervall:
70 | Aktive Standort-Bestimmung
71 | Mehr dazu
72 | Die App hat keine Berechtigung zum Zugiff auf den Standort
73 | Keine Log-Einträge vorhanden
74 | Zeigt die letzten von der App registrierten Ereignisse
75 | Log
76 | WLAN nicht aktiviert da sich das Gerät im Flugmodus befindet
77 |
78 | Schalte WLAN ein
79 | Schalte WLAN aus
80 | Standort betreten: %s
81 | Bildschirm wurde ausgeschaltet, aber Gerät ist ans
82 | Stromnetz angeschloßen
83 |
84 | Gerät entsperrt
85 | WLAN verbunden
86 | WLAN Verbindung verloren
87 | WLAN eingeschaltet
88 | WLAN ausgeschaltet
89 | Mit Stromversorgung verbunden
90 | Stromversorgung unterbrochen
91 | "Display aus" Timer abgebrochen
92 | "Keine Verbindung" Timer abgebrochen
93 | "Display aus" Timer gesetzt (%d min)
94 | "Keine Verbindung" Timer gesetzt (%d min)
95 | Display ausgeschaltet
96 | Display eingeschaltet
97 | Log löschen
98 | Ein-/Ausschalten
99 | WiFi Hotspot aktiv, WLAN wird nicht eingeschaltet
100 | WLAN Status kann nicht geändert werden
101 | WLAN Status kann nicht geändert werden: %s
102 | Gerät ist im Flugmodus
103 | Hinweis: In deiner Android Version kann der WLAN Status nicht
104 | durch Apps geändert werden, wenn sich das Gerät im Flugmdus befindet!
105 |
106 | App ausgeschaltet
107 | App eingeschaltet
108 | Klicke hier um diese Benachrichtigung auszublenden
109 | Diese Benachrichtung wird benötigt, damit WiFi Automatic im
110 | Hintergrund laufen kann. Die Benachrichtung kann in den Einstellungen ausgeblendet werden
111 | ohne das die Funktionalität der App beeinträchtigt wird.
112 |
113 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/Start.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.app.AlarmManager;
20 | import android.app.PendingIntent;
21 | import android.content.ComponentName;
22 | import android.content.Context;
23 | import android.content.Intent;
24 | import android.content.SharedPreferences;
25 | import android.content.pm.PackageManager;
26 | import android.os.Build;
27 | import android.preference.PreferenceManager;
28 |
29 | import java.util.Calendar;
30 | import java.util.Date;
31 |
32 | /**
33 | * Utility class to set all necessary timers / start the background service
34 | */
35 | abstract class Start {
36 |
37 | /**
38 | * Creates the ON_AT and OFF_AT timers
39 | *
40 | * @param c the contextl
41 | */
42 | static void createTimers(final Context c) {
43 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
44 | AlarmManager am = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
45 |
46 | Calendar cal = Calendar.getInstance();
47 |
48 | cal.set(Calendar.SECOND, 1);
49 | cal.set(Calendar.MILLISECOND, 0);
50 |
51 | if (prefs.getBoolean("on_at", false)) {
52 | String[] time = prefs.getString("on_at_time", Receiver.ON_AT_TIME).split(":");
53 |
54 | cal.set(Calendar.HOUR_OF_DAY, Integer.valueOf(time[0]));
55 | cal.set(Calendar.MINUTE, Integer.valueOf(time[1]));
56 |
57 | if (cal.getTimeInMillis() <= System.currentTimeMillis())
58 | cal.add(Calendar.DAY_OF_MONTH, 1);
59 |
60 | PendingIntent pi = PendingIntent.getBroadcast(c, Receiver.TIMER_ON_AT,
61 | new Intent(c, Receiver.class).putExtra("changeWiFi", true).setAction("ON_AT"),
62 | PendingIntent.FLAG_UPDATE_CURRENT);
63 | Util.setTimer(c, AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);
64 | if (BuildConfig.DEBUG) Logger.log(
65 | "ON_AT alarm set at " + new Date(cal.getTimeInMillis()).toLocaleString());
66 |
67 | } else { // stop timer
68 | am.cancel(PendingIntent.getBroadcast(c, Receiver.TIMER_ON_AT,
69 | new Intent(c, Receiver.class).putExtra("changeWiFi", true).setAction("ON_AT"),
70 | PendingIntent.FLAG_UPDATE_CURRENT));
71 | }
72 | if (prefs.getBoolean("off_at", false)) {
73 | String[] time = prefs.getString("off_at_time", Receiver.OFF_AT_TIME).split(":");
74 |
75 | cal = Calendar.getInstance();
76 |
77 | cal.set(Calendar.SECOND, 1);
78 | cal.set(Calendar.MILLISECOND, 0);
79 |
80 | cal.set(Calendar.HOUR_OF_DAY, Integer.valueOf(time[0]));
81 | cal.set(Calendar.MINUTE, Integer.valueOf(time[1]));
82 |
83 | if (cal.getTimeInMillis() <= System.currentTimeMillis())
84 | cal.add(Calendar.DAY_OF_MONTH, 1);
85 |
86 | PendingIntent pi = PendingIntent.getBroadcast(c, Receiver.TIMER_OFF_AT,
87 | new Intent(c, Receiver.class).putExtra("changeWiFi", false).setAction("OFF_AT"),
88 | PendingIntent.FLAG_UPDATE_CURRENT);
89 | Util.setTimer(c, AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);
90 | if (BuildConfig.DEBUG) Logger.log(
91 | "OFF_AT alarm set at " + new Date(cal.getTimeInMillis()).toLocaleString());
92 | } else { // stop timer
93 | am.cancel(PendingIntent.getBroadcast(c, Receiver.TIMER_OFF_AT,
94 | new Intent(c, Receiver.class).putExtra("changeWiFi", false).setAction("OFF_AT"),
95 | PendingIntent.FLAG_UPDATE_CURRENT));
96 | }
97 | if (BuildConfig.DEBUG) Logger.log("ON/OFF timers set");
98 | }
99 |
100 | /**
101 | * Sets all necessary timers / starts the background service depending on
102 | * the user settings
103 | *
104 | * @param c the context
105 | */
106 | @SuppressWarnings("deprecation")
107 | static void start(final Context c) {
108 | createTimers(c);
109 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
110 | AlarmManager am = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
111 | if (prefs.getBoolean("on_every", false)) {
112 | long interval = prefs.contains("on_every_time_min") ?
113 | 1000 * 60 * prefs.getInt("on_every_time_min", Receiver.ON_EVERY_TIME_MIN) :
114 | AlarmManager.INTERVAL_HOUR *
115 | prefs.getInt("on_every_time", Receiver.ON_EVERY_TIME_MIN / 60);
116 | am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval,
117 | PendingIntent.getBroadcast(c, Receiver.TIMER_ON_EVERY,
118 | new Intent(c, Receiver.class).putExtra("changeWiFi", true)
119 | .setAction("ON_EVERY"), PendingIntent.FLAG_UPDATE_CURRENT));
120 | } else { // stop timer
121 | am.cancel(PendingIntent.getBroadcast(c, Receiver.TIMER_ON_EVERY,
122 | new Intent(c, Receiver.class).putExtra("changeWiFi", true)
123 | .setAction("ON_EVERY"), PendingIntent.FLAG_UPDATE_CURRENT));
124 | }
125 |
126 | c.getPackageManager().setComponentEnabledSetting(new ComponentName(c, UnlockReceiver.class),
127 | prefs.getBoolean("on_unlock", true) &&
128 | Build.VERSION.SDK_INT < Build.VERSION_CODES.O ?
129 | PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
130 | PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
131 | PackageManager.DONT_KILL_APP);
132 |
133 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
134 | // on O and later, the APILevel26ForegroundService handles this
135 | if (prefs.getBoolean("off_screen_off", true) || prefs.getBoolean("on_unlock", true)) {
136 | c.startService(new Intent(c, ScreenChangeDetector.class));
137 | } else {
138 | c.stopService(new Intent(c, ScreenChangeDetector.class));
139 | }
140 | }
141 |
142 | GeofenceUpdateService.enqueueJob(c);
143 | APILevel26ForegroundService.start(c);
144 |
145 | if (BuildConfig.DEBUG) Logger.log("all timers set/cleared");
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/play/aidl/com/android/vending/billing/IInAppBillingService.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.vending.billing;
18 |
19 | import android.os.Bundle;
20 |
21 | /**
22 | * InAppBillingService is the service that provides in-app billing version 3 and beyond.
23 | * This service provides the following features:
24 | * 1. Provides a new API to get details of in-app items published for the app including
25 | * price, type, title and description.
26 | * 2. The purchase flow is synchronous and purchase information is available immediately
27 | * after it completes.
28 | * 3. Purchase information of in-app purchases is maintained within the Google Play system
29 | * till the purchase is consumed.
30 | * 4. An API to consume a purchase of an inapp item. All purchases of one-time
31 | * in-app items are consumable and thereafter can be purchased again.
32 | * 5. An API to get current purchases of the user immediately. This will not contain any
33 | * consumed purchases.
34 | *
35 | * All calls will give a response code with the following possible values
36 | * RESULT_OK = 0 - success
37 | * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
38 | * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
39 | * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
40 | * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
41 | * RESULT_ERROR = 6 - Fatal error during the API action
42 | * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
43 | * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
44 | */
45 | interface IInAppBillingService {
46 | /**
47 | * Checks support for the requested billing API version, package and in-app type.
48 | * Minimum API version supported by this interface is 3.
49 | * @param apiVersion the billing version which the app is using
50 | * @param packageName the package name of the calling app
51 | * @param type type of the in-app item being purchased "inapp" for one-time purchases
52 | * and "subs" for subscription.
53 | * @return RESULT_OK(0) on success, corresponding result code on failures
54 | */
55 | int isBillingSupported(int apiVersion, String packageName, String type);
56 |
57 | /**
58 | * Provides details of a list of SKUs
59 | * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
60 | * with a list JSON strings containing the productId, price, title and description.
61 | * This API can be called with a maximum of 20 SKUs.
62 | * @param apiVersion billing API version that the Third-party is using
63 | * @param packageName the package name of the calling app
64 | * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
65 | * @return Bundle containing the following key-value pairs
66 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
67 | * failure as listed above.
68 | * "DETAILS_LIST" with a StringArrayList containing purchase information
69 | * in JSON format similar to:
70 | * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
71 | * "title : "Example Title", "description" : "This is an example description" }'
72 | */
73 | Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
74 |
75 | /**
76 | * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
77 | * the type, a unique purchase token and an optional developer payload.
78 | * @param apiVersion billing API version that the app is using
79 | * @param packageName package name of the calling app
80 | * @param sku the SKU of the in-app item as published in the developer console
81 | * @param type the type of the in-app item ("inapp" for one-time purchases
82 | * and "subs" for subscription).
83 | * @param developerPayload optional argument to be sent back with the purchase information
84 | * @return Bundle containing the following key-value pairs
85 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
86 | * failure as listed above.
87 | * "BUY_INTENT" - PendingIntent to start the purchase flow
88 | *
89 | * The Pending intent should be launched with startIntentSenderForResult. When purchase flow
90 | * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
91 | * If the purchase is successful, the result data will contain the following key-value pairs
92 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
93 | * failure as listed above.
94 | * "INAPP_PURCHASE_DATA" - String in JSON format similar to
95 | * '{"orderId":"12999763169054705758.1371079406387615",
96 | * "packageName":"com.example.app",
97 | * "productId":"exampleSku",
98 | * "purchaseTime":1345678900000,
99 | * "purchaseToken" : "122333444455555",
100 | * "developerPayload":"example developer payload" }'
101 | * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
102 | * was signed with the private key of the developer
103 | * TODO: change this to app-specific keys.
104 | */
105 | Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
106 | String developerPayload);
107 |
108 | /**
109 | * Returns the current SKUs owned by the user of the type and package name specified along with
110 | * purchase information and a signature of the data to be validated.
111 | * This will return all SKUs that have been purchased in V3 and managed items purchased using
112 | * V1 and V2 that have not been consumed.
113 | * @param apiVersion billing API version that the app is using
114 | * @param packageName package name of the calling app
115 | * @param type the type of the in-app items being requested
116 | * ("inapp" for one-time purchases and "subs" for subscription).
117 | * @param continuationToken to be set as null for the first call, if the number of owned
118 | * skus are too many, a continuationToken is returned in the response bundle.
119 | * This method can be called again with the continuation token to get the next set of
120 | * owned skus.
121 | * @return Bundle containing the following key-value pairs
122 | * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
123 | * failure as listed above.
124 | * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
125 | * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
126 | * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
127 | * of the purchase information
128 | * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
129 | * next set of in-app purchases. Only set if the
130 | * user has more owned skus than the current list.
131 | */
132 | Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
133 |
134 | /**
135 | * Consume the last purchase of the given SKU. This will result in this item being removed
136 | * from all subsequent responses to getPurchases() and allow re-purchase of this item.
137 | * @param apiVersion billing API version that the app is using
138 | * @param packageName package name of the calling app
139 | * @param purchaseToken token in the purchase information JSON that identifies the purchase
140 | * to be consumed
141 | * @return 0 if consumption succeeded. Appropriate error values for failures.
142 | */
143 | int consumePurchase(int apiVersion, String packageName, String purchaseToken);
144 | }
145 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/src/main/java/de/j4velin/wifiAutoOff/Receiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Thomas Hoffmann
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.j4velin.wifiAutoOff;
18 |
19 | import android.annotation.SuppressLint;
20 | import android.app.AlarmManager;
21 | import android.app.PendingIntent;
22 | import android.content.BroadcastReceiver;
23 | import android.content.Context;
24 | import android.content.Intent;
25 | import android.content.SharedPreferences;
26 | import android.net.NetworkInfo;
27 | import android.net.wifi.SupplicantState;
28 | import android.net.wifi.WifiManager;
29 | import android.net.wifi.p2p.WifiP2pInfo;
30 | import android.net.wifi.p2p.WifiP2pManager;
31 | import android.os.Build;
32 | import android.os.PowerManager;
33 | import android.provider.Settings;
34 | import android.provider.Settings.SettingNotFoundException;
35 | import android.widget.Toast;
36 |
37 | import java.lang.reflect.Method;
38 |
39 | /**
40 | * Class for receiving various events and react on them.
41 | */
42 | public class Receiver extends BroadcastReceiver {
43 |
44 | public final static String LOCATION_ENTERED_ACTION = "LOCATION_ENTERED";
45 | // to prevent SecurityException: Not allowed to send ACTION_POWER_CONNECTED
46 | public final static String POWER_CONNECTED = "POWER_CONNECTED";
47 | public final static String EXTRA_LOCATION_NAME = "name";
48 | private static NetworkInfo.State previousState = null;
49 |
50 | private static final int TIMER_SCREEN_OFF = 1;
51 | private static final int TIMER_NO_NETWORK = 2;
52 | static final int TIMER_ON_AT = 3;
53 | static final int TIMER_OFF_AT = 4;
54 | static final int TIMER_ON_EVERY = 5;
55 |
56 | static final int TIMEOUT_NO_NETWORK = 5;
57 | static final int TIMEOUT_SCREEN_OFF = 10;
58 | static final int ON_EVERY_TIME_MIN = 120;
59 | static final String ON_AT_TIME = "8:00";
60 | static final String OFF_AT_TIME = "22:00";
61 |
62 | /**
63 | * Starts one of the timers to turn WiFi off
64 | *
65 | * @param context the context
66 | * @param id TIMER_SCREEN_OFF or TIMER_NO_NETWORK
67 | * @param time in min
68 | */
69 | private void startTimer(final Context context, int id, int time) {
70 | String action = (id == TIMER_SCREEN_OFF) ? "SCREEN_OFF_TIMER" : "NO_NETWORK_TIMER";
71 | Intent timerIntent =
72 | new Intent(context, Receiver.class).putExtra("timer", id).setAction(action);
73 | if (PendingIntent.getBroadcast(context, id, timerIntent, PendingIntent.FLAG_NO_CREATE) ==
74 | null) {
75 | Util.setTimer(context, AlarmManager.RTC_WAKEUP,
76 | System.currentTimeMillis() + 60000 * time, PendingIntent
77 | .getBroadcast(context, id, timerIntent,
78 | PendingIntent.FLAG_UPDATE_CURRENT));
79 | Log.insert(context, context.getString(
80 | id == TIMER_SCREEN_OFF ? R.string.event_screen_off_timer :
81 | R.string.event_no_network_timer, time), Log.Type.TIMER);
82 | } else if (BuildConfig.DEBUG) {
83 | Logger.log("timer for action " + action + " already set");
84 | }
85 | }
86 |
87 | /**
88 | * Stops the timer
89 | *
90 | * @param context the context
91 | * @param id TIMER_SCREEN_OFF or TIMER_NO_NETWORK
92 | * @return true, if timer was actually active
93 | */
94 | private boolean stopTimer(final Context context, int id) {
95 | Intent timerIntent = new Intent(context, Receiver.class).putExtra("timer", id)
96 | .setAction(id == TIMER_SCREEN_OFF ? "SCREEN_OFF_TIMER" : "NO_NETWORK_TIMER");
97 | PendingIntent pendingIntent =
98 | PendingIntent.getBroadcast(context, id, timerIntent, PendingIntent.FLAG_NO_CREATE);
99 | if (pendingIntent != null) {
100 | ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).cancel(pendingIntent);
101 | pendingIntent.cancel();
102 | Log.insert(context, (id == TIMER_SCREEN_OFF) ? R.string.event_screen_off_canceled :
103 | R.string.event_no_network_canceled, Log.Type.TIMER);
104 | }
105 | return pendingIntent != null;
106 | }
107 |
108 | /**
109 | * Get default shared preferences
110 | *
111 | * @param context the context
112 | * @return default SharedPreferences for given context
113 | */
114 | @SuppressLint("InlinedApi")
115 | private static SharedPreferences getSharedPreferences(final Context context) {
116 | String prefFileName = context.getPackageName() + "_preferences";
117 | return context.getSharedPreferences(prefFileName, Context.MODE_MULTI_PROCESS);
118 | }
119 |
120 | /**
121 | * Changes the WiFi state
122 | *
123 | * @param context the context
124 | * @param on true to turn WiFi on, false to turn it off
125 | */
126 | @SuppressWarnings("deprecation")
127 | private static void changeWiFi(final Context context, boolean on) {
128 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
129 | try {
130 | if (APILevel17Wrapper.isAirplaneModeOn(context)) {
131 | Log.insert(context, context.getString(R.string.unable_to_change_reason,
132 | context.getString(R.string.error_reason_airplane)), Log.Type.ERROR);
133 | if (BuildConfig.DEBUG)
134 | Logger.log("Unable to change WiFi state: In airplane mode on Android 8.1");
135 | }
136 | } catch (final SettingNotFoundException e) {
137 | if (BuildConfig.DEBUG) Logger.log(e);
138 | }
139 | }
140 | SharedPreferences prefs = getSharedPreferences(context);
141 | if (on && prefs.getBoolean("airplane", true)) {
142 | // check for airplane mode
143 | if (BuildConfig.DEBUG) Logger.log("checking for airplane mode");
144 | try {
145 | if (android.os.Build.VERSION.SDK_INT >=
146 | android.os.Build.VERSION_CODES.JELLY_BEAN_MR1 ?
147 | APILevel17Wrapper.isAirplaneModeOn(context) : Settings.System
148 | .getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON) ==
149 | 1) {
150 | Log.insert(context, R.string.event_airplane, Log.Type.AIRPLANE_MODE);
151 | return;
152 | }
153 | } catch (final SettingNotFoundException e) {
154 | // not airplane setting found? Handle like not in airplane mode
155 | // then
156 | if (BuildConfig.DEBUG) Logger.log(e);
157 | e.printStackTrace();
158 | }
159 | }
160 | if (on) {
161 | // check WiFi hotspot state (dont turn on WiFi if hotspot is active)
162 | WifiManager wifi = (WifiManager) context.getApplicationContext()
163 | .getSystemService(Context.WIFI_SERVICE);
164 | try {
165 | Method m = wifi.getClass().getDeclaredMethod("isWifiApEnabled");
166 | if ((boolean) m.invoke(wifi)) {
167 | Log.insert(context, R.string.hotspot_active, Log.Type.HOTSPOT);
168 | return;
169 | }
170 | } catch (Exception e) {
171 | if (BuildConfig.DEBUG) Logger.log(e);
172 | e.printStackTrace();
173 | }
174 | }
175 | try {
176 | WifiManager wm = ((WifiManager) context.getApplicationContext()
177 | .getSystemService(Context.WIFI_SERVICE));
178 | // do we need to change at all?
179 | if (wm.isWifiEnabled() != on) {
180 | Log.insert(context, on ? R.string.event_turn_on : R.string.event_turn_off,
181 | on ? Log.Type.WIFI_ON : Log.Type.WIFI_OFF);
182 | boolean success = wm.setWifiEnabled(on);
183 | if (!success) {
184 | Log.insert(context, R.string.unable_to_change, Log.Type.ERROR);
185 | if (BuildConfig.DEBUG) Logger.log("Unable to change WiFi state");
186 | }
187 | }
188 | } catch (Exception e) {
189 | Toast.makeText(context, "Can not change WiFi state: " + e.getClass().getName(),
190 | Toast.LENGTH_LONG).show();
191 | }
192 | }
193 |
194 | private static boolean isWiFiConnected(final Context context) {
195 | WifiManager wm = ((WifiManager) context.getApplicationContext()
196 | .getSystemService(Context.WIFI_SERVICE));
197 | return (wm != null && wm.getConnectionInfo() != null &&
198 | wm.getConnectionInfo().getSupplicantState() == SupplicantState.COMPLETED);
199 | }
200 |
201 | @SuppressLint("InlinedApi")
202 | @Override
203 | public void onReceive(final Context context, final Intent intent) {
204 | final String action = intent.getAction();
205 | if (BuildConfig.DEBUG) Logger.log("received: " + action);
206 | SharedPreferences prefs = getSharedPreferences(context);
207 | if (intent.hasExtra("timer")) {
208 | // one of the timers expired -> turn wifi off
209 | changeWiFi(context, false);
210 | stopTimer(context, intent.getIntExtra("timer", 0));
211 | } else if (intent.hasExtra("changeWiFi")) {
212 | // for "ON AT" or "OFF AT" options
213 | changeWiFi(context, intent.getBooleanExtra("changeWiFi", false));
214 | Start.createTimers(context);
215 | } else {
216 | switch (action) {
217 | case LOCATION_ENTERED_ACTION:
218 | if (!((WifiManager) context.getApplicationContext()
219 | .getSystemService(Context.WIFI_SERVICE)).isWifiEnabled()) {
220 | Log.insert(context, context.getString(R.string.event_location,
221 | intent.getStringExtra(EXTRA_LOCATION_NAME)),
222 | Log.Type.LOCATION_ENTERED);
223 | if (prefs.getBoolean("off_no_network", true)) {
224 | // start the timer before actually turning on the WiFi to set the NO_NETWORK
225 | // timer to at least 10 min. The set timer in the following WIFI_STATE_CHANGED_ACTION
226 | // will then have no effect, as the timer is already set
227 | startTimer(context, TIMER_NO_NETWORK, Math.max(10,
228 | prefs.getInt("no_network_timeout", TIMEOUT_NO_NETWORK)));
229 | }
230 | changeWiFi(context, true);
231 | } // else: WiFi is already enabled, do nothing
232 | break;
233 | case ScreenChangeDetector.SCREEN_OFF_ACTION:
234 | if (prefs.getBoolean("off_screen_off", true)) {
235 | if (!prefs.getBoolean("ignore_screen_off", false)) {
236 | // screen went off -> start TIMER_SCREEN_OFF
237 | Log.insert(context, R.string.event_screen_off, Log.Type.SCREEN_OFF);
238 | startTimer(context, TIMER_SCREEN_OFF,
239 | prefs.getInt("screen_off_timeout", TIMEOUT_SCREEN_OFF));
240 | } else {
241 | Log.insert(context, R.string.event_display_off_ignored_ac,
242 | Log.Type.SCREEN_OFF);
243 | }
244 | }
245 | break;
246 | case UnlockReceiver.USER_PRESENT_ACTION:
247 | case Intent.ACTION_USER_PRESENT:
248 | case ScreenChangeDetector.SCREEN_ON_ACTION:
249 | if (action.equals(ScreenChangeDetector.SCREEN_ON_ACTION)) {
250 | Log.insert(context, R.string.event_screen_on, Log.Type.SCREEN_ON);
251 | } else {
252 | Log.insert(context, R.string.event_unlocked, Log.Type.UNLOCKED);
253 | }
254 | // user unlocked the device -> stop TIMER_SCREEN_OFF, might turn on
255 | // WiFi
256 | stopTimer(context, TIMER_SCREEN_OFF);
257 | if (prefs.getBoolean("on_unlock", true)) {
258 | boolean noNetTimer = stopTimer(context, TIMER_NO_NETWORK);
259 | if (((WifiManager) context.getApplicationContext()
260 | .getSystemService(Context.WIFI_SERVICE)).isWifiEnabled()) {
261 | if (noNetTimer && prefs.getBoolean("off_no_network", true)) {
262 | // if WiFi is already turned on, just restart the NO_NETWORK timer
263 | startTimer(context, TIMER_NO_NETWORK,
264 | prefs.getInt("no_network_timeout", TIMEOUT_NO_NETWORK));
265 | }
266 | } else {
267 | changeWiFi(context, true);
268 | }
269 | }
270 | break;
271 | case WifiManager.NETWORK_STATE_CHANGED_ACTION:
272 | final NetworkInfo nwi =
273 | intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
274 | if (nwi == null) return;
275 | if (nwi.isConnected()) {
276 | if (!nwi.getState().equals(previousState)) {
277 | Log.insert(context, R.string.event_connected, Log.Type.WIFI_CONNECTED);
278 | }
279 | stopTimer(context, TIMER_NO_NETWORK);
280 | } else if (nwi.getState().equals(NetworkInfo.State.DISCONNECTED)) {
281 | if (!nwi.getState().equals(previousState)) {
282 | Log.insert(context, R.string.event_disconnected,
283 | Log.Type.WIFI_DISCONNECTED);
284 | }
285 | if (prefs.getBoolean("off_no_network", true)) {
286 | startTimer(context, TIMER_NO_NETWORK,
287 | prefs.getInt("no_network_timeout", TIMEOUT_NO_NETWORK));
288 | }
289 | }
290 | previousState = nwi.getState();
291 | break;
292 | case WifiManager.WIFI_STATE_CHANGED_ACTION:
293 | if (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
294 | WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED) {
295 | Log.insert(context, R.string.event_enabled, Log.Type.WIFI_ON);
296 | if (isWiFiConnected(context)) {
297 | if (BuildConfig.DEBUG) {
298 | Logger.log("Wifi already connected");
299 | }
300 | } else {
301 | if (prefs.getBoolean("off_no_network", true)) {
302 | startTimer(context, TIMER_NO_NETWORK,
303 | prefs.getInt("no_network_timeout", TIMEOUT_NO_NETWORK));
304 | }
305 | }
306 | if (prefs.getBoolean("off_screen_off", true) &&
307 | ((Build.VERSION.SDK_INT < 20 &&
308 | !((PowerManager) context.getApplicationContext()
309 | .getSystemService(Context.POWER_SERVICE))
310 | .isScreenOn()) || (Build.VERSION.SDK_INT >= 20 &&
311 | !APILevel20Wrapper.isScreenOn(context)))) {
312 | startTimer(context, TIMER_SCREEN_OFF,
313 | prefs.getInt("screen_off_timeout", TIMEOUT_SCREEN_OFF));
314 | }
315 | } else if (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
316 | WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_DISABLED) {
317 | Log.insert(context, R.string.event_disabled, Log.Type.WIFI_OFF);
318 | stopTimer(context, TIMER_SCREEN_OFF);
319 | stopTimer(context, TIMER_NO_NETWORK);
320 | }
321 | break;
322 | case WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION:
323 | // wifi direct connection changed
324 | NetworkInfo nwi2 = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
325 | WifiP2pInfo winfo =
326 | intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
327 | if (BuildConfig.DEBUG) Logger.log("new P2P network state: " + nwi2.getState());
328 | if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= 14)
329 | Logger.log("P2P group formed: " + APILevel14Wrapper.groupFormed(winfo));
330 | if (nwi2.isConnected() ||
331 | (Build.VERSION.SDK_INT >= 14 && APILevel14Wrapper.groupFormed(winfo))) {
332 | if (!nwi2.getState().equals(previousState)) {
333 | Log.insert(context, R.string.event_connected, Log.Type.WIFI_CONNECTED);
334 | }
335 | stopTimer(context, TIMER_NO_NETWORK);
336 | } else if (nwi2.getState().equals(NetworkInfo.State.DISCONNECTED) &&
337 | !isWiFiConnected(context)) {
338 | if (!nwi2.getState().equals(previousState)) {
339 | Log.insert(context, R.string.event_disconnected,
340 | Log.Type.WIFI_DISCONNECTED);
341 | }
342 | if (prefs.getBoolean("off_no_network", true)) {
343 | startTimer(context, TIMER_NO_NETWORK,
344 | prefs.getInt("no_network_timeout", TIMEOUT_NO_NETWORK));
345 | }
346 | }
347 | previousState = nwi2.getState();
348 | break;
349 | case POWER_CONNECTED:
350 | case Intent.ACTION_POWER_CONNECTED:
351 | // connected to external power supply
352 | if (prefs.getBoolean("power_connected", false)) {
353 | Log.insert(context, R.string.event_ac, Log.Type.AC_CONNECTED);
354 | changeWiFi(context, true);
355 | if (prefs.getBoolean("off_screen_off",
356 | true)) { // ignore display off events while charging
357 | stopTimer(context, TIMER_SCREEN_OFF);
358 | prefs.edit().putBoolean("ignore_screen_off", true).apply();
359 | if (BuildConfig.DEBUG) Logger.log("ignore screen off events");
360 | }
361 | }
362 | break;
363 | case Intent.ACTION_POWER_DISCONNECTED:
364 | // disconnected from external power supply
365 | if (prefs.getBoolean("power_connected", false)) {
366 | Log.insert(context, R.string.event_ac_disconnected,
367 | Log.Type.AC_DISCONNECTED);
368 | // do we need to start the screen off timer?
369 | if (prefs.getBoolean("off_screen_off", true)) {
370 | prefs.edit().putBoolean("ignore_screen_off", false).apply();
371 | if (BuildConfig.DEBUG)
372 | Logger.log("dont ignore screen off event any more");
373 | if ((Build.VERSION.SDK_INT < 20 &&
374 | !((PowerManager) context.getApplicationContext()
375 | .getSystemService(Context.POWER_SERVICE))
376 | .isScreenOn()) || (Build.VERSION.SDK_INT >= 20 &&
377 | !APILevel20Wrapper.isScreenOn(context))) {
378 | if (BuildConfig.DEBUG) Logger.log("screen is off -> start timer");
379 | startTimer(context, TIMER_SCREEN_OFF,
380 | prefs.getInt("screen_off_timeout", TIMEOUT_SCREEN_OFF));
381 | }
382 | }
383 | }
384 | break;
385 | }
386 | }
387 | }
388 | }
389 |
--------------------------------------------------------------------------------