Unable to instantiate Sinch client- NullPointerException Error

北慕城南 提交于 2020-01-07 02:37:07

问题


I am using a Sinch tutorial(https://github.com/sinch/android-app-app-calling-headers) as a framework for an app I am trying to develop. The following is the login class from the tutorial which I have updated and been successful in initializing the sinch client.

public class LoginActivity extends BaseActivity implements SinchService.StartFailedListener {

private Button mLoginButton;
private EditText mLoginName;
private static final int REQUEST_PERMISSION = 10;

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

    mLoginName = (EditText) findViewById(R.id.loginName);
    mLoginButton = (Button) findViewById(R.id.loginButton);
    mLoginButton.setEnabled(false);

    requestAppPermissions(new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.ACCESS_FINE_LOCATION}, R.string.msg,  REQUEST_PERMISSION);
    mLoginButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            loginClicked();
        }
    });

}

@Override
public void onPermissionGranted(int requestCode) {

}

@Override
protected void onServiceConnected() {
    mLoginButton.setEnabled(true);
    getSinchServiceInterface().setStartListener(this);
}

@Override
protected void onPause() {
    super.onPause();
}

@Override
public void onStartFailed(SinchError error) {
    Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show();
}

@Override
public void onStarted() {
    openPlaceCallActivity();
}

private void loginClicked() {
    String userName = mLoginName.getText().toString();

    if (userName.isEmpty()) {
        Toast.makeText(this, "Please enter a name", Toast.LENGTH_LONG).show();
        return;
    }

    if (!getSinchServiceInterface().isStarted()) {
        getSinchServiceInterface().startClient(userName);
    } else {
        openPlaceCallActivity();
    }
}

private void openPlaceCallActivity() {
    Intent mainActivity = new Intent(this, PlaceCallActivity.class);
    startActivity(mainActivity);
    }

}

The instantiation of the client occurs in the SinchService Class which is as follows:

 private static final String APP_KEY = "";
private static final String APP_SECRET = "";
private static final String ENVIRONMENT = "sandbox.sinch.com";
public static final String LOCATION = "LOCATION";
public static final String CALL_ID = "CALL_ID";
static final String TAG = SinchService.class.getSimpleName();

private SinchServiceInterface mSinchServiceInterface = new SinchServiceInterface();
private SinchClient mSinchClient;
private String mUserId;

private StartFailedListener mListener;

@Override
public void onCreate() {
    super.onCreate();
}

@Override
public void onDestroy() {
    if (mSinchClient != null && mSinchClient.isStarted()) {
        mSinchClient.terminate();
    }
    super.onDestroy();
}

private void start(String userName) {

    if (mSinchClient == null) {
        mUserId = userName;
        mSinchClient = Sinch.getSinchClientBuilder().context(getApplicationContext()).userId(userName)
                .applicationKey(APP_KEY)
                .applicationSecret(APP_SECRET)
                .environmentHost(ENVIRONMENT).build();

        mSinchClient.setSupportCalling(true);
        mSinchClient.startListeningOnActiveConnection();

        mSinchClient.addSinchClientListener(new MySinchClientListener());
        mSinchClient.getCallClient().addCallClientListener(new SinchCallClientListener());
        mSinchClient.start();
    }
}

private void stop() {
    if (mSinchClient != null) {
        mSinchClient.terminate();
        mSinchClient = null;
    }
}

private boolean isStarted() {
    return (mSinchClient != null && mSinchClient.isStarted());
}

@Override
public IBinder onBind(Intent intent) {
    return mSinchServiceInterface;
}

public class SinchServiceInterface extends Binder {

    public Call callPhoneNumber(String phoneNumber) {
        return mSinchClient.getCallClient().callPhoneNumber(phoneNumber);
    }

    public Call callUser(String userId) {
        return mSinchClient.getCallClient().callUser(userId);
    }

    public Call callUser(String userId, Map<String, String> headers) {
        return mSinchClient.getCallClient().callUser(userId, headers);
    }

    public String getUserName() {
        return mUserId;
    }

    public boolean isStarted() {
        return SinchService.this.isStarted();
    }

