I searched for a solution for more than a week to my situation and I have not found the solution.
I have a main activity and use Fragments. In my project I added a SPLASH, but as soon as it finishes executing the program opens twice.
Here's the code:
MainActivity.java
package org.jotadev.nh;
import org.jotadev.nh.adapter.TabsPagerAdapter;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Buscar", "Historial", "Favoritos", "Planes" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//activity_main
Log.i("MainActivity", "entró en onCreate");
// Initialization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
Log.i("MainActivity", "entró en onPageSelected");
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
//menu
#Override
public boolean onCreateOptionsMenu(Menu menu){
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
public void lanzarAbout(){
Intent intent = new Intent(this, About.class);
startActivity(intent);
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case R.id.action_about:
lanzarAbout();
break;
case R.id.action_settings:
Intent intent = new Intent(this, Preferences.class);
startActivity(intent);
break;
case R.id.action_show_preferences:
Log.i("Action", "mostrando ajustes");
mostrarPreferencias();
break;
case R.id.action_exit:
finish();
}
return false;
}
private void mostrarPreferencias() {
SharedPreferences pref = getSharedPreferences("org.jotadev.nh_preferences",MODE_PRIVATE);
String s = "pantalla completa: " + pref.getBoolean("PantallaCompleta", false)
+ ", tamaño letra: " + pref.getString("Tamanoletra", "?")
+ ", color Fondo: " + pref.getString("ColorFondo", "?")
+ "En Desarrollo: " + pref.getBoolean("Endesarrollo", true);
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
activity_main.xml
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
AndroidManifiest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jotadev.nh"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:debuggable="true"
>
<!-- Splash -->
<activity
android:name=".Splash"
android:label="#string/app_name"
android:screenOrientation="landscape"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="org.jotadev.nh.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:label="#string/app_name"
android:name=".About">
</activity>
<activity android:label="#string/title_settings"
android:name=".Preferences">
</activity>
</application>
</manifest>
I appreciate your help. Or please share an useful link. It is very dificult to find answers.
Related
I have a view (activity_SingIn) and its Presenter now in the onCreate method gives me the following error related to "singInPresenter.singInUser(v);"
2022-09-18 17:30:51.785 3811-3811/com.example.Natour21 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.Natour21, PID: 3811
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.NaTour21.Presenter.Activity.SingInPresenter.singInUser(android.view.View)' on a null object reference
at com.example.NaTour21.View.Activity.activity_singIn$2.onClick(activity_singIn.java:61)
package com.example.NaTour21.Presenter.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Handler;
import android.view.View;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.example.NaTour21.View.Activity.activity_Home;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import android.widget.ProgressBar;
public class SingInPresenter extends AppCompatActivity {
private EditText EmailLgn,PasswordLgn;
String[] messaggio = {"Campi vuoti inserili"};
private ProgressBar progressBar;
public void singInUser(View view) {
String email = EmailLgn.getText().toString();
String password = PasswordLgn.getText().toString();
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
progressBar.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
home();
}
}, 3000);
} else {
String error;
try{
throw task.getException();
}catch(Exception e){
error ="Errore di accesso utente";
}
Snackbar snackbar = Snackbar.make(view,error,Snackbar.LENGTH_SHORT);
snackbar.setBackgroundTint(Color.WHITE);
snackbar.setTextColor(Color.BLACK);
snackbar.show();
}
}
});
}
public void home() {
Intent intent = new Intent(this, activity_Home.class);
startActivity(intent);
finish();
}
#Override
public void onStart() {
super.onStart();
FirebaseUser UtenteCorrente = FirebaseAuth.getInstance().getCurrentUser();
if(UtenteCorrente != null){
home();
}
}
}
package com.example.NaTour21.View.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import com.example.NaTour21.Presenter.Activity.SingInPresenter;
import com.example.NaTour21.R;
import com.google.android.material.snackbar.Snackbar;
import android.view.View;
import android.widget.ProgressBar;
public class activity_singIn extends AppCompatActivity{
private EditText EmailLgn,PasswordLgn;
private Button loginLgn;
private Button registratiLgn;
private SingInPresenter singInPresenter;
private ProgressBar progressbar;
String[] messaggio = {"Campi vuoti inserirli",
"Accesso effettuato con successo",
"Formato email non valido",
"La password deve avere minimo 6 caratteri"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_singin);
getSupportActionBar().hide();
initializeComponent();
registratiLgn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(activity_singIn.this, activity_singUp.class);
startActivity(intent);
}
});
loginLgn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String email = EmailLgn.getText().toString();
String password = PasswordLgn.getText().toString();
if (email.isEmpty() || password.isEmpty()) {
Snackbar snackbar = Snackbar.make(v, messaggio[0], Snackbar.LENGTH_SHORT);
snackbar.setBackgroundTint(Color.WHITE);
snackbar.setTextColor(Color.BLACK);
snackbar.show();
} else if (!isValidEmail(email)) {
Snackbar snackbar = Snackbar.make(v, messaggio[2], Snackbar.LENGTH_SHORT);
snackbar.setBackgroundTint(Color.WHITE);
snackbar.setTextColor(Color.BLACK);
snackbar.show();
}else if (!(password.length() < 6)) {
Snackbar snackbar = Snackbar.make(v, messaggio[3], Snackbar.LENGTH_SHORT);
snackbar.setBackgroundTint(Color.WHITE);
snackbar.setTextColor(Color.BLACK);
snackbar.show();
}else{
Snackbar snackbar = Snackbar.make(v, messaggio[1], Snackbar.LENGTH_SHORT);
snackbar.setBackgroundTint(Color.WHITE);
snackbar.setTextColor(Color.BLACK);
snackbar.show();
singInPresenter.singInUser(v); //??????
}
}
});
}
private boolean isValidEmail(String email) {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
private void initializeComponent() {
registratiLgn = findViewById(R.id.btRegistratiLgn);
EmailLgn = findViewById(R.id.tilEmailLgn);
PasswordLgn = findViewById(R.id.tilPasswordLgn);
loginLgn = findViewById(R.id.btLoginLgn);
progressbar = findViewById(R.id.progressbarLgn);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/sfondo"
android:id="#+id/activity_singin"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="336dp"
android:layout_height="196dp"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/txtNomeApp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:clickable="true"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:text="NaTour21"
android:textColor="#color/white"
android:textSize="60sp" />
</LinearLayout>
<LinearLayout
android:layout_width="361dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp">
<EditText
android:id="#+id/tilEmailLgn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="25dp"
android:drawableLeft="#drawable/ic_email"
android:ems="10"
android:hint="Email"
android:textColor="#color/white"
android:inputType="textEmailAddress"
app:backgroundTint="#color/white"/>
<EditText
android:id="#+id/tilPasswordLgn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:drawableLeft="#drawable/ic_password"
android:drawableRight="#drawable/ic_occhio"
android:ems="10"
android:hint="Password"
android:inputType="textPassword"
android:textColor="#color/white"
app:backgroundTint="#color/white"/>
<ProgressBar
android:id="#+id/progressbarLgn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
app:layout_constraintTop_toBottomOf="#id/containerComponents" />
<Button
android:id="#+id/btLoginLgn"
android:layout_width="232dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="30dp"
android:background="#drawable/button_login"
android:text="Login"
android:textColor="#color/white"
android:textSize="16sp"
android:textStyle="bold"/>
<Button
android:id="#+id/btRegistratiLgn"
android:layout_width="232dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:background="#drawable/button_registrati"
android:text="Registrati"
android:textColor="#color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
Dear #Fabiola Salomone if you are trying to use MVP because you said you have a presenter then i am afraid you are not doing it correctly at least according to what i know about MVP please study about it that will be better instead of me or anyone else telling you the code directly because you will not know how it works that way , for a head start you need to make an interface and presenter and inside that presenter you will make three more interfaces View Model and Presenter again and then you will initialize that presenter inside you main activity , here you are extending you presenter with appcompactActivty that itself is wrong a lot about your code is wrong its not MVP by any means so i don't how can i help you exactly with this apart from what i just said, Once you know how MVP work then me or other users can surely help you with this, Still if you need any clearance you can ask :)
Following my previous question about messaging on javafx,
I want to notify user when message arrive.
Recently I use NotificationCompat.
When user touch the notification from notification bar, it must directly open related view (DirectMessageView).
I’ve configure an activity class (NotificationActivy extends Activity) on receive tag in androidmanifest.xml and call DirectMessageView and it's presenter on method "onCreate".
when user touch message on notification, it won’t display DirectMessageView, but the method inside presenter is called, and the view is not visible. Perhaps it’s my wrong implementation, please help
Here are classes I have created
Class SKSAplication that extends MobileAplication
public class SKSApplication extends MobileApplication{
private static SKSApplication instance;
public static final String DIRECT_MESSAGE_VIEW = "DIRECT_MESSAGE_VIEW";
public static final String GROUP_MESSAGE_VIEW = "GROUP_MESSAGE_VIEW";
private ViewRefresh activeView;
public SKSApplication() {
instance = this;
}
public static SKSApplication getInstance() {
return instance;
}
#Override
public void init() {
addViewFactory(HOME_VIEW, () -> {
HomeView homeView = new HomeView();
homePresenter = (HomePresenter) homeView.getPresenter();
return (View) homeView.getView();
});
addViewFactory(DIRECT_MESSAGE_VIEW, () -> {
DirectMessageView directMessageView = new DirectMessageView();
return (View) directMessageView.getView();
});
addViewFactory(GROUP_MESSAGE_VIEW, () -> {
GroupMessageView groupMessageView = new GroupMessageView();
return (View) groupMessageView.getView();
});
public void doRefreshMessageUI(Object objectModel) {
System.out.println("SKSApplication.doRefreshMessageUI " + getView().getName());
if (getActiveView() != null)
getActiveView().doRefresh(objectModel);
}
public ViewRefresh getActiveView() {
return activeView;
}
public void setActiveView(ViewRefresh activeView) {
this.activeView = activeView;
}
}
Class MyGCMListenerService
public class MyGCMListenerService extends GcmListenerService {
private final String NOTIFICATION_TAG = "NotificationExample";
public MyGCMListenerService() {
}
#Override
public void onMessageReceived(String from, Bundle data) {
String varMessage = data.getString("message");
try {
JSONObject json = new JSONObject(varMessage);
String messageContent = getStringFromJSON(json, "message");
Integer senderId = getIntegerFromJSON(json, "senderId");
String senderName = getStringFromJSON(json, "senderName");
String comId = getStringFromJSON(json, "communityId");
String salesGroup = getStringFromJSON(json, "salesGroup");
Integer messageType = getIntegerFromJSON(json, "type");
doViewNotification(messageType, senderName, salesGroup);
SKSApplication.getInstance().doRefreshMessageUI(messageContent,senderId,senderName,comId );
} catch (JSONException e) {
e.printStackTrace();
}
}
private void doViewNotification(Integer messageType, String senderName, String salesGroup) {
StringBuilder msg = new StringBuilder()
.append("Message from ")
.append(senderName)
.append(" #").append(salesGroup);
Intent resultIntent = new Intent(FXActivity.getInstance(), NotificationActivity.class);
resultIntent.putExtra(Constants.EXTRA_INTENT.MESSAGE_TYPE.getValue(), messageType);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
FXActivity.getInstance(),
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
long[] v = {500, 1000};
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSound(uri)
.setSmallIcon(FXActivity.getInstance().getApplicationInfo().icon)
.setContentTitle(getApplicationName(FXActivity.getInstance().getApplicationContext()))
.setVibrate(v)
.setContentText(msg.toString())
.setPriority(Notification.PRIORITY_DEFAULT)
.setNumber(100)
.setWhen(System.currentTimeMillis())
.setContentIntent(resultPendingIntent)
.setAutoCancel(true)
.addAction(FXActivity.getInstance().getApplicationInfo().icon, "Action", null);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
notificationManager.notify(NOTIFICATION_TAG, 0, builder.build());
} else {
notificationManager.notify(NOTIFICATION_TAG.hashCode(), builder.build());
}
}
}
layout xml file (directmessage.fxml)
<View xmlns:fx="http://javafx.com/fxml/1" fx:id="directMessageView" prefHeight="600.0" prefWidth="400.0"
xmlns="http://javafx.com/javafx/8.0.40"
fx:controller="com.tenma.mobile.message.directmessage.DirectMessagePresenter">
</View>
Class DirectMessageView
public class DirectMessageView extends FXMLView {
}
Class DirectMessagePresenter
public class DirectMessagePresenter implements Initializable, ViewRefresh{
#Override
public void initialize(URL location, ResourceBundle resources) {
{
directMessageView.showingProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
SKSApplication.getInstance().setActiveView(this);
doViewMessage();
}
});
}
private void doViewMessage() {
listMessage.getItems().clear();
MessageStoryHelper hlp = new MessageStoryHelper();
List<MessageModel> ls = null;
try {
ls = hlp.getMessages(Constants.MESSAGE_TYPE.DIRECT);
if (ls != null && ls.size() != 0)
for (MessageModel m :ls)
listMessage.add(m);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
androidmanifest
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tenma.mobile"
android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<permission android:name="com.tenma.mobile.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.tenma.mobile.permission.C2D_MESSAGE"/>
<application android:label="MobileSales" android:name="android.support.multidex.MultiDexApplication"
android:icon="#mipmap/ic_launcher">
<activity android:name="javafxports.android.FXActivity" android:label="MobileSales"
android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.tenma.mobile.SKSApplication"/>
<meta-data android:name="debug.port" android:value="0"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="com.tenma.mobile.common.NotificationActivity"
android:parentActivityName="javafxports.android.FXActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="javafxports.android.FXActivity"/>
</activity>
<!--start-->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<!-- for Gingerbread GSF backward compat -->
<!--<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>-->
<category android:name="com.tenma.mobile"/>
</intent-filter>
</receiver>
<!--end-->
<service
android:name="com.tenma.mobile.common.MyGCMListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
</intent-filter>
</service>
</application>
</manifest>
Class NotificationActivity extends Activity
public class NotificationActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent launchIntent = getIntent();
it working, but no view is visible
SKSApplication.getInstance().switchView(SKSApplication.DIRECT_MESSAGE_VIEW);
perhaps using this line below, but how to set Gluon View setContentView?
or retreive view ID and setContentView?
DirectMessageView directMessageView = new DirectMessageView();
Parent v = directMessageView.getView();
FXActivity.getInstance().setContentView(?????????);
}
}
Any help would be appreciated
Thank you in advance
Assuming you have the application running, this works for me:
Once you send the message back to the View, you need to close the notification activity by calling finish():
public class NotificationActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((SKSApplication) MobileApplication.getInstance()).doRefreshMessageUI("Hi from NotificationActivity");
finish();
}
}
Note you don't need to create a singleton instance of SKSApplication, you can retrieve an instance of it at any time by calling MobileApplication.getInstance().
Passing the message to the view can be done in SKSApplication by using Platform.runLater(), since you are not running on the JavaFX thread.
And to retrieve the corresponding view, just switch to that view:
public void doRefreshMessageUI(String msg) {
Platform.runLater(() -> {
messagesView.messageProperty().set(msg);
switchView(DIRECT_MESSAGE_VIEW);
});
}
providing the view has a StringProperty, that is bound to any of its controls text property.
private StringProperty message = new SimpleStringProperty();
public StringProperty messageProperty() {
return message;
}
I am following the quick start app for Android ( https://developers.google.com/identity/toolkit/android/quickstart ) and is giving the following error:
FATAL EXCEPTION: main
Process: com.google.identitytoolkit.demo, PID: 12813
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/facebook/Session;
(...)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.facebook.Session" on path: DexPathList[[zip file "/data/app/com.google.identitytoolkit.demo-1/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]
(...)
Suppressed: java.lang.ClassNotFoundException: com.facebook.Session
(...)
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
Here is my code:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.identitytoolkit.demo"
android:versionCode="1"
android:versionName="1.0.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.google.identitytoolkit.demo.GitkitDemo"
android:label="#string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="gitkit"
android:scheme="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
</intent-filter>
</activity>
<activity android:name="com.facebook.LoginActivity"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<meta-data
android:name="identitytoolkit.show_providers"
android:value="Google, Yahoo, Facebook" />
<meta-data
android:name="identitytoolkit.use_google_plus"
android:value="false" />
<meta-data
android:name="identitytoolkit.api_key"
android:value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<meta-data
android:name="identitytoolkit.server_client_id"
android:value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<meta-data
android:name="identitytoolkit.server_widget_url"
android:value="INSERT_YOUR_SERVER_WIDGET_URL" />
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/fb_app_id"/>
</application>
GitkitDemo.java
package com.google.identitytoolkit.demo;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.facebook.appevents.AppEventsLogger;
import com.facebook.FacebookSdk;
import com.google.identitytoolkit.GitkitClient;
import com.google.identitytoolkit.GitkitUser;
import com.google.identitytoolkit.IdToken;
import java.io.IOException;
public class GitkitDemo extends Activity implements OnClickListener {
private GitkitClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
#Override
public void onSignIn(IdToken idToken, GitkitUser user) {
showProfilePage(idToken, user);
}
#Override
public void onSignInFailed() {
Toast.makeText(GitkitDemo.this, "Sign in failed", Toast.LENGTH_LONG).show();
}
}).build();
showSignInPage();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (!client.handleActivityResult(requestCode, resultCode, intent)) {
super.onActivityResult(requestCode, resultCode, intent);
}
}
#Override
protected void onNewIntent(Intent intent) {
if (!client.handleIntent(intent)) {
super.onNewIntent(intent);
}
}
private void showSignInPage() {
setContentView(R.layout.welcome);
Button button = (Button) findViewById(R.id.sign_in);
button.setOnClickListener(this);
}
private void showProfilePage(IdToken idToken, GitkitUser user) {
setContentView(R.layout.profile);
showAccount(user);
findViewById(R.id.sign_out).setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.sign_in) {
client.startSignIn();
} else if (v.getId() == R.id.sign_out) {
showSignInPage();
}
}
private void showAccount(GitkitUser user) {
((TextView) findViewById(R.id.account_email)).setText(user.getEmail());
if (user.getDisplayName() != null) {
((TextView) findViewById(R.id.account_name)).setText(user.getDisplayName());
}
if (user.getPhotoUrl() != null) {
final ImageView pictureView = (ImageView) findViewById(R.id.account_picture);
new AsyncTask<String, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(String... arg) {
try {
byte[] result = HttpUtils.get(arg[0]);
return BitmapFactory.decodeByteArray(result, 0, result.length);
} catch (IOException e) {
return null;
}
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null) {
pictureView.setImageBitmap(bitmap);
}
}
}.execute(user.getPhotoUrl());
}
}
}
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
}
}
repositories {
mavenCentral()
flatDir {
dirs 'libs'
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion '19.1.0'
defaultConfig {
minSdkVersion 15
targetSdkVersion 19
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
res.srcDirs = ['res']
}
}
}
dependencies {
compile 'com.google.android.gms:play-services:6.1.11'
compile 'com.facebook.android:facebook-android-sdk:4.6.0'
compile(name: 'identitytoolkit-api11', ext: 'aar')
compile(name: 'identitytoolkit_fb', ext: 'jar')
}
This is due to Facebook changed its SDK for v4. Facebook Session Class is no longer there. This library 'identitytoolkit_fb' only works for Facebook Android SDK v3. I guess you probably would like to download the v4 version library from Github https://github.com/googlesamples/identity-toolkit-android/blob/master/plugins/identitytoolkit_fbv4.jar?raw=true.
Use that one to replace the current "identitytoolkit_fb.jar". That will work.
I have a strange issue with my Fragment, I get no errors at runtime (I'm using Android Studio v8.7 and the Gradle compiles just fine) but when my app runs on my phone it's now showing up, it looks like an empty Activity.
Activity.class
package android.bignerdranch.com.criminalintent;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.view.MenuItem;
public class CrimeActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crime);
// These are Fragments from the app.v4 package, it's needed to make the app compatible with API < 11
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if(fragment == null) {
fragment = new Fragment();
fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Fragment.class
package android.bignerdranch.com.criminalintent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
public class CrimeFragment extends Fragment {
private Crime mCrime;
private EditText mTitleField;
private Button mDateButton;
private CheckBox mSolvedCheckbox;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_crime, container, false);
mTitleField = (EditText)v.findViewById(R.id.crime_title);
mTitleField.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mCrime.setTitle(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
mDateButton = (Button)v.findViewById(R.id.crime_date);
mDateButton.setText(mCrime.getDate().toString());
mDateButton.setEnabled(false);
mSolvedCheckbox = (CheckBox)v.findViewById(R.id.crime_solved);
mSolvedCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mCrime.setSolved(isChecked);
}
});
return v;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCrime = new Crime();
}
}
Activity.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/crime_title_label"
style="?android:listSeparatorTextViewStyle" />
<EditText
android:id="#+id/crime_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/crime_title_hint" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/crime_details_label"
style="?android:listSeparatorTextViewStyle" />
<Button
android:id="#+id/crime_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" />
<CheckBox
android:id="#+id/crime_solved"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:text="#string/crime_solved_label" />
</LinearLayout>
Can somebody point me in the right direction and tell me what could solve my issue?
Ok i found the errors, I was instantiating the wrong Fragment.
Instead of
if(fragment == null) {
fragment = new Fragment();
fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit();
It should be
if(fragment == null) {
fragment = new CrimeFragment();
fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit();
I'm attempting to create a dynamic UI using the support.v4 library to insert fragments into a framelayout I have defined for my main activity.
Here is my activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:baselineAligned="false" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="vertical" >
<Button
android:id="#+id/button_report"
android:text="#string/button_report"
android:textSize="22sp"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="#+id/button_pay"
android:text="#string/button_pay"
android:textSize="22sp"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="#+id/button_contact"
android:text="#string/button_contact"
android:textSize="22sp"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<FrameLayout
android:id="#+id/container"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="2" />
</LinearLayout>
And here is the MainActivity.java:
package com.example.Test;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends FragmentActivity
{
// Declare button variables
protected Button btnReport;
protected Button btnPay;
protected Button btnContact;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Assign buttons
btnReport = (Button)findViewById(R.id.button_report);
btnPay = (Button)findViewById(R.id.button_pay);
btnContact = (Button)findViewById(R.id.button_contact);
// Import fragments
final Fragment fragmentPhone = new FragmentPhone();
final Fragment fragmentReport = new FragmentReport();
final Fragment fragmentPay = new FragmentPay();
final android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
// Check for existing fragment, if none then add FragmentPhone.class
if (savedInstanceState != null) return;
else {
ft.add(R.id.container, fragmentPhone);
ft.commit();
}
// "Report" button
btnReport.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ft.replace(R.id.container, fragmentReport); //Replace the details_container
ft.addToBackStack(null); // Add transaction to back stack
ft.commit(); // Commit the transaction
}
});
// "Pay" button
btnPay.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ft.replace(R.id.container, fragmentPay);
ft.addToBackStack(null);
ft.commit();
}
});
// "Contact" button
btnContact.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ft.replace(R.id.container, fragmentPhone);
ft.addToBackStack(null);
ft.commit();
}
});
}
}
And here is my FragmentPhone class:
package com.example.Test;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentPhone extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_phone, container, false);
}
}
When I launch the app, the xml loads correctly and the framelayout gets filled with fragmentPhone, but pressing any of the buttons creates an "app has stopped unexpectedly" dialogue and prompts me to force close.
Any ideas or suggestions will be greatly appreciated. Thanks!
I ended up re-getting and re-declaring FragmentManager and FragmentTransaction within each onClickListener. I also removed "addToBackStack" as I decided it was unneeded. Here is my current, working code:
// "Report" button
btnReport.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
android.support.v4.app.FragmentManager fragmentManager1 = getSupportFragmentManager();
FragmentTransaction fragmentTransaction1 = fragmentManager1.beginTransaction();
fragmentTransaction1.replace(R.id.container, fragmentReport);
fragmentTransaction1.commit();
}
});
(untested)
make ft a global field so it's available in the click handler.