0

我正在尝试扫描BLE设备并在我的BLEFragment中显示它们。 但是,我有当我点击(R.id.scanButton)错误:获取null视图的上下文

E/AndroidRuntime: FATAL EXCEPTION: main 
                    Process: com.my.example, PID: 10990 
                    java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.view.View.getContext()' on a null object reference 
                     at com.iothings.connect.BLEFragment$ListAdapter.getView(BLEFragment.java:231) 
                     at android.widget.AbsListView.obtainView(AbsListView.java:2389) 
                     at android.widget.ListView.makeAndAddView(ListView.java:1878) 
                     at android.widget.ListView.fillDown(ListView.java:705) 
                     at android.widget.ListView.fillFromTop(ListView.java:766) 
                     at android.widget.ListView.layoutChildren(ListView.java:1673) 
                     at android.widget.AbsListView.onLayout(AbsListView.java:2191) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743) 
                     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586) 
                     at android.widget.LinearLayout.onLayout(LinearLayout.java:1495) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 
                     at android.widget.FrameLayout.onLayout(FrameLayout.java:273) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:131) 
                     at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42) 
                     at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1375) 
                     at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:870) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1193) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 
                     at android.widget.FrameLayout.onLayout(FrameLayout.java:273) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743) 
                     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586) 
                     at android.widget.LinearLayout.onLayout(LinearLayout.java:1495) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 
                     at android.widget.FrameLayout.onLayout(FrameLayout.java:273) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743) 
                     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586) 
                     at android.widget.LinearLayout.onLayout(LinearLayout.java:1495) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 
                     at android.widget.FrameLayout.onLayout(FrameLayout.java:273) 
                     at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2720) 
                     at android.view.View.layout(View.java:16662) 
                     at android.view.ViewGroup.layout(ViewGroup.java:5439) 
                     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2202) 
                     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1955) 
                     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1125) 
                     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6100) 
                     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) 
                     at android.view.Choreographer.doCallbacks(Choreographer.java:670) 
                     at android.view.Choreographer.doFrame(Choreographer.java:606) 
                    at android.view.Choreographe 

BLEFragment.java

public class BLEFragment extends Fragment implements ScanResultsConsumer { 

private boolean ble_scanning = false; 
//public Handler handler = new Handler(); 
private ListAdapter ble_device_list_adapter; 
private BLEScanner ble_scanner; 
private static final long SCAN_TIMEOUT = 5000; 
private static final int REQUEST_LOCATION = 0; 
private static String[] PERMISSIONS_LOCATION = {Manifest.permission.ACCESS_COARSE_LOCATION}; private boolean permissions_granted=false; 
private int device_count=0; 
private Toast toast; 
static class ViewHolder { 
    public TextView text; 
    public TextView bdaddr; 
} 

@BindView(R.id.deviceList) ListView listView; 
@BindView(R.id.scanButton) Button scanButton; 


@OnClick(R.id.scanButton) 
public void onScan(View view) { 
    if (!ble_scanner.isScanning()) { 
     Log.d(Constants.TAG, "Not currently scanning"); 
     device_count=0; 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      if (getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) 
        != PackageManager.PERMISSION_GRANTED) { 
       permissions_granted = false; 
       requestLocationPermission(); 
      } else { 
       Log.i(Constants.TAG, "Location permission has already been granted. Starting scanning."); 
       permissions_granted = true; 
      } 
     } else { 
      // the ACCESS_COARSE_LOCATION permission did not exist before M so.... 
      permissions_granted = true; 
     } 
     startScanning(); 
    } else { 
     Log.d(Constants.TAG, "Already scanning"); 
     ble_scanner.stopScanning(); 
    } 
} 

private void startScanning() { 
    if (permissions_granted) { 
     getActivity().runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       ble_device_list_adapter.clear(); 
       ble_device_list_adapter.notifyDataSetChanged(); 
      } 
     }); 
     simpleToast(Constants.SCANNING,2000); 
     ble_scanner.startScanning(this, SCAN_TIMEOUT); 
    } else { 
     Log.i(Constants.TAG, "Permission to perform Bluetooth scanning was not yet granted"); 
    } 
} 

