2017-05-22 4 views
-1

Ich arbeite an dem Projekt, in dem Sie mit anderen Gerät über Bluetooth RFCOMM verbinden müssen. Ich habe einen Code geschrieben (meistens basierend auf Mitch Tabian Tutorials auf youtube), und ich stecke fest.Kann nicht empfangen und senden Daten über Bluetooth RFComm in Android App

Ich kann mit dem Laptop verbinden, aber ich kann keine Daten senden und empfangen. Ich bitte euch um meinen Code zu suchen und mir sagen, welcher Teil falsch ist

Zweite Aktivität

package com.example.mgr; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Build; 
import android.os.Bundle; 
import android.support.annotation.Nullable; 
import android.support.v4.content.LocalBroadcastManager; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.ImageView; 
import android.widget.Spinner; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.nio.charset.Charset; 
import java.util.ArrayList; 
import java.util.UUID; 

public class pulpit2kod extends AppCompatActivity { 
    private static final String TAG = "pulpit2kod"; 
    BluetoothAdapter mBluetoothAdapter; 
    private Spinner spinnerlist; 
    private ArrayList<String> mDeviceList = new ArrayList<>(); 
    private ArrayList<BluetoothDevice> bttDeviceList = new ArrayList<>(); 
    private ImageView btton; 
    private ImageView bttoff; 
    BluetoothDevice mBTDevice; 
    Button btconnect; 
    Button btsearch; 
    Button btgoto1screen; 
    Button btONOFF; 
    Button btvisibility; 
    Button btsend; 
    Button btpair; 
    EditText etsend; 
    BluetoothConnectionService mBluetoothConnection; 
    private static final UUID MY_UUID_INSECURE = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");//{0000110e-0000-1000-8000-00805f9b34fb} 

    StringBuilder messages; 
    TextView etreceive; 
    @Override 
    protected void onCreate(@Nullable Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.pulpit2); 
     spinnerlist = (Spinner) findViewById(R.id.spinner); 
     Log.d(TAG, "onCreate: Starting"); 
     btconnect = (Button) findViewById(R.id.polacz); 
     btsearch = (Button) findViewById(R.id.search) ; 
     btgoto1screen = (Button) findViewById(R.id.goto1screen); 
     btONOFF = (Button) findViewById(R.id.ONOFF); 
     btvisibility = (Button) findViewById(R.id.widocznosc); 
     btsend = (Button) findViewById(R.id.btsend); 
     btpair = (Button) findViewById(R.id.pair); 
     btton = (ImageView) findViewById(R.id.btton); 
     bttoff = (ImageView) findViewById(R.id.bttoff); 
     etsend = (EditText) findViewById(R.id.etsend); 
     etreceive = (TextView) findViewById(R.id.etreceive); 
     messages = new StringBuilder(); 

     LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver4, new IntentFilter("incomingMessage")); 
     //-------------------BT ON logo --------------------------------------------------------------- 
     int logobtton = getResources().getIdentifier("@drawable/btton", null, this.getPackageName()); 
     btton.setImageResource(logobtton); 
     //-------------------BT OFF logo -------------------------------------------------------------- 
     int logobttoff = getResources().getIdentifier("@drawable/bttoff", null, this.getPackageName()); 
     bttoff.setImageResource(logobttoff); 
     //---------------------lista position click-------------------------------- 
     spinnerlist.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 
      @Override 
      public void onItemSelected(AdapterView<?> parent, View view, final int position, long id) { 
       btpair.setOnClickListener(new View.OnClickListener() { 
        @Override 
        public void onClick(View v) { 
         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED); 
         registerReceiver(mBroadcastReceiver3,filter); 
         if (Build.VERSION.SDK_INT>Build.VERSION_CODES.JELLY_BEAN_MR2){ 
          bttDeviceList.get(position).createBond(); 
          mBTDevice = bttDeviceList.get(position); 
          mBluetoothConnection = new BluetoothConnectionService(pulpit2kod.this); 

         } 
        } 
       }); 

      } 
      @Override 
      public void onNothingSelected(AdapterView<?> parent) { 
       Toast.makeText(pulpit2kod.this,"Wybierz pozycję, aby polaczyc", Toast.LENGTH_SHORT).show(); 
      } 
     }); 
     btconnect.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       startConnection(); 
      } 
     }); 
     btsend.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
      byte [] bytes = etsend.getText().toString().getBytes(Charset.defaultCharset()); 
       mBluetoothConnection.write(bytes); 
       etsend.setText(""); 
      } 
     }); 

     //---------------------BT wyszikiwanie przycisk----------------------------- 
     btsearch.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
      wyszukiwanie(); 
      } 

     }); 
     //---------------------BT widocznosc przycisk------------------------------- 
     btvisibility.setOnClickListener(new View.OnClickListener(){ 
      @Override 
      public void onClick(View v) { 
       Log.d(TAG, "onCreate: discoverability bt"); 
       widocznosc(); 
      } 
     }); 

     //----------------------bluetooth przycisk---------------------------------- 
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     btONOFF.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Log.d(TAG, "onClick: enabling/disabling bt"); 
       enabledDisableBT(); 
       }}); 

     //--------------------- przycisk powrot do glownego menu---------------------- 
     btgoto1screen.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Log.d(TAG, "onClick: Powrot do menu"); 
       Intent intent = new Intent(pulpit2kod.this, MainActivity.class); 
       startActivity(intent); 
      } 
     }); 
    logobt(); 

    } 

    public void startConnection(){ 

     startBTConnection(mBTDevice,MY_UUID_INSECURE); 
    } 

    public void startBTConnection(BluetoothDevice device, UUID uuid){ 
     Log.d(TAG, "startBTConnection: Initializing RFCOM Bluetooth Connection."); 

     mBluetoothConnection.startClient(device,uuid); 
    } 

    private void logobt() { 
     if (!mBluetoothAdapter.isEnabled()){ 
      bttoff.setVisibility(View.VISIBLE); 
      btton.setVisibility(View.INVISIBLE); 
     } 
     if (mBluetoothAdapter.isEnabled()){ 
      bttoff.setVisibility(View.INVISIBLE); 
      btton.setVisibility(View.VISIBLE); 
     } 
    } 

    private void wyszukiwanie() { 
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     mBluetoothAdapter.startDiscovery(); 
     if (mBluetoothAdapter.isDiscovering()){ 
      mBluetoothAdapter.cancelDiscovery(); 
      mBluetoothAdapter.startDiscovery(); 
     } 
     if (!mBluetoothAdapter.isDiscovering()) { 
      mBluetoothAdapter.startDiscovery(); 
      } 
     bttDeviceList.clear(); 
     mDeviceList.clear(); 
     IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 
     registerReceiver(mReceiver,filter); 

     } 

    //------------------------- metoda widocznosc ---------------------------------------- 
    private void widocznosc() { 
     Log.d(TAG, "widocznosc: Making device discoverable for 120 seconds"); 
     Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); 
     startActivity(discoverableIntent); 
     IntentFilter intentFilter = new IntentFilter(mBluetoothAdapter.ACTION_SCAN_MODE_CHANGED); 
     registerReceiver(mBroadcastReceiver2,intentFilter); 
    } 




    //-------------------------kompatybilność z BT i ON/OFF------------------------------------- 
    private void enabledDisableBT() { 
     if(mBluetoothAdapter ==null){ 
      Log.d(TAG, "enabledDisableBT: BT not supported"); 
     } 
     if(!mBluetoothAdapter.isEnabled()){ 
      Intent enableBTIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
      startActivity(enableBTIntent); 
      IntentFilter BTIntent = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 
      registerReceiver(mBroadcastReceiver1, BTIntent); 
      bttDeviceList.clear(); 
      mDeviceList.clear(); 
      spinnerlist.setAdapter(null); 
      btton.setVisibility(View.VISIBLE); 
      bttoff.setVisibility(View.INVISIBLE); 
     } 
     if(mBluetoothAdapter.isEnabled()){ 
      mBluetoothAdapter.disable(); 
      IntentFilter BTInent = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 
      registerReceiver(mBroadcastReceiver1, BTInent); 
      bttoff.setVisibility(View.VISIBLE); 
      btton.setVisibility(View.INVISIBLE); 
      } 
     } 




    //---------------------------------------------------------------------------------------------- 
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 
     @Override 

     public void onReceive(Context context, Intent intent) { 
      String action = intent.getAction(); 
      if (BluetoothDevice.ACTION_FOUND.equals(action)) { 
       BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 
       bttDeviceList.add(device); 
       mDeviceList.add(device.getName()+": "+device.getAddress()); 
       Log.d(TAG, "onReceive: Dodano"+device.getName()+": "+device.getAddress()); 
       spinnerlist.setAdapter(new ArrayAdapter<String>(context,android.R.layout.simple_spinner_item,mDeviceList)); 
       } 
      } 
    }; 
    //---------------------------stan BT------------------------------------------------------- 
    private final BroadcastReceiver mBroadcastReceiver1 = new BroadcastReceiver() { 
     public void onReceive(Context context, Intent intent) { 
      final String action = intent.getAction(); 
      if (action.equals(mBluetoothAdapter.ACTION_STATE_CHANGED)){ 
       final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,mBluetoothAdapter.ERROR); 
       switch (state){ 
        case BluetoothAdapter.STATE_OFF: 
         Log.d(TAG, "onReceive: STATE OFF"); 
         Toast.makeText(pulpit2kod.this ,"Turned off",Toast.LENGTH_SHORT).show(); 
         break; 
        case BluetoothAdapter.STATE_TURNING_OFF: 
         Log.d(TAG, "onReceive: STATE TURNING OFF"); 
         Toast.makeText(pulpit2kod.this ,"Turning off",Toast.LENGTH_SHORT).show(); 
         break; 
        case BluetoothAdapter.STATE_TURNING_ON: 
         Log.d(TAG, "onReceive:STATE TURNING ON"); 
         Toast.makeText(pulpit2kod.this ,"Turning on",Toast.LENGTH_SHORT).show(); 
         break; 
        case BluetoothAdapter.STATE_ON: 
         Log.d(TAG, "onReceive: STATE ON"); 
         Toast.makeText(pulpit2kod.this ,"Turned on",Toast.LENGTH_SHORT).show(); 
         break; 

       } 
      } 
     } 
    }; 

    private final BroadcastReceiver mBroadcastReceiver2 = new BroadcastReceiver() { 
     public void onReceive(Context context, Intent intent) { 
      final String action = intent.getAction(); 
      if (action.equals(mBluetoothAdapter.ACTION_SCAN_MODE_CHANGED)){ 
       int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,mBluetoothAdapter.ERROR); 
       switch (mode){ 
        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 
         Log.d(TAG, "onReceive: Discoverability Enabled"); 
         break; 
        case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 
         Log.d(TAG, "onReceive: Discoverability Disabled. Able to recieve connections"); 
         break; 
        case BluetoothAdapter.SCAN_MODE_NONE: 
         Log.d(TAG, "onReceive:Discoverability Disabled. Not able to recieve connections"); 
         break; 
        case BluetoothAdapter.STATE_CONNECTING: 
         Log.d(TAG, "onReceive: Connecting"); 
         break; 
        case BluetoothAdapter.STATE_CONNECTED: 
         Log.d(TAG, "onReceive: Connected"); 
         break; 

       } 
      } 
     } 
    }; 
    private final BroadcastReceiver mBroadcastReceiver3 = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      final String action = intent.getAction(); 
      if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){ 
       BluetoothDevice mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 
       if (mDevice.getBondState()==BluetoothDevice.BOND_BONDED){ 
        Toast.makeText(pulpit2kod.this,"Bonded",Toast.LENGTH_SHORT).show(); 
        mBTDevice = mDevice; 

       } 
       if (mDevice.getBondState()==BluetoothDevice.BOND_BONDING){ 
        Toast.makeText(pulpit2kod.this,"Bonding",Toast.LENGTH_SHORT).show(); 
       } 
       if (mDevice.getBondState()==BluetoothDevice.BOND_NONE){ 
        Toast.makeText(pulpit2kod.this,"Not bonded",Toast.LENGTH_SHORT).show(); 

       } 
      } 
     } 
    }; 
    BroadcastReceiver mBroadcastReceiver4 = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      String text = intent.getStringExtra("theMessage"); 
      messages.append(text +"\n"); 
      etreceive.setText(messages); 
     } 
    }; 
    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     unregisterReceiver(mBroadcastReceiver1); 
     unregisterReceiver(mBroadcastReceiver2); 
     unregisterReceiver(mBroadcastReceiver3); 
     unregisterReceiver(mBroadcastReceiver4); 
     unregisterReceiver(mReceiver); 
    }} 

