BluetoothTethering / Verbindung Handy zum Auto

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • BluetoothTethering / Verbindung Handy zum Auto

    Hallo zusammen
    ich steh wieder mal vor einem Problem.
    Ich wollte mir eine einfache App basteln die bei meinem Handy (Version 6.0) die Einstellungen/Tethering/Bluetooth-Tethering aktiviert/deaktiviert.

    Ich habe mir dazu im Internet den Code runter geladen.
    Allderings verstehen tu ich ihn nicht so richtig.
    Mein grösseres Problem ist aber, daß er
    nach dem Start immer bei Zeile 44 (PTPanServuceListerner > proxy.getClass......)
    abbricht bzw. catch ... aufruft.



    Kann mir da jemand helfen ?
    Gruß herrm_no

    Quellcode

    1. proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, new Object[]{Boolean.valueOf(true)});


    Quellcode

    1. catch (IllegalArgumentException e)
    BluetootTethering

    Java-Quellcode

    1. package com.herrm_no.bluetoothtethering;
    2. import android.annotation.SuppressLint;
    3. import android.bluetooth.BluetoothAdapter;
    4. import android.bluetooth.BluetoothManager;
    5. import android.bluetooth.BluetoothProfile;
    6. import android.content.Context;
    7. import android.os.Bundle;
    8. import android.support.v7.app.AppCompatActivity;
    9. import android.view.Menu;
    10. import android.view.MenuItem;
    11. import android.widget.CompoundButton;
    12. import android.widget.Switch;
    13. import java.lang.reflect.Constructor;
    14. import java.lang.reflect.Method;
    15. public class BluetoothTethering extends AppCompatActivity {
    16. BluetoothAdapter mBluetoothAdapter = null;
    17. Class<?> classBluetoothPan = null;
    18. Constructor<?> BTPanCtor = null;
    19. Object BTSrvInstance = null;
    20. Class<?> noparams[] = {};
    21. Method mIsBTTetheringOn;
    22. public static Switch toggle ;
    23. @Override
    24. protected void onCreate(Bundle savedInstanceState) {
    25. super.onCreate(savedInstanceState);
    26. setContentView(R.layout.activity_bluetooth_tethering);
    27. toggle = findViewById(R.id.wifi_switch);
    28. toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    29. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    30. try {
    31. mBluetoothAdapter = getBTAdapter();
    32. mBluetoothAdapter.enable();
    33. Thread.sleep(100);
    34. toggleTethering();
    35. } catch (InterruptedException e) {
    36. e.printStackTrace();
    37. }
    38. }
    39. });
    40. }
    41. @Override
    42. public boolean onCreateOptionsMenu(Menu menu) {
    43. // Inflate the menu; this adds items to the action bar if it is present.
    44. getMenuInflater().inflate(R.menu.menu_bluetooth_tethering, menu);
    45. return true;
    46. }
    47. @Override
    48. public boolean onOptionsItemSelected(MenuItem item) {
    49. // Handle action bar item clicks here. The action bar will
    50. // automatically handle clicks on the Home/Up button, so long
    51. // as you specify a parent activity in AndroidManifest.xml.
    52. int id = item.getItemId();
    53. //noinspection SimplifiableIfStatement
    54. if (id == R.id.action_settings) {
    55. return true;
    56. }
    57. return super.onOptionsItemSelected(item);
    58. }
    59. public void toggleTethering() {
    60. Context MyContext = getApplicationContext();
    61. mBluetoothAdapter = getBTAdapter();
    62. String sClassName = "android.bluetooth.BluetoothPan";
    63. try {
    64. classBluetoothPan = Class.forName(sClassName);
    65. mIsBTTetheringOn = classBluetoothPan.getDeclaredMethod("isTetheringOn", noparams);
    66. BTPanCtor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class);
    67. BTPanCtor.setAccessible(true);
    68. BTSrvInstance = BTPanCtor.newInstance(MyContext, new BTPanServiceListener(MyContext));
    69. Thread.sleep(250);
    70. } catch (ClassNotFoundException e) {
    71. e.printStackTrace();
    72. } catch (Exception e) {
    73. e.printStackTrace();
    74. }
    75. }
    76. @SuppressLint("NewApi")
    77. private BluetoothAdapter getBTAdapter() {
    78. if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)
    79. return BluetoothAdapter.getDefaultAdapter();
    80. else {
    81. BluetoothManager bm = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
    82. return bm.getAdapter();
    83. }
    84. }
    85. public static void changeToggleState(boolean state) {
    86. try{
    87. if(state){
    88. toggle.setChecked(BTPanServiceListener.state);
    89. }else {
    90. toggle.setChecked(BTPanServiceListener.state);
    91. }
    92. }catch (Exception e){
    93. e.printStackTrace();
    94. }
    95. }
    96. }
    Alles anzeigen


    BTPanServiceListener

    Java-Quellcode

    1. package com.herrm_no.bluetoothtethering;
    2. import android.bluetooth.BluetoothAdapter;
    3. import android.bluetooth.BluetoothDevice;
    4. import android.bluetooth.BluetoothProfile;
    5. import android.content.Context;
    6. import android.util.Log;
    7. import android.widget.Toast;
    8. import java.lang.reflect.Constructor;
    9. import java.lang.reflect.InvocationTargetException;
    10. public class BTPanServiceListener implements BluetoothProfile.ServiceListener {
    11. private final Context context;
    12. public static boolean state = false;
    13. BluetoothAdapter mBluetoothAdapter = null;
    14. Class<?> classBluetoothPan = null;
    15. //public Boolean BOL = true;
    16. public BTPanServiceListener(final Context context) {
    17. this.context = context;
    18. }
    19. @Override
    20. public void onServiceConnected(final int profile,
    21. final BluetoothProfile proxy) {
    22. //Some code must be here or the compiler will optimize away this callback.
    23. Log.i("MyApp", "BTPan proxy connected");
    24. try {
    25. //boolean nowVal = ((Boolean) proxy.getClass().getMethod("isTetheringOn", new Class[0]).invoke(proxy, new Object[0])).booleanValue();
    26. boolean nowVal = ((Boolean) proxy.getClass().getMethod("isTetheringOn", new Class[0]).invoke(proxy));
    27. if (nowVal) {
    28. proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, new Object[]{Boolean.valueOf(false)});
    29. // proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, true); //enable);
    30. Toast.makeText(context, "Turning bluetooth tethering off", Toast.LENGTH_SHORT).show();
    31. state = false;
    32. } else {
    33. proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, new Object[]{Boolean.valueOf(true)});
    34. // proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, false); //enable);
    35. Toast.makeText(context, "Turning bluetooth tethering on", Toast.LENGTH_SHORT).show();
    36. state = true;
    37. }
    38. BluetoothTethering.changeToggleState(state);
    39. } catch (IllegalAccessException e) {
    40. // TODO Auto-generated catch block
    41. e.printStackTrace();
    42. } catch (IllegalArgumentException e) {
    43. // TODO Auto-generated catch block
    44. e.printStackTrace();
    45. } catch (InvocationTargetException e) {
    46. // TODO Auto-generated catch block
    47. e.printStackTrace();
    48. } catch (NoSuchMethodException e) {
    49. // TODO Auto-generated catch block
    50. e.printStackTrace();
    51. }
    52. }
    53. @Override
    54. public void onServiceDisconnected(final int profile) {
    55. }
    56. }
    Alles anzeigen
    Manifest

    XML-Quellcode

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:tools="http://schemas.android.com/tools"
    4. package="com.herrm_no.bluetoothtethering">
    5. <uses-permission android:name="android.permission.BLUETOOTH" />
    6. <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    7. <application
    8. android:allowBackup="true"
    9. android:icon="@mipmap/ic_launcher"
    10. android:label="@string/app_name"
    11. android:roundIcon="@mipmap/ic_launcher_round"
    12. android:supportsRtl="true"
    13. android:theme="@style/AppTheme"
    14. tools:ignore="GoogleAppIndexingWarning">
    15. <activity android:name=".BluetoothTethering">
    16. <intent-filter>
    17. <action android:name="android.intent.action.MAIN" />
    18. <category android:name="android.intent.category.LAUNCHER" />
    19. </intent-filter>
    20. </activity>
    21. </application>
    22. </manifest>
    Alles anzeigen
  • Hi herrm_no,
    ich habe mir das mal angeschaut und was gefunden, was ziemlich gut funktioniert. (getestet auf S8 mit Android 9)
    Leider gibt es keine offizielle API, sondern muss sich die Methoden selber besorgen. Daher kann ich dir nicht sagen für welche Android-Version das ganze funktioniert.
    Wichtig: Bluetooth muss an sein! Das kannst du ja selber noch prüfen, habe ich jetzt bei dem Beispiel außen vorgelassen.

    Android-Manifest:

    XML-Quellcode

    1. <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
    2. <uses-permission android:name="android.permission.BLUETOOTH" />
    3. <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />


    MainActivity:

    Java-Quellcode

    1. public class MainActivity extends AppCompatActivity {
    2. Button toggleBTButton;
    3. Object instance = null;
    4. Method setTetheringOn = null;
    5. Method isTetheringOn = null;
    6. Object mutex = new Object();
    7. @Override
    8. protected void onCreate(Bundle savedInstanceState) {
    9. super.onCreate(savedInstanceState);
    10. setContentView(R.layout.activity_main);
    11. toggleBTButton = findViewById(R.id.toggleBTButton);
    12. // Setup Methods
    13. try {
    14. Class<?> classBluetoothPan = Class.forName("android.bluetooth.BluetoothPan");
    15. Constructor<?> ctor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class);
    16. ctor.setAccessible(true);
    17. Class[] paramSet = new Class[1];
    18. paramSet[0] = boolean.class;
    19. synchronized (mutex) {
    20. setTetheringOn = classBluetoothPan.getDeclaredMethod("setBluetoothTethering", paramSet);
    21. isTetheringOn = classBluetoothPan.getDeclaredMethod("isTetheringOn", null);
    22. instance = ctor.newInstance(getApplicationContext(), new BTPanServiceListener());
    23. }
    24. }
    25. catch (ClassNotFoundException ex) {
    26. Log.i("MainActivity", "Android-Version not supported!");
    27. ex.printStackTrace();
    28. }
    29. catch (Exception ex) {
    30. ex.printStackTrace();
    31. }
    32. toggleBTButton.setOnClickListener(new View.OnClickListener() {
    33. @Override
    34. public void onClick(View v) {
    35. try {
    36. //Check if BT-Tethering is on
    37. if((Boolean)isTetheringOn.invoke(instance, null)) {
    38. Log.i("MainActivity", "Turn Tethering off");
    39. setTetheringOn.invoke(instance, false);
    40. toggleBTButton.setText("Turn on");
    41. }
    42. else {
    43. Log.i("MainActivity", "Turn Tethering on");
    44. setTetheringOn.invoke(instance, true);
    45. toggleBTButton.setText("Turn off");
    46. }
    47. }
    48. catch (Exception ex){
    49. ex.printStackTrace();
    50. }
    51. }
    52. });
    53. }
    54. public class BTPanServiceListener implements BluetoothProfile.ServiceListener {
    55. @Override
    56. public void onServiceConnected(final int profile, final BluetoothProfile proxy) {
    57. try {
    58. //Set Button Text
    59. if ((Boolean) isTetheringOn.invoke(instance, null)) {
    60. toggleBTButton.setText("Turn off");
    61. } else {
    62. toggleBTButton.setText("Turn on");
    63. }
    64. }
    65. catch (Exception ex){ex.printStackTrace();}
    66. }
    67. @Override
    68. public void onServiceDisconnected(final int profile) { }
    69. }
    70. }
    Alles anzeigen
    Layout:

    XML-Quellcode

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:app="http://schemas.android.com/apk/res-auto"
    4. xmlns:tools="http://schemas.android.com/tools"
    5. android:layout_width="match_parent"
    6. android:layout_height="match_parent"
    7. tools:context=".MainActivity">
    8. <Button
    9. android:id="@+id/toggleBTButton"
    10. android:layout_width="wrap_content"
    11. android:layout_height="wrap_content"
    12. android:layout_marginStart="8dp"
    13. android:layout_marginTop="8dp"
    14. android:layout_marginEnd="8dp"
    15. android:text="Turn On"
    16. app:layout_constraintEnd_toEndOf="parent"
    17. app:layout_constraintStart_toStartOf="parent"
    18. app:layout_constraintTop_toTopOf="parent" />
    19. </androidx.constraintlayout.widget.ConstraintLayout>
    Alles anzeigen
  • Hallo Xcreen
    vielen vielen Dank für den Code
    So oder zumindest so ähnlich hatte ich es auch schon probiert.
    Funktioniert leider wieder nicht bei mir.
    Bluetooth ist an.
    Ich will diesen Scheiß Fehler finden.
    Kannst du mir da bitte noch ein paar Infos geben
    a)

    Quellcode

    1. Class<?> classBluetoothPan = Class.forName("android.bluetooth.BluetoothPan");

    Kannst du mir sagen wie das funktioniert. Die KLasse "android.bluetooth.BluetootPan" gibt es doch nicht. Oder hast du die noch irgendwo eingebunden.
    Ich versteh einfach nicht diese Code Zeile.
    2) Ich debugge die App und bekomme hier ein paar Infos. Kannst du mal vergleichen ob das Identisch zu deinem ist. Will sehen wo es eigentlich wirklich hängt.
    Beim letzten Bild /Code

    Quellcode

    1. //Set Button Text
    2. if ((Boolean) isTetheringOn.invoke(instance, null)) {
    3. toggleBTButton.setText("Turn off");
    4. } else {
    5. toggleBTButton.setText("Turn on");
    6. }
    7. }
    8. catch (Exception ex){ex.printStackTrace();}
    9. }
    Beim debuggen geht er immer auf die Else Abfrage ("Turn on" und danach auf catch (Exception)
    Ich hoffe man kann da was finden.
    Gruß herrm_no


  • Also ich hab jetzt mein Problem gefunden.
    Eigentlich hätte schon alles funktioniert jedoch musst ich im Manifest

    Quellcode

    1. <uses-permission-sdk-23 android:name="android.permission.WRITE_SETTINGS" />


    einstellen und im
    Build.gradle

    Quellcode

    1. android {
    2. compileSdkVersion 27
    3. defaultConfig {
    4. applicationId "com.herrm_no.bttetheringonoff"
    5. minSdkVersion 22
    6. //noinspection ExpiredTargetSdkVersion
    7. targetSdkVersion 22
    8. versionCode 1
    9. versionName "1.0"
    10. testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    11. }
    Alles anzeigen
    Die targetSdKVersion von 27 auf 22 umstellen..
    Das war eigentlich der Hauptfehler. Ich habe immer ein neues Projekt erstellt und da war die TargetSDK Version immer höher als 22.
    Ich versteh allerdings immer noch nicht so recht warum es auf SDKVersion 22 und kleiner funtioniert und höher nicht mehr.
    Unabhängig welche Android Version auf dem Handy installiert ist.

    Danke aber für die Super Hilfe :)
    Gruß herrm_no
  • Hi,
    sorry für die späte Antwort, hatte am Wochenende einiges zu tun...
    Ich habe die SDK-Version selbst auf 28 und keine Probleme.

    Die Klasse android.bluetooth.BluetootPan exisitert fest im Android-System und muss deswegen nicht hinzugefügt werden.
    Da dies aber keine offizelle API Lösung ist, kann ich dir nicht genau sagen und welchen Android-Versionen es läuft.
    Soweit ich das gesehen hatte, sollte es aber eigentlich fast überall gehen.

    Hier meine Demo-App, die kannst du ja mal vergleichen. drive.google.com/open?id=15aDXkWXzD8gzB3tGjHxRzOqefaMfwBin
  • Jetzt hab ich aber doch noch ein Problem
    Ich habe einen Button auf der Start Seite der BT und Tethering ein und ausschaltet.
    Das funktioniert auch super gut.
    Allerdings läuft er beim
    Erste Mal : Button drücken > OnServiceConnected > ich krieg einen Toast auf den Bildschirm gemeldet - BT und Tethering sind aber dann eingeschaltet
    beim 2 Mal Button drücken BT und Tethering ist aus : OK
    beim 3 Mal Button drücken > OnServiceConnected > ich krieg zwei Toasts hintereinander > er läuft 2 mal den Code durch - BT und Tethering sind aber dann eingeschaltet
    beim 4 Mal Button BT und Tehtering ist aus: OK
    beim 5 Mal Button >OnServiceConnected > ich krieg 3 Toasts hintereinander > er läuft 3 mal den Code durch - BT und Tethering sind aber dann ein geschaltet
    usw.
    Der Code für BT ist hier natürlich nicht zu sehen. Das Problem liegt nur am Tethering
    Was kann da der Grund dafür sein.
    Ich versteh überhaupt nicht warum der BTPANServiceListener da so reagiert.
    Ich hab schon alles mögliche probiert. Immer das selbe Ergebnis.
    Auch wenn ich den Code so wie bei dir in Demo-App verwende kommt das gleiche raus (Deine Demo App hab ich leider nicht zum laufen gebracht. Das Problem geh ich aber danach noch an)
    Muss man den Listerner irgendwie zurücksetzen oder...
    Gruß

    Quellcode

    1. public class BTPanServiceListener implements BluetoothProfile.ServiceListener {
    2. private final Context context;
    3. public static boolean state = false;
    4. public BTPanServiceListener(final Context context) {
    5. this.context = context;
    6. }
    7. @Override
    8. public void onServiceConnected(final int profile,
    9. final BluetoothProfile proxy) {
    10. boolean nowVal;
    11. //Some code must be here or the compiler will optimize away this callback.
    12. Log.i("MyApp", "BTPan proxy connected");
    13. try {
    14. //boolean nowVal = ((Boolean) proxy.getClass().getMethod("isTetheringOn", new Class[0]).invoke(proxy, new Object[0])).booleanValue();
    15. nowVal = (Boolean) proxy.getClass().getMethod("isTetheringOn", new Class[0]).invoke(proxy, new Object[0]);
    16. if (nowVal) {
    17. proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, Boolean.FALSE);
    18. // proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, Boolean.FALSE);
    19. Toast.makeText(context, "onServiceConnected: Turning bluetooth tethering off", Toast.LENGTH_SHORT).show();
    20. state = false;
    21. } else {
    22. proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, true);
    23. //proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, new Object[]{Boolean.valueOf(true)});
    24. //proxy.getClass().getMethod("setBluetoothTethering", new Class[]{Boolean.TYPE}).invoke(proxy, Boolean.TRUE);
    25. Toast.makeText(context, "onServiceConnected: Turning bluetooth tethering on", Toast.LENGTH_SHORT).show();
    26. state = true;
    27. }
    28. // BluetoothTethering.changeToggleState(state);
    29. } catch (IllegalAccessException e) {
    30. // TODO Auto-generated catch block
    31. e.printStackTrace();
    32. } catch (IllegalArgumentException e) {
    33. // TODO Auto-generated catch block
    34. e.printStackTrace();
    35. } catch (InvocationTargetException e) {
    36. // TODO Auto-generated catch block
    37. e.printStackTrace();
    38. } catch (NoSuchMethodException e) {
    39. // TODO Auto-generated catch block
    40. e.printStackTrace();
    41. }
    42. }
    43. @Override
    44. public void onServiceDisconnected(final int profile) {
    45. }
    46. }
    Alles anzeigen
  • Ich habe gerade mal geschaut. Der BluetoothProfile.ServiceListener wird bei mir am Start einmal ausgeführt und danach reagiert er nur auf Bluetooth (an/aus) Änderungen.
    Er reagiert nicht auf Bluetooth Tethering (an/aus) Änderungen.
    Also solltest du den Listener nicht dafür verwenden Tethering-Änderungen mit zu bekommen. Ab du könnest einen Thread/Service erstellen und dort via isTetheringOn überprüfen, ob es an oder aus ist.
  • So, jetzt hab ich das Problem glaub ich gefunden.
    Ich hab jetzt mit if und while schleifen versucht meine Probleme irgendwie in den Griff zu bekommen.
    Es hat auch zum Schluss alles funktioniert. Dann hab ich zufälligerweise auf dem Handy Bildschirm beim starten meiner Software immer bei einem anderes Widget bemerkt das es das Icon von on auf off und umgekehrt wechselt.
    Das war ein anderes Tool was ich vor längerem installiert und nicht mehr dran gedacht habe. (macht eigentlich das Selbe wie meine App)
    Nach der Deinstallation hat alles so funktioniert wie es hätte sein sollen.
    Das andere Tool hat mir also dazwischen gefunkt. Jetzt läuft der BTPanServiceListener auch so wie er laufen soll.

    Endliiiiiiiich :)
    Danke für all die Hilfe
    Gruß
  • Neu

    Hallo ich mische mich mal dazu.


    Also ich habe auch mal das Test Beispiel von @Xcreen getestet läuft ohne Probleme. Unter AS 3.4 und auch Gradle 5.1.1 habe aber auch die dependencies angepasst.

    In der onCreate brauchst du doch nur den Button abfragen. Oder willst du den Button gar nicht haben? Wenn ja mache dir eine Variable in der du den Status speicherst.

    dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'



    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha03'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha03'

    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    Ein Feedback auf Tipps ist auch schön. :P