@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
    //returning our layout file 
    View view = inflater.inflate(R.layout.fragment_2_ble, container, false); 
    ButterKnife.bind(this, view); 

    setButtonText(); 

    ble_device_list_adapter = new ListAdapter(); 

    listView.setAdapter(ble_device_list_adapter); 

    ble_scanner = new BLEScanner(); 

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 

     @Override 
     public void onItemClick(AdapterView<?> parent, View view, 
           int position, long id) { 

      if (ble_scanning) { 
       ble_scanner.stopScanning(); 
      } 

      BluetoothDevice device = ble_device_list_adapter.getDevice(position); 
      if (toast != null) { 
       toast.cancel(); 
      } 
      Intent intent = new Intent(getActivity(), PeripheralControlActivity.class); 
      intent.putExtra(PeripheralControlActivity.EXTRA_NAME, device.getName()); 
      intent.putExtra(PeripheralControlActivity.EXTRA_ID, device.getAddress()); 
      startActivity(intent); 

     } 
    }); 
    return view; 
} 


@Override 
public void candidateBleDevice(final BluetoothDevice device, byte[] scan_record, int rssi) { 
    getActivity().runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      ble_device_list_adapter.addDevice(device); 
      ble_device_list_adapter.notifyDataSetChanged(); 
      device_count++; 
     } 
    }); 
} 

@Override 
public void scanningStarted() { 
    setScanState(true); 
} 

@Override 
public void scanningStopped() { 
    if (toast != null) { 
     toast.cancel(); 
    } 
    setScanState(false); 
} 

private void setButtonText() { 
    String text=""; 
    text = Constants.FIND; 
    final String button_text = text; 
    getActivity().runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      //((TextView) MainActivity.this.findViewById(R.id.scanButton)).setText(button_text); 
     } 
    }); 
} 

private void setScanState(boolean value) { 
    ble_scanning = value; 
    Log.d(Constants.TAG,"Setting scan state to "+value); 
    scanButton.setText(value ? Constants.STOP_SCANNING : Constants.FIND); 
} 

public static class ListAdapter extends BaseAdapter { 
    private ArrayList<BluetoothDevice> ble_devices; 

    public ListAdapter() { 
     super(); 
     ble_devices = new ArrayList<BluetoothDevice>(); 
    } 

    public void addDevice(BluetoothDevice device) { 
     if (!ble_devices.contains(device)) { 
      ble_devices.add(device); 
     } 
    } 

    public boolean contains(BluetoothDevice device) { 
     return ble_devices.contains(device); 
    } 

    public BluetoothDevice getDevice(int position) { 
     return ble_devices.get(position); 
    } 

    public void clear() { 
     ble_devices.clear(); 
    } 

    @Override 
    public int getCount() { 
     return ble_devices.size(); 
    } 

    @Override 
    public Object getItem(int i) { 
     return ble_devices.get(i); 
    } 

    @Override 
    public long getItemId(int i) { 
     return i; 
    } 

    @Override 
    public View getView(int i, View view, ViewGroup viewGroup) { 
     ViewHolder viewHolder; 
     if (view == null) { 
      Context context = view.getContext(); 
      LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = inflater.inflate(R.layout.list_row, null); 
      viewHolder = new ViewHolder(); 
      viewHolder.text = (TextView) view.findViewById(R.id.textView); 
      viewHolder.bdaddr = (TextView) view.findViewById(R.id.bdaddr); 
      view.setTag(viewHolder); 
     } else { 
      viewHolder = (ViewHolder) view.getTag(); 
     } 
     BluetoothDevice device = ble_devices.get(i); 
     String deviceName = device.getName(); 
     if (deviceName != null && deviceName.length() > 0) { 
      viewHolder.text.setText(deviceName); 
     } else { 
      viewHolder.text.setText("unknown device"); 
     } 
     viewHolder.bdaddr.setText(device.getAddress()); 
     return view; 
    } 
} 