BluetoothConnectionService

package com.example.mgr; 


import android.app.ProgressDialog; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothServerSocket; 
import android.bluetooth.BluetoothSocket; 
import android.content.Context; 
import android.content.Intent; 
import android.support.v4.content.LocalBroadcastManager; 
import android.util.Log; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.nio.charset.Charset; 
import java.util.UUID; 

/** 
* Created by User on 12/21/2016. 
*/ 

public class BluetoothConnectionService { 
    private static final String TAG = "BluetoothConnectionServ"; 

    private static final String appName = "MYAPP"; 

    private static final UUID MY_UUID_INSECURE = 
      UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66"); 

    private final BluetoothAdapter mBluetoothAdapter; 
    Context mContext; 

    private AcceptThread mInsecureAcceptThread; 

    private ConnectThread mConnectThread; 
    private BluetoothDevice mmDevice; 
    private UUID deviceUUID; 
    ProgressDialog mProgressDialog; 

    private ConnectedThread mConnectedThread; 

    public BluetoothConnectionService(Context context) { 
     mContext = context; 
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     start(); 
    } 


    /** 
    * This thread runs while listening for incoming connections. It behaves 
    * like a server-side client. It runs until a connection is accepted 
    * (or until cancelled). 
    */ 
    private class AcceptThread extends Thread { 