    public void startClient(String userName) {
        start(userName);
    }

    public void stopClient() {
        stop();
    }

    public void setStartListener(StartFailedListener listener) {
        mListener = listener;
    }

    public Call getCall(String callId) {
        return mSinchClient.getCallClient().getCall(callId);
    }
}

public interface StartFailedListener {
    void onStartFailed(SinchError error);

    void onStarted();
}

private class MySinchClientListener implements SinchClientListener {

    @Override
    public void onClientFailed(SinchClient client, SinchError error) {
        if (mListener != null) {
            mListener.onStartFailed(error);
        }
        mSinchClient.terminate();
        mSinchClient = null;
    }

    @Override
    public void onClientStarted(SinchClient client) {
        Log.d(TAG, "SinchClient started");
        if (mListener != null) {
            mListener.onStarted();
        }
    }

    @Override
    public void onClientStopped(SinchClient client) {
        Log.d(TAG, "SinchClient stopped");
    }

    @Override
    public void onLogMessage(int level, String area, String message) {
        switch (level) {
            case Log.DEBUG:
                Log.d(area, message);
                break;
            case Log.ERROR:
                Log.e(area, message);
                break;
            case Log.INFO:
                Log.i(area, message);
                break;
            case Log.VERBOSE:
                Log.v(area, message);
                break;
            case Log.WARN:
                Log.w(area, message);
                break;
        }
    }

    @Override
    public void onRegistrationCredentialsRequired(SinchClient client,
            ClientRegistration clientRegistration) {
    }
}

private class SinchCallClientListener implements CallClientListener {

    @Override
    public void onIncomingCall(CallClient callClient, Call call) {
        Log.d(TAG, "Incoming call");
        Intent intent = new Intent(SinchService.this, IncomingCallScreenActivity.class);
        intent.putExtra(CALL_ID, call.getCallId());
        intent.putExtra(LOCATION, call.getHeaders().get("location"));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        SinchService.this.startActivity(intent);
       }
   }

}

For my purposes, I need to derive the username for the client from my shared preferences folder. I made a dummy app that uses the same framework above with the addition of shared preferences but I always get a NullPointerException error. The following is my login class from my dummy app.

   public class LoginActivity extends BaseActivity implements SinchService.StartFailedListener {

private EditText mLoginName, recipientName, coordinateA, coordinateB;
private Button loginButton;
private static final int REQUEST_PERMISSION = 10;
public static final String DEFAULT = "N/A";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    userName = (EditText) findViewById(R.id.userInput);
    recipientName = (EditText) findViewById(R.id.recipientInput);
    loginButton = (Button) findViewById(R.id.loginButton);
    requestAppPermissions(new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.ACCESS_FINE_LOCATION}, R.string.msg,  REQUEST_PERMISSION);

    SharedPreferences sharedPreferences = getSharedPreferences("MyData", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString("user_name", mLoginName.getText().toString());
    editor.putString("recipient_name", recipientName.getText().toString());
    editor.commit();

    loginButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            loginClicked();
        }
    });

}

@Override
public void onPermissionGranted(int requestCode) {

}

@Override
protected void onServiceConnected() {
    getSinchServiceInterface().setStartListener(this);
}

@Override
protected void onPause() {
    super.onPause();
}

@Override
public void onStartFailed(SinchError error) {
    Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show();
}

@Override
public void onStarted() {
    openPlaceCallActivity();
}

private void loginClicked() {
    SharedPreferences sharedPreferences = getSharedPreferences("MyData", MODE_PRIVATE);
    String userName = sharedPreferences.getString("user_name", DEFAULT);

     if (userName.isEmpty()) {
        Toast.makeText(this, "Please enter a name", 
        Toast.LENGTH_LONG).show();
        return;
    }  

    if (!getSinchServiceInterface().isStarted()) {
        getSinchServiceInterface().startClient(userName);
    } else {
        openPlaceCallActivity();

    }
}
private void openPlaceCallActivity() {
    Intent mainActivity = new Intent(LoginActivity.this, PlaceCallActivity.class);
    startActivity(mainActivity);
    }

}

