I'm trying to use the Android Skype SDK sample code in my project and I'm getting an error saying Could not execute method OnClick. SkypeActivity.class cannot be cast to S4BDemoApplication.class
.
My guess is this part of code in my S4BDemoApplication.class:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
The line MultiDex.install(this)
might be causing the issue as I haven't included any dexOptions
in my gradle.
I actually did have them but when I try to run it, I get an error saying
no such property preDexLibraries So I had to comment them out in my gradle and it worked fine.
Do you think this is the reason for the error? Is there a workaround for this?
My gradle file
apply plugin: 'com.android.application'
def ROOTDIR = file("..").absolutePath
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
useLibrary 'org.apache.http.legacy'
defaultConfig {
applicationId "it.moondroid.chatbot"
minSdkVersion 17
targetSdkVersion 23
versionCode 1
versionName "1.0"
multiDexEnabled true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
buildTypes {
debug {
minifyEnabled false
debuggable true
jniDebuggable true
}
release {
debuggable true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/MSFTSIG.RSA'
exclude 'META-INF/BCKEY.DSA'
exclude 'META-INF/BCKEY.SF'
exclude 'META-INF/MSFTSIG.SF'
}
dexOptions {
// preDexLibraries=false
// jumboMode = true
// javaMaxHeapSize "4g"
}
}
configurations {
all*. exclude group: 'com.android.support', module: 'support-v4'
all*. exclude group: 'com.android.support', module: 'support-annotations'
}
productFlavors {
}
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile files('libs/sanmoku-0.0.5.jar')
compile files('libs/joda-time-2.1.jar')
compile(name: "libucmp", ext: 'aar')
compile(name: "platform", ext: 'aar')
compile(name: "injector", ext: 'aar')
compile(name: "SkypeForBusiness", ext: 'aar')
compile(name: "ucmp-enums", ext: 'aar')
compile(name: "TelemetryClient2", ext: 'aar')
compile(name: "TelemetryService", ext: 'aar')
compile(name: "android-database-sqlcipher", ext: 'aar')
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:recyclerview-v7:23.0.1'
compile 'com.android.support:cardview-v7:23.0.1'
compile 'com.android.support:support-v4:23.0.1'
}
Errors:
FATAL EXCEPTION: main Process: it.moondroid.chatbot, PID: 20952 Theme: themes:{default=overlay:system, iconPack:system, fontPkg:system, com.android.systemui=overlay:system, com.android.systemui.navbar=overlay:system} java.lang.IllegalStateException: Could not execute method for android:onClick at android.view.View$DeclaredOnClickListener.onClick(View.java:4458) at android.view.View.performClick(View.java:5204) at android.view.View$PerformClick.run(View.java:21158) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5461) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at android.view.View$DeclaredOnClickListener.onClick(View.java:4453) at android.view.View.performClick(View.java:5204) at android.view.View$PerformClick.run(View.java:21158) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5461) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.ClassCastException: it.moondroid.chatbot.ChatBotApplication cannot be cast to it.moondroid.chatbot.SFBDemoApplication at it.moondroid.chatbot.SkypeActivity.onJoinMeetingButtonClick(SkypeActivity.java:143) at java.lang.reflect.Method.invoke(Native Method) at android.view.View$DeclaredOnClickListener.onClick(View.java:4453) at android.view.View.performClick(View.java:5204) at android.view.View$PerformClick.run(View.java:21158) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5461) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
SkypeActivity.java
package it.moondroid.chatbot;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.TextView;
import com.microsoft.office.sfb.appsdk.AnonymousSession;
import com.microsoft.office.sfb.appsdk.Application;
import com.microsoft.office.sfb.appsdk.ConfigurationManager;
import com.microsoft.office.sfb.appsdk.Conversation;
import com.microsoft.office.sfb.appsdk.DevicesManager;
import com.microsoft.office.sfb.appsdk.Observable;
import com.microsoft.office.sfb.appsdk.SFBException;
import java.net.URI;
/**
* Main Activity of the app.
* The activity provides UI to join the meeting and navigate to the conversations view.
*/
public class SkypeActivity extends AppCompatActivity {
Application application = null;
ConfigurationManager configurationManager = null;
DevicesManager devicesManager = null;
ConversationPropertyChangeListener conversationPropertyChangeListener = null;
Conversation anonymousConversation = null;
AnonymousSession anonymousSession = null;
TextView conversationStateTextView = null;
Button joinMeetingButton = null;
private Intent conversationsIntent = null;
boolean meetingJoined = false;
/**
* Creating the activity initializes the SDK Application instance.
* @param savedInstanceState saved instance.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_skype);
this.application = Application.getInstance(this.getApplication().getApplicationContext());
this.devicesManager = application.getDevicesManager();
this.configurationManager = application.getConfigurationManager();
// This flag will enable certain features that are in preview mode.
// E.g. Audio / Video capability OnPrem topologies.
this.configurationManager.enablePreviewFeatures(true);
// Note that the sample enable video over cellular network. This is not the default.
this.configurationManager.setRequireWiFiForVideo(false);
// Max video channel count needs to be set to view video for more than one participant.
this.configurationManager.setMaxVideoChannelCount(5);
// Get UI elements.
this.conversationStateTextView = (TextView)findViewById(R.id.statusTextViewId);
this.joinMeetingButton = (Button)findViewById(R.id.joinMeetingButtonId);
this.conversationsIntent = new Intent(this,ConversationsActivity.class);
this.updateUiState();
}
@Override
protected void onDestroy() {
this.configurationManager = null;
this.application = null;
super.onDestroy();
}
/**
* Navigate to the conversations list view.
* Note that, the conversations list view is provided only for demonstration purposes.
* For anonymous meeting join it will always have a single conversation after meeting join is
* successful.
* @param view View
*/
public void onConversationsButtonClick(android.view.View view) {
this.navigateToConversationsActivity();
}
/**
* The click handler joins or leaves the meeting based on current state.
*
* @param view View.
*/
public void onJoinMeetingButtonClick(android.view.View view) {
// Hide keyboard
InputMethodHelper.hideSoftKeyBoard(this.getApplication().getApplicationContext(),
view.getWindowToken());
if (meetingJoined) {
// Leave the meeting.
try {
this.anonymousConversation.leave();
this.meetingJoined = false;
this.updateUiState();
} catch (SFBException e) {
e.printStackTrace();
}
} else {
//Join the meeting.
// Get the display name.
final android.widget.TextView displayNameTextView =
(android.widget.TextView) findViewById(R.id.displayNameEditTextId);
// Get the meeting uri
final android.widget.EditText joinMeetingEditText =
(android.widget.EditText) findViewById(R.id.meetingUriEditTextId);
String meetingUriString = joinMeetingEditText.getText().toString();
URI meetingUri = URI.create(meetingUriString);
// Join meeting and monitor conversation state to determine meeting join completion.
try {
// Set the default device to Speaker
//this.devicesManager.setActiveEndpoint(DevicesManager.Endpoint.LOUDSPEAKER);
this.anonymousSession = this.application.joinMeetingAnonymously(
displayNameTextView.getText().toString(), meetingUri);
this.anonymousConversation = this.anonymousSession.getConversation();
SFBDemoApplication application = (SFBDemoApplication)getApplication();
application.setAnonymousConversation(this.anonymousConversation);
// Conversation begins in Idle state. It will move from Idle->Establishing->InLobby/Established
// depending on meeting configuration.
// We will monitor property change notifications for State property.
// Once the conversation is Established, we will move to the next activity.
this.conversationPropertyChangeListener = new ConversationPropertyChangeListener();
this.anonymousConversation.addOnPropertyChangedCallback(this.conversationPropertyChangeListener);
} catch (SFBException e) {
e.printStackTrace();
}
}
}
/**
* Update the UI state.
*/
public void updateUiState() {
if (meetingJoined) {
this.joinMeetingButton.setText(R.string.leave_meeting);
} else {
this.joinMeetingButton.setText(R.string.join_meeting);
//conversationStateTextView.setText("");
}
}
/**
* Navigate to the Conversations activity.
*/
private void navigateToConversationsActivity() {
startActivity(this.conversationsIntent);
}
/**
* Determines meeting join state based on conversations state.
*/
public void updateConversationState() {
Conversation.State state = this.anonymousConversation.getState();
conversationStateTextView.setText(state.toString());
switch (state) {
case ESTABLISHED:
this.meetingJoined = true;
break;
case IDLE:
conversationStateTextView.setText("");
this.meetingJoined = false;
if (this.anonymousConversation != null) {
this.anonymousConversation.removeOnPropertyChangedCallback(this.conversationPropertyChangeListener);
this.anonymousConversation = null;
}
break;
default:
}
// Refresh the UI
this.updateUiState();
if (meetingJoined) {
this.navigateToConversationsActivity();
}
}
/**
* Helper method to show alerts.
* @param message Alert message.
*/
private void showAlert(String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message);
builder.show();
}
/**
* Callback implementation for listening for conversation property changes.
*/
class ConversationPropertyChangeListener extends Observable.OnPropertyChangedCallback {
/**
* onProperty changed will be called by the Observable instance on a property change.
*
* @param sender Observable instance.
* @param propertyId property that has changed.
*/
@Override
public void onPropertyChanged(Observable sender, int propertyId) {
if (propertyId == Conversation.STATE_PROPERTY_ID) {
updateConversationState();
}
}
}
}
SFBDemoApplication.java
package it.moondroid.chatbot;
import android.content.Context;
import android.support.multidex.MultiDex;
import android.support.multidex.MultiDexApplication;
import com.microsoft.office.sfb.appsdk.Conversation;
/**
* Demo Application class
*/
public class SFBDemoApplication extends MultiDexApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
/**
* Saving the anonymous conversation to be shared across activities.
*/
private Conversation anonymousConversation = null;
/**
* Save the anonymous conversation.
* @param conversation
*/
public void setAnonymousConversation(Conversation conversation) {
this.anonymousConversation = conversation;
}
/**
* Get the anonymous conversation.
* @return Conversation conversation.
*/
public Conversation getAnonymousConversation() {
return this.anonymousConversation;
}
}