     // lokalny serwer 
     private final BluetoothServerSocket mmServerSocket; 

     public AcceptThread(){ 
      BluetoothServerSocket tmp = null; 

      // nasluchiwanie 
      try{ 
       tmp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(appName, MY_UUID_INSECURE); 

       Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE); 
      }catch (IOException e){ 
       Log.e(TAG, "AcceptThread: IOException: " + e.getMessage()); 
      } 

      mmServerSocket = tmp; 
     } 

     public void run(){ 
      Log.d(TAG, "run: AcceptThread Running."); 

      BluetoothSocket socket = null; 

      try{ 
       Log.d(TAG, "run: RFCOM server socket start....."); 

       socket = mmServerSocket.accept(); 

       Log.d(TAG, "run: RFCOM server socket accepted connection."); 

      }catch (IOException e){ 
       Log.e(TAG, "AcceptThread: IOException: " + e.getMessage()); 
      } 

      if(socket != null){ 
       connected(socket,mmDevice); 
      } 

      Log.i(TAG, "END mAcceptThread "); 
     } 

     public void cancel() { 
      Log.d(TAG, "cancel: Canceling AcceptThread."); 
      try { 
       mmServerSocket.close(); 
      } catch (IOException e) { 
       Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage()); 
      } 
     } 

    } 

    private class ConnectThread extends Thread { 
     private BluetoothSocket mmSocket; 

     public ConnectThread(BluetoothDevice device, UUID uuid) { 
      Log.d(TAG, "ConnectThread: started."); 
      mmDevice = device; 
      deviceUUID = uuid; 
     } 

     public void run(){ 
      BluetoothSocket tmp = null; 
      Log.i(TAG, "RUN mConnectThread "); 

      // Get a BluetoothSocket for a connection with the 
      // given BluetoothDevice 
      try { 
       Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: " 
         +MY_UUID_INSECURE); 
       tmp = mmDevice.createRfcommSocketToServiceRecord(deviceUUID); 
      } catch (IOException e) { 
       Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage()); 
      } 

      mmSocket = tmp; 

      mBluetoothAdapter.cancelDiscovery(); 


      try { 
       mmSocket.connect(); 

       Log.d(TAG, "run: ConnectThread connected."); 
      } catch (IOException e) { 
       try { 
        mmSocket.close(); 
        Log.d(TAG, "run: Closed Socket."); 
       } catch (IOException e1) { 
        Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage()); 
       } 
       Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE); 
      } 

      connected(mmSocket,mmDevice); 
     } 
     public void cancel() { 
      try { 
       Log.d(TAG, "cancel: Closing Client Socket."); 
       mmSocket.close(); 
      } catch (IOException e) { 
       Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage()); 
      } 
     } 
    } 

    public synchronized void start() { 
     Log.d(TAG, "start"); 

     if (mConnectThread != null) { 
      mConnectThread.cancel(); 
      mConnectThread = null; 
     } 
     if (mInsecureAcceptThread == null) { 
      mInsecureAcceptThread = new AcceptThread(); 
      mInsecureAcceptThread.start(); 
     } 
    } 


    public void startClient(BluetoothDevice device,UUID uuid){ 
     Log.d(TAG, "startClient: Started."); 

     mProgressDialog = ProgressDialog.show(mContext,"Connecting Bluetooth" 
       ,"Please Wait...",true); 

     mConnectThread = new ConnectThread(device, uuid); 
     mConnectThread.start(); 
    } 

    private class ConnectedThread extends Thread { 
     private final BluetoothSocket mmSocket; 
     private final InputStream mmInStream; 
     private final OutputStream mmOutStream; 

     public ConnectedThread(BluetoothSocket socket) { 
      Log.d(TAG, "ConnectedThread: Starting."); 

      mmSocket = socket; 
      InputStream tmpIn = null; 
      OutputStream tmpOut = null; 

      try{ 
       mProgressDialog.dismiss(); 
      }catch (NullPointerException e){ 
       e.printStackTrace(); 
      } 


      try { 
       tmpIn = mmSocket.getInputStream(); 
       tmpOut = mmSocket.getOutputStream(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      mmInStream = tmpIn; 
      mmOutStream = tmpOut; 
     } 

     public void run(){ 
      byte[] buffer = new byte[1024]; 

      int bytes; 

      while (true) { 
       try { 
        bytes = mmInStream.read(buffer); 

        String incomingMessage = new String(buffer, 0, bytes); 

        Intent IncomingMessageIntent = new Intent("incomingMessage"); 
        IncomingMessageIntent.putExtra("theMessage",incomingMessage); 
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(IncomingMessageIntent); 
       } catch (IOException e) { 
        Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage()); 
        break; 
       } 
      } 
     } 


     public void write(byte[] bytes) { 
      String text = new String(bytes, Charset.defaultCharset()); 
      Log.d(TAG, "write: Writing to outputstream: " + text); 
      try { 
       mmOutStream.write(bytes); 
      } catch (IOException e) { 
       Log.e(TAG, "write: Error writing to output stream. " + e.getMessage()); 
      } 
     } 

     public void cancel() { 
      try { 
       mmSocket.close(); 
      } catch (IOException e) { } 
     } 
    } 

    private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) { 
     Log.d(TAG, "connected: Starting."); 

     // Start the thread to manage the connection and perform transmissions 
     mConnectedThread = new ConnectedThread(mmSocket); 
     mConnectedThread.start(); 
    } 

    /** 
    * Write to the ConnectedThread in an unsynchronized manner 
    * 
    * @param out The bytes to write 
    * @see ConnectedThread#write(byte[]) 
    */ 
    public void write(byte[] out) { 
     // Create temporary object 
     ConnectedThread r; 

     // Synchronize a copy of the ConnectedThread 
     Log.d(TAG, "write: Write Called."); 
     //perform the write 
     mConnectedThread.write(out); 
    } 

} 
+1

fügen Sie bitte die Logcat-Logs zur Frage hinzu –

Antwort

0

Ihr Code scheint auf BluetoothChat zu beruhen Beispiel, je nachdem, was Sie senden möchten, könnte Ihr Code korrekt oder völlig falsch sein.

Wenn Sie versuchen, Text an Laptop zu senden, müssen Sie eine Windows-Anwendung (UWP, .NET, Win32, MFC, was auch immer Sie wollen) für rfcomm Verbindungen machen.

Wenn Sie versuchen, Dateien zu senden, haben Sie 2 Möglichkeiten.

  • Senden an den Laptop über OBEX, Sie müssen kein Windows-Programm erstellen.
  • Senden Sie Dateien über RFCOMM, müssen Sie ein Windows-Programm erstellen und eigene Implementierungen für das Senden und Empfangen von Dateien in beiden mobilen und PC-Software.
  • Wenn Sie versuchen, benutzerdefinierte Daten zu senden, müssen Sie eine Windows-Anwendung (UWP, .NET, Win32, MFC, was auch immer Sie verwenden möchten) für rfcomm Verbindungen machen.

    Verwandte Themen