When comparing my login class with the tutorial's login class-- the only difference is where the variable "userName" is derived. We both have a value attached to the username; however, only one client is able to establish while the other throws a NullPointerException Error. Anyone know why?

EDIT: The error message is as follows:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.dejon_000.sinchtest2, PID: 32470
              java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.example.dejon_000.sinchtest2.SinchService$SinchServiceInterface.isStarted()' on a null object reference
                  at com.example.dejon_000.sinchtest2.LoginActivity.loginClicked(LoginActivity.java:83)
                  at com.example.dejon_000.sinchtest2.LoginActivity.access$000(LoginActivity.java:17)
                  at com.example.dejon_000.sinchtest2.LoginActivity$1.onClick(LoginActivity.java:47)
                  at android.view.View.performClick(View.java:4802)
                  at android.view.View$PerformClick.run(View.java:20059)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:135)
                  at android.app.ActivityThread.main(ActivityThread.java:5422)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at java.lang.reflect.Method.invoke(Method.java:372)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)

SECOND EDIT: The getSinchServiceInterface() method is found in the BaseActivity class. It is as follows:

public abstract class BaseActivity extends Activity implements ServiceConnection {

private SparseIntArray mErrorString;
public static final String DEFAULT = "N/A";
private SinchService.SinchServiceInterface mSinchServiceInterface;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getApplicationContext().bindService(new Intent(this, SinchService.class), this,
            BIND_AUTO_CREATE);
    mErrorString = new SparseIntArray();
}

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    if (SinchService.class.getName().equals(componentName.getClassName())) {
        mSinchServiceInterface = (SinchService.SinchServiceInterface) iBinder;
        onServiceConnected();
    }
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
    if (SinchService.class.getName().equals(componentName.getClassName())) {
        mSinchServiceInterface = null;
        onServiceDisconnected();
    }
}

protected void onServiceConnected() {
    // for subclasses
}

protected void onServiceDisconnected() {
    // for subclasses
}

protected SinchService.SinchServiceInterface getSinchServiceInterface() {
    return mSinchServiceInterface;
}

public abstract void onPermissionGranted(int requestCode);

public void requestAppPermissions(final String[] requestedPermissions, final int stringId, final int requestCode) {
    mErrorString.put(requestCode, stringId);

    int permissionCheck = PackageManager.PERMISSION_GRANTED;
    boolean showRequestPermissions = false;
    for (String permission : requestedPermissions) {
        permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
        showRequestPermissions = showRequestPermissions || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
    }

    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        if (showRequestPermissions) {
            Snackbar.make(findViewById(android.R.id.content), stringId, Snackbar.LENGTH_INDEFINITE).setAction("GRANT", new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    ActivityCompat.requestPermissions(BaseActivity.this, requestedPermissions, requestCode);

                }
            }).show();
        } else {
            ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
        }

    } else {
        onPermissionGranted(requestCode);
    }

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    int permissionCheck = PackageManager.PERMISSION_GRANTED;
    for(int permission : grantResults){
        permissionCheck = permissionCheck + permission;
    }
    if((grantResults.length > 0)&& PackageManager.PERMISSION_GRANTED == permissionCheck ){
        onPermissionGranted(requestCode);

    }else{
        Snackbar.make(findViewById(android.R.id.content), mErrorString.get(requestCode), Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent();
                i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                i.setData(Uri.parse("package:"+ getPackageName()));
                i.addCategory(Intent.CATEGORY_DEFAULT);
                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                startActivity(i);
            }
        }).show();
    }

   }

 }

回答1:


Try this :

on your BaseActivity.java

instead of

protected void onServiceConnected() {
// for subclasses
}

put

protected void onServiceConnected(IBinder iBinder) {
mSinchServiceInterface = (SinchService.SinchServiceInterface) iBinder;
}

and in your LoginActivity.java

Override the function onServiceConnected(IBinder iBinder)

@Override
protected void onServiceConnected(IBinder iBinder) {
   super.onServiceConnected(iBinder);
   getSinchServiceInterface().setStartListener(this);
}


来源:https://stackoverflow.com/questions/41307882/unable-to-instantiate-sinch-client-nullpointerexception-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!