I know this is a question already asked but I am having difficulty understanding what is wrong with my code as I have not used any timers, AsyncTasks or other handlers. I am using Volley to make requests to my web service that's it. The app runs on all emulators but once I try to run it on a device I get this error
E/AndroidRuntime: FATAL EXCEPTION: AcquireTokenRequestHandlerThread
Process: com.microsoft.graph.helpdesk, PID: 18915
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7146)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1033)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4971)
at android.view.View.invalidateInternal(View.java:12704)
at android.view.View.invalidate(View.java:12668)
at android.view.View.setFlags(View.java:10690)
at android.view.View.setVisibility(View.java:7136)
at com.microsoft.graph.helpdesk.SignInActivity.onSuccess(SignInActivity.java:73)
at com.microsoft.graph.helpdesk.SignInActivity.onSuccess(SignInActivity.java:35)
at com.microsoft.graph.auth.AuthenticationManager$2.onSuccess(AuthenticationManager.java:118)
at com.microsoft.graph.auth.AuthenticationManager$2.onSuccess(AuthenticationManager.java:115)
at com.microsoft.aad.adal.AcquireTokenRequest$CallbackHandler$2.run(AcquireTokenRequest.java:904)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.os.HandlerThread.run(HandlerThread.java:61)
The app starts and allows me to log in but then crashes immediately with the error above.
This is the code for my sign in activity:
public class SignInActivity
extends BaseActivity
implements AuthenticationCallback<AuthenticationResult> {
private FirebaseAnalytics mFirebaseAnalytics;
@InjectView(layout_diagnostics)
protected View mDiagnosticsLayout;
@InjectView(view_diagnosticsdata)
protected TextView mDiagnosticsTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(activity_signin);
onSignInO365Clicked();
setTitle(R.string.app_name);
// Obtain the FirebaseAnalytics instance.
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
ButterKnife.inject(this);
}
@OnClick(o365_signin)
public void onSignInO365Clicked() {
try {
authenticate();
} catch (IllegalArgumentException e) {
warnBadClient();
}
}
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
// reset anything that may have gone wrong...
mDiagnosticsLayout.setVisibility(INVISIBLE);
mDiagnosticsTxt.setText("");
// get rid of this Activity so that users can't 'back' into it
finish();
// save our auth token to use later
SharedPrefsUtil.persistAuthToken(authenticationResult);
// get the user display name
final String userDisplayableId =
authenticationResult
.getUserInfo()
.getDisplayableId();
// get the index of their '@' in the name (to determine domain)
final int at = userDisplayableId.indexOf("@");
// parse-out the tenant
final String tenant = userDisplayableId.substring(at + 1);
SharedPrefsUtil.persistUserTenant(tenant);
SharedPrefsUtil.persistUserID(authenticationResult);
// go to our main activity
start();
}
@Override
public void onError(Exception e) {
e.printStackTrace();
//Show the localized message supplied with the exception or
//or a default message from the string resources if a
//localized message cannot be obtained
String msg;
if (null == (msg = e.getLocalizedMessage())) {
msg = getString(sign_in_err);
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
} else {
mDiagnosticsTxt.setText(msg);
mDiagnosticsLayout.setVisibility(VISIBLE);
}
}
private void warnBadClient() {
Toast.makeText(this,
warning_client_id_redirect_uri_incorrect,
Toast.LENGTH_LONG)
.show();
}
private void authenticate() throws IllegalArgumentException {
validateOrganizationArgs();
mAuthenticationManager.connect(this);
}
private void validateOrganizationArgs() throws IllegalArgumentException {
UUID.fromString(ServiceConstants.CLIENT_ID);
URI.create(ServiceConstants.REDIRECT_URI);
}
private void start() {
Intent appLaunch = new Intent(this, MainActivity.class);
startActivity(appLaunch);
}
}
and also for the activity I am trying to view:
public class MainActivity extends AzureAppCompatActivity {
// Instantiate the Firebase Analytics
private FirebaseAnalytics mFirebaseAnalytics;
private TextView txtRequest;
// Instantiate the RequestQueue.
private RequestQueue mQueue;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_myTickets:
//Fragment code
setTitle("My Tickets");
MyTicketFragment mtf = new MyTicketFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content, mtf, "FragmentName");
fragmentTransaction.commit();
return true;
case R.id.navigation_closed:
//Fragment code
setTitle("Closed Tickets");
ClosedFragment cf = new ClosedFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction();
fragmentTransaction2.replace(R.id.content, cf, "FragmentName");
fragmentTransaction2.commit();
return true;
case R.id.navigation_unassigned:
//Fragment code
setTitle("Unassigned Tickets");
UnassignedFragment uf = new UnassignedFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction3 = getSupportFragmentManager().beginTransaction();
fragmentTransaction3.replace(R.id.content, uf, "FragmentName");
fragmentTransaction3.commit();
return true;
case R.id.navigation_over10days:
//Fragment code
setTitle("Tickets over 10 days");
Over10DayFragment of = new Over10DayFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction4 = getSupportFragmentManager().beginTransaction();
fragmentTransaction4.replace(R.id.content, of, "FragmentName");
fragmentTransaction4.commit();
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
if (savedInstanceState == null) {
navigation.getMenu().performIdentifierAction(R.id.navigation_myTickets, 0);
}
}
@Override
protected AzureADModule getAzureADModule() {
AzureADModule.Builder builder = new AzureADModule.Builder(this);
builder.validateAuthority(true)
.authenticationResourceId(ServiceConstants.AUTHENTICATION_RESOURCE_ID)
.authorityUrl(ServiceConstants.AUTHORITY_URL)
.redirectUri(ServiceConstants.REDIRECT_URI)
.clientId(ServiceConstants.CLIENT_ID);
return builder.build();
}
@Override
protected Object[] getModules() {
return new Object[]{new AzureModule()};
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.snippet_list_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.AddTicket:
Intent AddTicketIntent = new Intent(MainActivity.this,
AddTicket.class);
startActivity(AddTicketIntent);
return true;
case R.id.disconnect:
//SignOut Needs to go here
// drop the application shared preferences to clear any old auth tokens
getSharedPreferences(AppModule.PREFS, Context.MODE_PRIVATE)
.edit() // get the editor
.clear() // clear it
.apply(); // asynchronously apply
mAuthenticationManager.disconnect();
Intent login = new Intent(this, SignInActivity.class);
login.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(login);
default:
return super.onOptionsItemSelected(item);
}
}
}
I'm not sure if they are helpful in finding an answer or if the fragments the activity is creating are the problem but I can't see how. Also I have gotten the app to work on a mobile twice before but immediately crashes once I open it again. Many thanks for your help. -Adam.