private void requestLocationPermission() { 
    Log.i(Constants.TAG, "Location permission has NOT yet been granted. Requesting permission."); 
    if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION)){ 
     Log.i(Constants.TAG, "Displaying location permission rationale to provide additional context."); 
     final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
     builder.setTitle("Permission Required"); 
     builder.setMessage("Please grant Location access so this application can perform Bluetooth scanning"); 
     builder.setPositiveButton(android.R.string.ok, null); 
     builder.setOnDismissListener(new DialogInterface.OnDismissListener() { 
      public void onDismiss(DialogInterface dialog) { 
       Log.d(Constants.TAG, "Requesting permissions after explanation"); 
       ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION); 
      } 
     }); 
     builder.show(); 
    } else { 
     ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION); 
    } 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
    if (requestCode == REQUEST_LOCATION) { 
     Log.i(Constants.TAG, "Received response for location permission request."); 
     // Check if the only required permission has been granted 
     if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
      // Location permission has been granted 
      Log.i(Constants.TAG, "Location permission has now been granted. Scanning....."); 
      permissions_granted = true; 
      if (ble_scanner.isScanning()) { 
       startScanning(); 
      } 
     }else{ 
      Log.i(Constants.TAG, "Location permission was NOT granted."); 
     } 
    } else { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
    } 
} 

private void simpleToast(String message, int duration) { 
    toast = Toast.makeText(getActivity(), message, duration); 
    toast.setGravity(Gravity.CENTER, 0, 0); 
    toast.show(); 
} 

@Override 
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    //you can set the title for your toolbar here for different fragments different titles 
    getActivity().setTitle("BLE"); 
} 
} 

BLEScanner.java

public class BLEScanner { 
private BluetoothLeScanner scanner = null; 
private BluetoothAdapter bluetooth_adapter = null; 
private Handler handler = new Handler(); 
private ScanResultsConsumer scan_results_consumer; 
private Context context; 
private boolean scanning = false; 
private String device_name_start = ""; 


public void BleScanner(Context context) { 
    this.context = context; 

    final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); 
    bluetooth_adapter = bluetoothManager.getAdapter(); 

    // check bluetooth is available and on 
    if (bluetooth_adapter == null || !bluetooth_adapter.isEnabled()) { 
     Log.d(Constants.TAG, "Bluetooth is NOT switched on"); 
     Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
     enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     context.startActivity(enableBtIntent); 
    } 
    Log.d(Constants.TAG, "Bluetooth is switched on"); 
} 


public void startScanning(final ScanResultsConsumer scan_results_consumer, long stop_after_ms) { 
    if (scanning) { 
     Log.d(Constants.TAG, "Already scanning so ignoring startScanning request"); 
     return; 
    } 
    Log.d(Constants.TAG, "Scanning..."); 
    if (scanner == null) { 
     scanner = bluetooth_adapter.getBluetoothLeScanner(); 
     Log.d(Constants.TAG, "Created BluetoothScanner object"); 
    } 
    handler.postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      if (scanning) { 
       Log.d(Constants.TAG, "Stopping scanning"); 
       scanner.stopScan(scan_callback); 
       setScanning(false); 
      } 
     } 
    }, stop_after_ms); 

    this.scan_results_consumer = scan_results_consumer; 
    List<ScanFilter> filters; 
    filters = new ArrayList<ScanFilter>(); 
    /*ScanFilter filter = new ScanFilter.Builder().setDeviceName("SP5").build(); 
    filters.add(filter);*/ 
    ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 
    setScanning(true); 
    scanner.startScan(filters, settings, scan_callback); 
} 

public void stopScanning() { 
    setScanning(false); 
    Log.d(Constants.TAG, "Stopping scanning"); 
    scanner.stopScan(scan_callback); 
} 

private ScanCallback scan_callback = new ScanCallback() { 
    public void onScanResult(int callbackType, final ScanResult result) { 
     if (!scanning) { 
      return; 
     } 
     scan_results_consumer.candidateBleDevice(result.getDevice(), result.getScanRecord().getBytes(), result.getRssi()); 
    } 
}; 

public boolean isScanning() { 
    return scanning; 
} 

void setScanning(boolean scanning) { 
    this.scanning = scanning; 
    if (!scanning) { 
     scan_results_consumer.scanningStopped(); 
    } else { 
     scan_results_consumer.scanningStarted();  } 
} 
} 

我想问题来自null的视图的getContext。 有关如何解决此问题的任何想法?由于

+0

您可以在上下文中使用getActivity() – Redman

回答

1

ViewGroup viewGroup不为空,所以你可以使用

viewGroup.getContext() 
0

您可以使用以下行来获取上下文中的片段。

getActivity().getBaseContext(); 

用上面的代码替换上述getView()方法中的上下文。

+0

由于适配器位于“静态”类中,用户将无法访问'getActivity'。 –