My main activity kicks off a secondary activity (using 
startActivityForResult) that invites the user to input details of one of 
four players at a bridge table.

When the user has chosen a player and clicked OK, the following things 
happen (triggered by code in onActivityResult)

1. The player details (passed back in the Intent returned by the secondary 
activity) are written to a text file.
2. An AsyncTask is started to send that file to a server PC using SMB.
3. While the AsyncTask is still running, the same secondary activity is 
invoked again to get the next player's details.

This sequence is repeated until all four players' details have been sent to 
the server.

On my tablet, this works perfectly every time but one of my beta testers 
has a bizarre problem. He can usually enter the first player's name 
successfully, sometimes the second and occasionally the third but 
eventually one of the names screens appears for a short time later only to 
disappear again without the user clicking my OK button.

Note that the player-names screen allows the user to type a partial name 
and uses a ListView to display all players in a club membership list that 
contain the letters typed. I don't know if that's significant.

What I am seeing in my trace file is that the onCreate method of the select 
player activity is called. The OKClicked method is never called. In fact, I 
have trace points before every finish() call in the select player activity 
and none of them is called. After the onCreate call, the next thing I see 
in my trace file, about 30 seconds later, is onActivityResult reporting a 
ResultCode of zero and the returned Intent pointer of null. In other words, 
the select player activity has spontaneously closed without the user 
clicking OK or it going through any of my code designed to close the 
activity tidily.

This never happens on my tablet, which is running Android 4.4.2. It always 
happens on my beta tester's tablet, which is running 4.4.

After reading reports of a similar Android problem, I changed all the 
activities' settings in my manifest (including the main activity) to 
launchMode singleTop but this made no difference.

Any suggestions? This is particularly awkward because I cannot reproduce 
the problem on my kit. I am having to do all my debugging remotely by 
adding trace points and asking my beta tester to repeat the experiment.

I have uploaded the code for the select player activity in case it's of 
interest.

Kind regards
Keith


-- 
You received this message because you are subscribed to the Google Groups 
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to android-developers+unsubscr...@googlegroups.com.
To post to this group, send email to android-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/android-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/android-developers/6502018f-b8b0-4dbb-a3a8-b132458cca3d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
package uk.org.writerman.scoresheet;

import android.content.Intent;
import android.os.SystemClock;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;

public class SelectPlayer extends AppCompatActivity {

    private cClubMembers MembershipList = new cClubMembers();
    private cClubMembers EBUList = new cClubMembers();

    private cClubMembers MatchingPlayers = new cClubMembers();

    private cClubMemberDetails ChosenPlayer;

    private String TableName;
    private boolean UseExternalFilestore;
    private boolean HaveNamesFile;
    private boolean HaveEBUList;
    private String SeatName;

    private Button OKButton;
    private ImageButton SearchButton;

    private ListView lvMatches;
    private long LastAbortClick;

    private boolean m_InternalChange;
    private boolean VisitorOnDisplay;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // SelectPlayer. Parameters are Table identity string, Seat (as string) UseExternalFilestore and HaveNames
        // If it's a repeat, may also have ParamPlayerID, ParamPlayerName and ParamPlayerEBUNo
        // Return values are ParamPlayerID, ParamPlayerName and ParamPlayerEBUNo

