mirror of
https://github.com/adolfintel/OpenPods.git
synced 2026-09-15 07:16:10 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
952c11ba21 | ||
|
|
9bea2c5e6e | ||
|
|
88c344d4ff | ||
|
|
6f3b43e84c | ||
|
|
8a41df7c51 | ||
|
|
35a9d96398 | ||
|
|
298ce85990 | ||
|
|
18158d70b2 | ||
|
|
0f74a0607e | ||
|
|
3bd3ec74e7 | ||
|
|
5c39fb37f7 |
@@ -5,9 +5,9 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.dosse.airpods"
|
applicationId "com.dosse.airpods"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 28
|
targetSdkVersion 23
|
||||||
versionCode 7
|
versionCode 9
|
||||||
versionName '0.7'
|
versionName '0.9'
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -18,6 +18,9 @@ android {
|
|||||||
}
|
}
|
||||||
productFlavors {
|
productFlavors {
|
||||||
}
|
}
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.bluetooth_le"
|
android:name="android.hardware.bluetooth_le"
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}catch(Throwable t){}
|
}catch(Throwable t){}
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) ok=false;
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) ok=false;
|
||||||
if(ok){
|
if(ok){
|
||||||
startService(new Intent(getApplicationContext(),PodsService.class));
|
Starter.startPodsService(getApplicationContext());
|
||||||
}else{
|
}else{
|
||||||
Intent i=new Intent(this,IntroActivity.class);
|
Intent i=new Intent(this,IntroActivity.class);
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ import android.bluetooth.BluetoothManager;
|
|||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.bluetooth.le.BluetoothLeScanner;
|
import android.bluetooth.le.BluetoothLeScanner;
|
||||||
import android.bluetooth.le.ScanCallback;
|
import android.bluetooth.le.ScanCallback;
|
||||||
|
import android.bluetooth.le.ScanFilter;
|
||||||
|
import android.bluetooth.le.ScanFilter.Builder;
|
||||||
import android.bluetooth.le.ScanResult;
|
import android.bluetooth.le.ScanResult;
|
||||||
|
import android.bluetooth.le.ScanSettings;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -26,8 +29,9 @@ import android.support.v4.app.NotificationCompat;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RemoteViews;
|
import android.widget.RemoteViews;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the class that does most of the work. It has 3 functions:
|
* This is the class that does most of the work. It has 3 functions:
|
||||||
@@ -78,7 +82,20 @@ public class PodsService extends Service {
|
|||||||
btScanner = btAdapter.getBluetoothLeScanner();
|
btScanner = btAdapter.getBluetoothLeScanner();
|
||||||
if (btAdapter == null) throw new Exception("No BT");
|
if (btAdapter == null) throw new Exception("No BT");
|
||||||
if (!btAdapter.isEnabled()) throw new Exception("BT Off");
|
if (!btAdapter.isEnabled()) throw new Exception("BT Off");
|
||||||
btScanner.startScan(new ScanCallback() {
|
|
||||||
|
List<ScanFilter> filters = getScanFilters();
|
||||||
|
ScanSettings settings = new ScanSettings.Builder().setScanMode(2).setReportDelay(2).build();
|
||||||
|
|
||||||
|
btScanner.startScan(
|
||||||
|
filters,
|
||||||
|
settings,
|
||||||
|
new ScanCallback() {
|
||||||
|
@Override
|
||||||
|
public void onBatchScanResults(List<ScanResult> scanResults) {
|
||||||
|
for (ScanResult result : scanResults) onScanResult(-1, result);
|
||||||
|
super.onBatchScanResults(scanResults);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onScanResult(int callbackType, ScanResult result) {
|
public void onScanResult(int callbackType, ScanResult result) {
|
||||||
try {
|
try {
|
||||||
@@ -128,6 +145,21 @@ public class PodsService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ScanFilter> getScanFilters() {
|
||||||
|
byte[] manufacturerData = new byte[27];
|
||||||
|
byte[] manufacturerDataMask = new byte[27];
|
||||||
|
|
||||||
|
manufacturerData[0] = 7;
|
||||||
|
manufacturerData[1] = 25;
|
||||||
|
|
||||||
|
manufacturerDataMask[0] = -1;
|
||||||
|
manufacturerDataMask[1] = -1;
|
||||||
|
|
||||||
|
Builder builder = new Builder();
|
||||||
|
builder.setManufacturerData(76, manufacturerData, manufacturerDataMask);
|
||||||
|
return Collections.singletonList(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
private void stopAirPodsScanner(){
|
private void stopAirPodsScanner(){
|
||||||
try{
|
try{
|
||||||
if(btScanner!=null){
|
if(btScanner!=null){
|
||||||
@@ -170,17 +202,20 @@ public class PodsService extends Service {
|
|||||||
private static boolean maybeConnected =false;
|
private static boolean maybeConnected =false;
|
||||||
private class NotificationThread extends Thread{
|
private class NotificationThread extends Thread{
|
||||||
private boolean isLocationEnabled(){
|
private boolean isLocationEnabled(){
|
||||||
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P){
|
||||||
return service!=null&&service.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
|
LocationManager service = (LocationManager) getSystemService(getApplicationContext().LOCATION_SERVICE);
|
||||||
|
return service!=null&&service.isLocationEnabled();
|
||||||
|
}else{
|
||||||
|
try {
|
||||||
|
return Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE) != Settings.Secure.LOCATION_MODE_OFF;
|
||||||
|
}catch(Throwable t){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void run(){
|
private NotificationManager mNotifyManager;
|
||||||
boolean notificationShowing=false;
|
public NotificationThread(){
|
||||||
RemoteViews notificationBig=new RemoteViews(getPackageName(),R.layout.status_big);
|
mNotifyManager=(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
RemoteViews notificationSmall=new RemoteViews(getPackageName(),R.layout.status_small);
|
|
||||||
RemoteViews locationDisabledBig=new RemoteViews(getPackageName(),R.layout.location_disabled_big);
|
|
||||||
RemoteViews locationDisabledSmall=new RemoteViews(getPackageName(),R.layout.location_disabled_small);
|
|
||||||
NotificationManager mNotifyManager=(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
NotificationCompat.Builder mBuilder=new NotificationCompat.Builder(PodsService.this,TAG);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //on oreo and newer, create a notification channel
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //on oreo and newer, create a notification channel
|
||||||
NotificationChannel channel = new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_LOW);
|
NotificationChannel channel = new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_LOW);
|
||||||
channel.enableVibration(false);
|
channel.enableVibration(false);
|
||||||
@@ -189,6 +224,14 @@ public class PodsService extends Service {
|
|||||||
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
|
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
|
||||||
mNotifyManager.createNotificationChannel(channel);
|
mNotifyManager.createNotificationChannel(channel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
public void run(){
|
||||||
|
boolean notificationShowing=false;
|
||||||
|
RemoteViews notificationBig=new RemoteViews(getPackageName(),R.layout.status_big);
|
||||||
|
RemoteViews notificationSmall=new RemoteViews(getPackageName(),R.layout.status_small);
|
||||||
|
RemoteViews locationDisabledBig=new RemoteViews(getPackageName(),R.layout.location_disabled_big);
|
||||||
|
RemoteViews locationDisabledSmall=new RemoteViews(getPackageName(),R.layout.location_disabled_small);
|
||||||
|
NotificationCompat.Builder mBuilder=new NotificationCompat.Builder(PodsService.this,TAG);
|
||||||
mBuilder.setShowWhen(false);
|
mBuilder.setShowWhen(false);
|
||||||
mBuilder.setOngoing(true);
|
mBuilder.setOngoing(true);
|
||||||
mBuilder.setSmallIcon(R.mipmap.notification_icon);
|
mBuilder.setSmallIcon(R.mipmap.notification_icon);
|
||||||
@@ -290,6 +333,9 @@ public class PodsService extends Service {
|
|||||||
intentFilter.addAction("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED");
|
intentFilter.addAction("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED");
|
||||||
intentFilter.addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED");
|
intentFilter.addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED");
|
||||||
intentFilter.addCategory("android.bluetooth.headset.intent.category.companyid.76");
|
intentFilter.addCategory("android.bluetooth.headset.intent.category.companyid.76");
|
||||||
|
try{
|
||||||
|
unregisterReceiver(btReceiver);
|
||||||
|
}catch (Throwable t){}
|
||||||
btReceiver=new BroadcastReceiver() {
|
btReceiver=new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
@@ -321,9 +367,6 @@ public class PodsService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try{
|
|
||||||
unregisterReceiver(btReceiver);
|
|
||||||
}catch (Throwable t){}
|
|
||||||
try{
|
try{
|
||||||
registerReceiver(btReceiver,intentFilter);
|
registerReceiver(btReceiver,intentFilter);
|
||||||
}catch(Throwable t){}
|
}catch(Throwable t){}
|
||||||
@@ -387,5 +430,4 @@ public class PodsService extends Service {
|
|||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.dosse.airpods;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,6 +12,10 @@ import android.util.Log;
|
|||||||
public class Starter extends BroadcastReceiver {
|
public class Starter extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
context.startService(new Intent(context,PodsService.class));
|
startPodsService(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final void startPodsService(Context context){
|
||||||
|
context.startService(new Intent(context, PodsService.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
<string name="hideClicked">Das Icon wird bald verschwinden</string>
|
<string name="hideClicked">Das Icon wird bald verschwinden</string>
|
||||||
<string name="noBtText">Es sieht so aus als hätte dieses Gerät kein Bluetooth LE</string>
|
<string name="noBtText">Es sieht so aus als hätte dieses Gerät kein Bluetooth LE</string>
|
||||||
<string name="locationDisabledText">Du musst Standortinformationen aktivieren, damit OpenPods den Status deiner AirPods auslesen kann</string>
|
<string name="locationDisabledText">Du musst Standortinformationen aktivieren, damit OpenPods den Status deiner AirPods auslesen kann</string>
|
||||||
<string name="supportedDevices">Unterstützte Geräte:\n• Apple AirPods 1st gen</string>
|
<string name="supportedDevices">Unterstützte Geräte:\n• Apple AirPods 1st gen\n• Apple AirPods 2nd gen</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -8,6 +8,5 @@
|
|||||||
<string name="hideClicked">El ícono desaparecerá pronto</string>
|
<string name="hideClicked">El ícono desaparecerá pronto</string>
|
||||||
<string name="noBtText">Parece que este dispositivo no tiene Bluetooth LE</string>
|
<string name="noBtText">Parece que este dispositivo no tiene Bluetooth LE</string>
|
||||||
<string name="locationDisabledText">Necesitas encender Localización para permitir que OpenPods lea el estado</string>
|
<string name="locationDisabledText">Necesitas encender Localización para permitir que OpenPods lea el estado</string>
|
||||||
<string name="supportedDevices">Dispositivos compatibles:\n
|
<string name="supportedDevices">Dispositivos compatibles:\n• Apple AirPods 1st gen\n• Apple AirPods 2nd gen</string>
|
||||||
• Apple AirPods 1st gen</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
<string name="hideClicked">L\'icona sarà rimossa presto</string>
|
<string name="hideClicked">L\'icona sarà rimossa presto</string>
|
||||||
<string name="noBtText">Questo dispositivo non supporta Bluetooth LE</string>
|
<string name="noBtText">Questo dispositivo non supporta Bluetooth LE</string>
|
||||||
<string name="locationDisabledText">Attiva la posizione per permttere a OpenPods di leggere lo stato</string>
|
<string name="locationDisabledText">Attiva la posizione per permttere a OpenPods di leggere lo stato</string>
|
||||||
<string name="supportedDevices">Dispositivi supportati:\n• Apple AirPods 1st gen</string>
|
<string name="supportedDevices">Dispositivi supportati:\n• Apple AirPods 1st gen\n• Apple AirPods 2nd gen</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -9,5 +9,5 @@
|
|||||||
<string name="hideClicked">桌面图标很快就会隐藏掉</string>
|
<string name="hideClicked">桌面图标很快就会隐藏掉</string>
|
||||||
<string name="noBtText">看起来您的设备并不支持蓝牙</string>
|
<string name="noBtText">看起来您的设备并不支持蓝牙</string>
|
||||||
<string name="locationDisabledText">您需要开启定位来让 OpenPods 读取状态</string>
|
<string name="locationDisabledText">您需要开启定位来让 OpenPods 读取状态</string>
|
||||||
<string name="supportedDevices">支持的设备:\n• Apple AirPods 一代</string>
|
<string name="supportedDevices">支持的设备:\n• Apple AirPods 1st gen\n• Apple AirPods 2nd gen</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
<string name="hideClicked">The icon will disappear soon</string>
|
<string name="hideClicked">The icon will disappear soon</string>
|
||||||
<string name="noBtText">It looks like this device doesn\'t have Bluetooth LE</string>
|
<string name="noBtText">It looks like this device doesn\'t have Bluetooth LE</string>
|
||||||
<string name="locationDisabledText">You need to turn on Location to allow OpenPods to read the status</string>
|
<string name="locationDisabledText">You need to turn on Location to allow OpenPods to read the status</string>
|
||||||
<string name="supportedDevices">Supported devices:\n• Apple AirPods 1st gen</string>
|
<string name="supportedDevices">Supported devices:\n• Apple AirPods 1st gen\n• Apple AirPods 2nd gen</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ buildscript {
|
|||||||
|
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
The Free and Open Source app for monitoring your AirPods on Android
|
The Free and Open Source app for monitoring your AirPods on Android
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
The project is currently in Alpha.
|
|
||||||
|
|
||||||
[Download from F-Droid](https://f-droid.org/repository/browse/?fdid=com.dosse.airpods)
|
[Download from F-Droid](https://f-droid.org/repository/browse/?fdid=com.dosse.airpods)
|
||||||
[Download APK](https://downloads.fdossena.com/geth.php?r=openpods-apk)
|
[Download APK](https://downloads.fdossena.com/geth.php?r=openpods-apk)
|
||||||
|
|
||||||
@@ -16,11 +14,12 @@ The project is currently in Alpha.
|
|||||||
|
|
||||||
## Supported devices
|
## Supported devices
|
||||||
* Apple AirPods 1st gen
|
* Apple AirPods 1st gen
|
||||||
|
* Apple AirPods 2nd gen
|
||||||
|
|
||||||
## Project status
|
## DO NOT REUPLOAD TO GOOGLE PLAY
|
||||||
Right now, this project should be considered in alpha state. It was not extensively tested, it may not be stable or work at all on your device.
|
**This app violates Google Play policies and is designed to break if you try to fix that unless you really know what you're doing.** You have been warned. I do NOT want this app to be on Google Play.
|
||||||
|
|
||||||
**Feedback is appreciated**
|
I had to do this because several people were redistributing modified proprietary versions of this app on Google Play in violation of the GNU GPLv3 license.
|
||||||
|
|
||||||
## Donate
|
## Donate
|
||||||
[Donate with PayPal](https://www.paypal.me/sineisochronic)
|
[Donate with PayPal](https://www.paypal.me/sineisochronic)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 63 KiB |
Reference in New Issue
Block a user