获取空视图的上下文

时间:2017-02-28 07:19:50

标签: android listview android-fragments bluetooth bluetooth-lowenergy

我正在尝试扫描BLE设备并在我的BLEFragment中显示它们。 但是,当我点击(R.id.scanButton)时出现错误:

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();        }
}
}

我认为问题来自视图的getContext为null。 有关如何解决这个问题的任何想法?感谢

2 个答案:

答案 0 :(得分:1)

ViewGroup viewGroup不为空,因此您可以使用

viewGroup.getContext() 

答案 1 :(得分:0)

您可以使用以下行在Fragment中获取上下文。

getActivity().getBaseContext();

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