简体   繁体   中英

Internet socket connection stops the app on android

I have a problem with my app. I have a MainActivity, where is a drawer with fragments. From Scan fragment I call Scan Activity. This part is workng. And when I press back button, it goes back to MainActivity with ScanFragment. And there is also socket operation to send the code and maybe there is the problem. When I turn off wifi, it shows I/O error in Toast, but when I try to send the data, it goes into black screen. I found the problem in profiler, that MainActivity do not start after closing Scan activity, but the app is still running.

活动缺失图片

After a while android ask, if close non responding app. I tried to move all classes and functions into MainActivity, but then scanner wont start. Thanks for any help

My code of MainActivity.java :

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    private DrawerLayout drawer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        drawer = findViewById(R.id.drawer_layout);

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ScanFragment()).commit();
            navigationView.setCheckedItem(R.id.nav_scan);
        }
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        switch (menuItem.getItemId()) {
            case R.id.nav_scan:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ScanFragment()).commit();
                break;
            case R.id.nav_okruh:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OkruhFragment()).commit();
                break;
            case R.id.nav_kzavozu:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new KZavozuFragment()).commit();
                break;
            case R.id.nav_zprava:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ZpravaFragment()).commit();
                break;
        }
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    @Override
    public void onBackPressed() {
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }
}

Code of ScanFragment.java :

public class ScanFragment extends Fragment {
    String kod;
    String hostname = (address);
    int port = (number);

    Date date;
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_scan, container, false);
        Button button = (Button) view.findViewById(R.id.button2);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                zapnoutSkener();
            }
        });
        Button rucne = (Button) view.findViewById(R.id.button3);
        final EditText rucneKod = (EditText) view.findViewById(R.id.numberInput);

        rucne.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                odeslat(rucneKod.getText().toString());
            }
        });
        return view;
    }

    public class Spojeni extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... strings) {
            Log.i("hodnota", strings[0]);
            Log.i("kod", strings[1]);
            try (Socket socket = new Socket(hostname, port)) {
                OutputStream outputStream = socket.getOutputStream();
                InputStream inputStream = socket.getInputStream();

                PrintWriter writer = new PrintWriter(outputStream, true);
                writer.println(strings[0] + ";" + kod + ";" + simpleDateFormat.format(date));

                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                String line = reader.readLine();
                socket.close();
                return line;
            } catch (UnknownHostException e) {
                return "Server nebezi, zopakujte odeslani";
            } catch (IOException e) {
                return "I/O Error, zkontrolujte pripojeni k internetu";
            } catch (Exception e) {
                return "Obecny error";
            }
        }
    }

    public void zapnoutSkener() {
        Intent intent = new Intent(getActivity(), ScanOkno.class);
        Toast.makeText(getActivity(), "Zapinani akce", Toast.LENGTH_LONG).show();
        Log.i("Zapinani skeneru", "ted");
        startActivityForResult(intent, 1);
    }

    public void odeslat(String kod) {
        date = Calendar.getInstance().getTime();
        Toast.makeText(getActivity(), "Odesílám kód: " + kod, Toast.LENGTH_SHORT).show();
        Spojeni spojit = new Spojeni();
        String odpoved = null;
        try {
            odpoved = spojit.execute("SCAN", kod).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.i("Odpoved", odpoved);
        Toast.makeText(getActivity(), "Odpoved: " + odpoved, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 1) {
            Log.i("KOD", String.valueOf(resultCode));
            if (resultCode == 1) {
                String result = data.getStringExtra("code");
                Log.i("Vysledek", result);
                odeslat(result);
            }
        }
    }
}

Code of scanner activity ScanOkno.java :

public class ScanOkno extends AppCompatActivity implements BarcodeReader.BarcodeReaderListener {

    private BarcodeReader barcodeReader;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan_okno);
        barcodeReader = (BarcodeReader) getSupportFragmentManager().findFragmentById(R.id.barcode_fragment);
    }

    @Override
    public void onScanned(Barcode barcode) {
        // play beep sound
        barcodeReader.playBeep();
        String kod = barcode.rawValue;
        barcodeReader.pauseScanning();
        Intent intent = new Intent();
        intent.putExtra("code", barcode.rawValue);
        setResult(1, intent);
        finish();
        //Intent intent = new Intent(getApplicationContext(), MainActivity.class);
        //intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
    }

    @Override
    public void onScannedMultiple(List<Barcode> list) {

    }

    @Override
    public void onBitmapScanned(SparseArray<Barcode> sparseArray) {

    }

    @Override
    public void onScanError(String s) {

    }

    @Override
    public void onCameraPermissionDenied() {
        Toast.makeText(getApplicationContext(), "Camera permission denied!", Toast.LENGTH_LONG).show();
    }
}
odpoved = spojit.execute("SCAN", kod).get()

is your problem. Calling get() on an AsyncTask blocks the current Thread until the task completes, essentially defeating the purpose of an AsyncTask.

Consider using a callback.

First, make Spojeni a static class:

public static class Spojeni extends AsyncTask<String, Void, String>

This will prevent memory leaks from occurring. I do see some variables that you access inside the parent class, but you can pass them in your call to execute() and retrieve them from your AsyncTask there.

Then, create an interface (can be a child of ScanFragment or in its own file):

public interface OnTaskCompleteListener {
    void onTaskComplete(String result);
}

Add a constructor and a global variable to your AsyncTask:

private OnTaskCompleteListener listener;

public Spojeni(OnTaskCompleteListener listener) {
    this.listener = listener;
}

And implement onPostExecute() :

@Override
public void onPostExecute(String result) {
    listener.onTaskComplete(result);
}

When you create an instance of Spojeni:

new Spojeni(new OnTaskCompleteListener() {
    @Override
    public void onTaskComplete(String result) {
        //handle the result
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM