问题
I want to make a POS app. In this app, I need to print a receipt, but I have a problem with the bluetooth connection.
In this code, I want to set the printer device that I use in my fragment. I want the bluetooth to stay connected even though I move to another fragment. I put the code in my MainActivity, but the problem is every time I move to another fragment, mService
is always null. So I couldn't connect to the device.
Please help me. Thanks in advance.
MainActivity.Java
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener{
private static final String TAG = "MainActivity";
Fragment fragment = null;
Class fragmentClass = null;
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
public static final int MESSAGE_CONNECTION_LOST = 6;
public static final int MESSAGE_UNABLE_CONNECT = 7;
private String mConnectedDeviceName = null;
// Key names received from the BluetoothService Handler
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";
public static final int REQUEST_CONNECT_DEVICE = 1;
private static final int REQUEST_ENABLE_BT = 2;
private BluetoothAdapter mBluetoothAdapter = null;
public BluetoothService mService = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
fragmentClass = RegisterFragment.class;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_main2, fragment).commit();
Log.v(TAG, "Starting DoDaily service...");
startService(new Intent(this, DoDaily.class));
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
FragmentManager fm = getSupportFragmentManager();
//if you added fragment via layout xml
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the session
} else {
if (mService == null) {
setMService();
}
}
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.main2, menu);
return true;
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
String TAG_FRAGMENT="";
if (id == R.id.nav_regist) {
fragmentClass = RegisterFragment.class;
TAG_FRAGMENT ="register";
// Handle the camera action
} else if (id == R.id.nav_activity) {
fragmentClass = ActivityFragment.class;
TAG_FRAGMENT ="activity";
}
else if(id == R.id.nav_inventory)
{
fragmentClass = InventoryFragment.class;
TAG_FRAGMENT ="inventory";
}
else if (id == R.id.nav_manage) {
fragmentClass = SettingFragment.class;
TAG_FRAGMENT ="setting";
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_main2, fragment,TAG_FRAGMENT).commit();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if (DEBUG)
Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothService.STATE_CONNECTED:
//btnScan.setText(getText(R.string.Connecting));
fragment1.btnScanEnable(false);
break;
case BluetoothService.STATE_CONNECTING:
Toast.makeText(MainActivity.this,R.string.title_connecting,Toast.LENGTH_SHORT).show();
break;
case BluetoothService.STATE_LISTEN:
case BluetoothService.STATE_NONE:
Toast.makeText(MainActivity.this,R.string.title_not_connected,Toast.LENGTH_SHORT).show();
break;
}
break;
case MESSAGE_WRITE:
break;
case MESSAGE_READ:
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(MainActivity.this,"Connected to " + mConnectedDeviceName,
Toast.LENGTH_SHORT).show();
String text ="Connected to "+mConnectedDeviceName;
fragment1.setTvText(text);
break;
case MESSAGE_TOAST:
Toast.makeText(MainActivity.this, msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();
break;
case MESSAGE_CONNECTION_LOST:
Toast.makeText(MainActivity.this, "Device connection was lost",Toast.LENGTH_SHORT).show();
String text1 ="Not Connect to Any Device";
fragment1.setTvText(text1);
// editText.setEnabled(false);
// sendButton.setEnabled(false);
break;
case MESSAGE_UNABLE_CONNECT:
Toast.makeText(MainActivity.this, "Unable to connect device",
Toast.LENGTH_SHORT).show();
break;
}
}
};
@Override
public void onStart() {
super.onStart();
// If Bluetooth is not on, request that it be enabled.
// setupChat() will then be called during onActivityResult
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the session
} else {
if (mService == null){
setMService();
}
}
}
@Override
public synchronized void onResume() {
super.onResume();
if (mService != null) {
if (mService.getState() == BluetoothService.STATE_NONE) {
// Start the Bluetooth services
mService.start();
}
}
}
@Override
public synchronized void onPause() {
super.onPause();
if (DEBUG)
Log.e(TAG, "- ON PAUSE -");
}
@Override
public void onStop() {
super.onStop();
if (DEBUG)
Log.e(TAG, "-- ON STOP --");
}
@Override
public void onDestroy() {
super.onDestroy();
// Stop the Bluetooth services
if (mService != null)
mService.stop();
if (DEBUG)
Log.e(TAG, "--- ON DESTROY ---");
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (DEBUG)
Log.d(TAG, "onActivityResult " + resultCode);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:{
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
// Get the device MAC address
String address = data.getExtras().getString(
DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BLuetoothDevice object
if (BluetoothAdapter.checkBluetoothAddress(address)) {
BluetoothDevice device = mBluetoothAdapter
.getRemoteDevice(address);
// Attempt to connect to the device
mService.connect(device);
}
}
break;
}
case REQUEST_ENABLE_BT:{
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a session
// FragmentManager fm1 = getSupportFragmentManager();
// SettingFragment fragment1 = (SettingFragment) fm1.findFragmentByTag("setting");
// fragment1.KeyListenerInit();
setMService();
} else {
// User did not enable Bluetooth or an error occured
Log.d(TAG, "BT not enabled");
Toast.makeText(MainActivity.this, R.string.bt_not_enabled_leaving,Toast.LENGTH_SHORT).show();
onBackPressed();
}
break;
}
}
}
public void setMService()
{
mService = new BluetoothService(MainActivity.this, mHandler);
}
}
SettingFragment.Java
public class SettingFragment extends Fragment {
public static final int REQUEST_CONNECT_DEVICE = 1;
private static final String CHINESE = "GBK";
SessionManagement sessionManagement;
DatabaseHandler db;
TextView tvConnected;
Button btnScan;
Button btnTest;
public SettingFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootview = inflater.inflate(R.layout.fragment_setting, container, false);
getActivity().setTitle("Setting");
btnScan = (Button)rootview.findViewById(R.id.btnScan);
btnTest = (Button) rootview.findViewById(R.id.btnTest);
tvConnected = (TextView) rootview.findViewById(R.id.tvPrinterConnect);
KeyListenerInit();
return rootview;
}
public void setTvText(String text)
{
tvConnected = (TextView) getActivity().findViewById(R.id.tvPrinterConnect);
tvConnected.setText(text);
}
public void btnScanEnable(Boolean set)
{
btnScan = (Button)getActivity().findViewById(R.id.btnScan);
btnScan.setEnabled(set);
}
public void KeyListenerInit() {
btnScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
});
((MainActivity)getActivity()).setMService();
}
}
回答1:
remove this line from fragment KeyListenerInit method because you already initialize object in Activity then why you again intialize this.
((MainActivity)getActivity()).setMService();
and remove this code from onCreate method because you already add this code in onStart method so no need in onCreate method:
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the session
} else {
if (mService == null) {
setMService();
}
}
来源:https://stackoverflow.com/questions/43261428/bluetooth-printer-connection-failed-in-android