        // We use the prompt above the input box (instructions when input is empty) to show
        //      no matches, number of matches or full details of exact match. Colour code the background
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_select_player);

        // STAW
        Statics.log(getApplicationContext(), "Start SelectPlayer activity");

        m_InternalChange = false;
        VisitorOnDisplay = false;
        LastAbortClick = SystemClock.elapsedRealtime() - 4000;      // To ensure first click doesn't abort

        TableName = getIntent().getStringExtra(GLOBALS.ParamChosenTable);
        SeatName = getIntent().getStringExtra(GLOBALS.ParamCompassPole);
        UseExternalFilestore = getIntent().getBooleanExtra(GLOBALS.ParamUseExternalFilestore, true);
        HaveNamesFile = getIntent().getBooleanExtra(GLOBALS.ParamHaveNames, false);
        HaveEBUList = getIntent().getBooleanExtra(GLOBALS.ParamHaveEBUList, false);

        final TextView tvCaption = (TextView) findViewById(R.id.spTableCaption);
        tvCaption.setText(getString(R.string.Table) + " " + TableName + " " + SeatName);

        OKButton = (Button)findViewById(R.id.bOK);
        lvMatches = (ListView)findViewById(R.id.spMatchList);

         if (HaveNamesFile) {
            try {
                MembershipList.ProcessNamesFile(getApplicationContext(), UseExternalFilestore, GLOBALS.NamesFileName);
            } catch (Exception ex) {
                Toast.makeText(getApplicationContext(), R.string.CannotParseNames, Toast.LENGTH_LONG).show();
            }
        }

        if (HaveEBUList) {
            try {
                EBUList.ProcessNamesFile(getApplicationContext(), UseExternalFilestore, GLOBALS.EBUNamesFile);
                EBUList.isEBUList = true;
            } catch (Exception ex) {
                Toast.makeText(getApplicationContext(), R.string.CannotParseEBUNames, Toast.LENGTH_LONG).show();
            }
        }

        // Monitor for selection from list
        lvMatches.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (position < MatchingPlayers.size()) {
                    // Copy matching player info to name box
                    String HisName = ChoosePlayer(MatchingPlayers.get(position));

                    // As amn internal change, copy the name to the input box
                    TextView tvInput = (TextView) findViewById(R.id.spUserInput);
                    m_InternalChange = true;
                    tvInput.setText(HisName);
                    m_InternalChange = false;
                }
              }
        });

        // Monitor for changes to name box
        final TextView tvUserInput = (TextView) findViewById(R.id.spUserInput);
        tvUserInput.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                if (m_InternalChange)   return;
                LookForMatches();
            }

        });

        // Have we been here before?
        String MemberName = getIntent().getStringExtra(GLOBALS.ParamPlayerName);
        if (MemberName != null) {
            int MemberNo = getIntent().getIntExtra(GLOBALS.ParamPlayerID, -1);
            int EBUNo = getIntent().getIntExtra(GLOBALS.ParamPlayerEBUNo, -1);

            cClubMemberDetails LastChoice = new cClubMemberDetails(MemberNo, MemberName.trim(), cClubMemberDetails.EBUNoToString(EBUNo));

            if (!LastChoice.getMemberName().isEmpty())
                ChoosePlayer(LastChoice);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.abortmenu, menu);
        return super.onCreateOptionsMenu(menu);

    }

    /**
     * Event Handling for Individual menu item selected
     * Identify single menu item by it's id
     * */
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case R.id.closeapp:
                if ((SystemClock.elapsedRealtime() - LastAbortClick) <= GLOBALS.AbortTime) {
                    Statics.log(getApplicationContext(), "SelectPlayer: User selected ahort");
                    setResult(GLOBALS.RetValCloseApp);
                    finish();
                }
                else {
                    Toast.makeText(getApplicationContext(), getString(R.string.AbortPrompt), Toast.LENGTH_LONG).show();
                    LastAbortClick = SystemClock.elapsedRealtime();
                }
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void ClearMatchList() {
        // Also disables the OK button
        // Now populate the array list with one empty entry
        ArrayList<HashMap<String, String>> nList = new ArrayList<HashMap<String, String>>();
        HashMap<String, String> nLine = new HashMap<String, String>();
        nLine.put(namesListAdapter.NameColumn, "");
        nList.add(nLine);

        namesListAdapter adapter = new namesListAdapter(getApplicationContext(), this, nList);
        lvMatches.setAdapter(adapter);

 //       String[] MatchList = new String[1];
 //       MatchList[0] = "";
 //       ArrayAdapter<String> lvAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, MatchList);
//
//        lvMatches.setAdapter(lvAdapter);
        Statics.enableButton(OKButton, false);
    }
    private void hideVisPanel() {
        setVisPanel("");
    }
    private void setVisPanel(String Text) {
        TextView visPrompt = (TextView) findViewById(R.id.ifVisPrompt);
        LinearLayout visPanel = (LinearLayout) findViewById(R.id.ifVisPanel);
        visPrompt.setText(Text);
        if (Text.isEmpty()) {
            visPrompt.setVisibility(View.GONE);
            visPanel.setVisibility(View.GONE);
        } else {
            visPrompt.setVisibility(View.VISIBLE);
            visPanel.setVisibility(View.VISIBLE);
        }

    }
    private void LookForMatches() {

         // If single digit, look only for club number
        MatchingPlayers.clear();

        final TextView tvUserInput = (TextView) findViewById(R.id.spUserInput);
        String NewInput = tvUserInput.getText().toString().trim();
        final TextView tvPrompt = (TextView)findViewById(R.id.spNamePrompt);

        boolean AllNumeric = Statics.isEntirelyNumeric(NewInput);
        VisitorOnDisplay = false;

        if (NewInput.isEmpty() || (!AllNumeric && NewInput.length()<3)) {
            // Clear the prompt. User instructions will appear as hint if the box is empty
            tvPrompt.setBackgroundColor(GLOBALS.PromptColour);
            tvPrompt.setText("");
            ClearMatchList();
            hideVisPanel();
            return;
        }

        // If it's entirely numeric, check for club number
        // If it's text, search by name
        cClubMemberDetails Match;
        int MatchType = GLOBALS.mtNoMatch;

        if (AllNumeric) {
            int NumberInput = Integer.parseInt(NewInput);

            // Check for club number or EBU number, first in members list then in EBU list
            if (HaveNamesFile) {
                // Search names file by club number
                try {
                    Match = MembershipList.findByNumber(NumberInput);
                    // If we find a match on number, don't search any further
                    MatchingPlayers.add(Match);
                    MatchType = GLOBALS.mtPerfectMatch;
                }
                catch (Exception ex)    {   }
            }
            // Not found in club members list. How about EBU list?
            if (MatchingPlayers.size() < 1 && HaveEBUList) {
                try {

                    Match = EBUList.findByNumber(NumberInput);
                    // If we find a match on number, don't search any further
                    MatchingPlayers.add(Match);
                    MatchType = GLOBALS.mtPerfectMatch;
                }
                catch (Exception ex)    {    }
            }
        } else {
            // Not numeric. Search the list(s)for name matches. There could be several partials
            if (HaveNamesFile) {
                MatchType = MatchingPlayers.findMatchesIn(MembershipList, NewInput);
             }
            if (MatchType == GLOBALS.mtNoMatch && HaveEBUList)
                MatchType = MatchingPlayers.findMatchesIn(EBUList, NewInput);

        }

        switch (MatchType){
            case GLOBALS.mtPerfectMatch: {
                ChoosePlayer(Match = MatchingPlayers.get(0));

            }
            break;

            case GLOBALS.mtAmbiguousMatch: {
                // Populate our ListView with possible matches
                String[] MatchList = MatchingPlayers.toStringArray();
                int nMatches = MatchingPlayers.size();

                ArrayList<HashMap<String, String>> nList = new ArrayList<HashMap<String, String>>();

                for (int n=0; n<nMatches; ++n) {
                    HashMap<String, String> nLine = new HashMap<String, String>();
                    nLine.put(namesListAdapter.NameColumn, MatchList[n]);
                    nList.add(nLine);
                }
                namesListAdapter adapter = new namesListAdapter(getApplicationContext(), this, nList);
                lvMatches.setAdapter(adapter);

 //               ArrayAdapter<String> lvAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, MatchList);
//

                String Prompt = (nMatches == 1) ? getString(R.string.OnePlayerMatch)
                                                : Integer.toString(nMatches) + " " + getString(R.string.MultiplePlayerMatches);
                tvPrompt.setText(Prompt);
                tvPrompt.setBackgroundColor(GLOBALS.ExactMatchColour);

 //               lvMatches.setAdapter(lvAdapter);
                Statics.enableButton(OKButton, false);
            }
            break;

            default:    {
                // No matches
                tvPrompt.setText(getString(R.string.NoPlayerMatches));
                tvPrompt.setBackgroundColor(GLOBALS.NoMatchColour);
                ClearMatchList();

                // It could be an explicitly typed name. Note that ClearMatchList() will
                // have disabled the OK button
                if (!NewInput.isEmpty() && !AllNumeric) {
                    ChosenPlayer = new cClubMemberDetails(NewInput);
                    Statics.enableButton(OKButton, true);
                    tvPrompt.setText(getString(R.string.NoPlayerMatches));

                    String Prompt=getString(R.string.If) + " \"" + NewInput + "\" " + getString(R.string.isVisitor);
                    setVisPanel(Prompt);
                    VisitorOnDisplay = true;
                 }
            }
        }
    }

    private String ChoosePlayer(cClubMemberDetails TheOne) {
        ChosenPlayer = TheOne;
        String EBUNo = ChosenPlayer.getEBUNumber().trim();
        String EBUString;
        String DetailsString;

        if (EBUNo.isEmpty())
            EBUString = "";
        else
            EBUString = " (" + EBUNo + ")";

        if (ChosenPlayer.getClubNumber() > 0) {
            // We have found a matching club member
            DetailsString = Integer.toString(ChosenPlayer.getClubNumber()) + ": " + ChosenPlayer.getMemberName() + EBUString;
        } else {
            // Matching non-member
            DetailsString = ChosenPlayer.getMemberName()+ EBUString;
        }

        final TextView tvPrompt = (TextView)findViewById(R.id.spNamePrompt);
        Statics.setTextViewHTML(getApplicationContext(), tvPrompt, DetailsString);
//        tvPrompt.setText(DetailsString);
        tvPrompt.setBackgroundColor(GLOBALS.ExactMatchColour);
        VisitorOnDisplay = false;
        Statics.enableButton(OKButton, true);
        return ChosenPlayer.getMemberName();

    }

    public void ClearClicked(View callingView) {
        final TextView tvInput = (TextView)findViewById(R.id.spUserInput);
        tvInput.setText("");
        ClearMatchList();
    }
    public void PromptClicked(View callingView) {
//        if (VisitorOnDisplay)   OKClicked(callingView);
    }
    public void OKClicked(View callingView) {
        if (ChosenPlayer != null) {
            Statics.log(getApplicationContext(), "OK clicked. Returning player details " + ChosenPlayer.toString());
            Intent results = new Intent();

            results.putExtra(GLOBALS.ParamPlayerID, ChosenPlayer.getClubNumber());
            results.putExtra(GLOBALS.ParamPlayerName, ChosenPlayer.getMemberName());
            results.putExtra(GLOBALS.ParamPlayerEBUNo, ChosenPlayer.getEBUNumber());
            setResult(GLOBALS.RetValNormal, results);
            // STAW
            Statics.log(getApplicationContext(), "Finish");
            finish();
        }
    }

    @Override
    public void onBackPressed() {
        setResult(GLOBALS.RetValGoBack);
        // STAW
        Statics.log(getApplicationContext(), "Back was pressed");
        finish();
    }
}

Reply via email to