I have this question again about NSD, this time I would like to ask ask if anybody know how to display only service name without all the details like port, host, service type.So far I managed to display all services using ArrayList and NsdServiceInfo object which displays all details about service as I mentioned before, but in my case I want to display only service name.
If you have any ideas, you are more than welcome to share with me
private String SERVICE_TYPE = "_lala._tcp.";
private InetAddress hostAddress;
private int hostPort;
private NsdManager mNsdManager;
NsdServiceInfo mService;
private WebView mWebView;
ArrayList<NsdServiceInfo> services;
ArrayAdapter<NsdServiceInfo> adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Getting toolbar by id
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//disabling default title text
getSupportActionBar().setDisplayShowTitleEnabled(false);
//NSD stuff
mNsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
//Creating the arrayList and arrayAdapter to store services
services = new ArrayList<>();
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, services);
ListView listView = findViewById(R.id.ListViewServices);
listView.setAdapter(adapter);
//Creating onClick listener for the chosen service and trying to resolve it
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Object serviceObj = adapterView.getItemAtPosition(i);
NsdServiceInfo selectedService = (NsdServiceInfo) serviceObj;
//mNsdManager.stopServiceDiscovery(mDiscoveryListener);
mNsdManager.resolveService(selectedService, mResolveListener);
}
});
}
// Each time create new discovery listener for discovery methods onServicefound.
NsdManager.DiscoveryListener mDiscoveryListener = new NsdManager.DiscoveryListener() {
#Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e("TAG", "DiscoveryFailed: Error code: " + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
#Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e("TAG", "Discovery failed : Error code: " + errorCode);
}
#Override
public void onDiscoveryStarted(String regType) {
Log.d("TAG", "Service discovery started");
}
#Override
public void onDiscoveryStopped(String serviceType) {
Log.i("TAG", "Discovery stopped: " + serviceType);
}
// When service is found add it to the array. Log d is for debugging purposes.
#Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
Log.d("TAG", "Service discovery success : " + serviceInfo);
Log.d("TAG", "Host = " + serviceInfo.getServiceName());
Log.d("TAG", "Port = " + serviceInfo.getPort());
services.add(serviceInfo);
//Notifying adapter about change in UI thread because it informs view about data change.
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
}
//When service connection is lost to avoid duplicating we create new serviceToRemove object and check if that object is equals to current service,
// if it yes wre remove the service from an array and inform adapter about the change.
#Override
public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
Log.d("TAG", "Service lost " + nsdServiceInfo);
NsdServiceInfo serviceToRemove = new NsdServiceInfo();
for (NsdServiceInfo currentService : services) {
if (currentService.getHost() == nsdServiceInfo.getHost() && currentService.getPort() == currentService.getPort() && currentService.getServiceName() == currentService.getServiceName()) {
serviceToRemove = currentService;
}
}
if (serviceToRemove != null) {
services.remove(serviceToRemove);
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
}
Log.d("TAG", "Xd" + services);
}
//}
};
//Creating new Resolve listener each time when user chooses the service. If the connection was made we launch web view activity with the webpage.
NsdManager.ResolveListener mResolveListener = new NsdManager.ResolveListener() {
#Override
public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int errorCode) {
Log.e("TAG", "Resolved failed " + errorCode);
Log.e("TAG", "Service = " + nsdServiceInfo);
}
#Override
public void onServiceResolved(NsdServiceInfo nsdServiceInfo) {
Log.d("TAG", "bbz" + nsdServiceInfo);
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
startActivity(intent);
}
});
Log.d("TAG", "Resolve Succeeded " + nsdServiceInfo);
if (nsdServiceInfo.getServiceType().equals(SERVICE_TYPE)) {
Log.d("TAG", "Same IP");
return;
}
hostPort = nsdServiceInfo.getPort();
hostAddress = nsdServiceInfo.getHost();
}
};
// NsdHelper's tearDown method
public void tearDown() {
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
}
Related
I am creating an android app chatbot using google's dialog flow (API.AI). The problem is, If I am sending text input for my intents,it is giving right response, whereas if same thing I am sending using voice input, am getting wrong response. I am not able to understand what is the problem.
Here is my code :-
public class MyChatActivity extends AppCompatActivity implements View.OnClickListener, AIListener {
public String TAG = this.getClass().getSimpleName();
private List<ChatMessageBean> chatList = new ArrayList<>();
private String CLIENT_ACCESS_TOKEN = "My dialog flow agent's client access token";
AIConfiguration config;
AIService aiService;
AIRequest aiRequest;
AIDataService aiDataService;
TextToSpeech textToSpeech;
RecyclerView chatRecyclerView,menuRecyclerView;
ChatMessageListAdapter chatMessageListAdapter;
FloatingActionButton sendMessageButton,recordMessageButton;
EditText enterMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_chat_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initializeVariables();
setListeners();
}
public void initializeVariables() {
config = new AIConfiguration(CLIENT_ACCESS_TOKEN, AIConfiguration.SupportedLanguages.English, AIConfiguration.RecognitionEngine.System);
aiService = AIService.getService(getApplicationContext(), config);
aiRequest = new AIRequest();
aiDataService = new AIDataService(getApplicationContext(), config);
chatRecyclerView = (RecyclerView) findViewById(R.id.chat_list_recycler_view);
setMenuRecyclerView();
enterMessage = (EditText) findViewById(R.id.enter_text_message);
sendMessageButton = (FloatingActionButton) findViewById(R.id.send_message_button);
recordMessageButton =(FloatingActionButton) findViewById(R.id.record_message_button);
textToSpeech = new TextToSpeech(getApplicationContext(),new TextToSpeech.OnInitListener(){
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.US);
}
}
});
}
public void setListeners() {
sendMessageButton.setOnClickListener(this);
aiService.setListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.record_message_button:
aiService.startListening();
break;
case R.id.send_message_button:
String message = enterMessage.getText().toString().trim();
enterMessage.setText("");
sendMessage(message);//sending message with text input
break;
}
}
private boolean validateMessage(String message) {
if ((message.equals("")) || (message.isEmpty()) || (message.length() == 0))
return false;
return true;
}
public void sendMessage(String message) {
// In this method i am sending the message to dialog flow
if (validateMessage(message)) {
ChatMessageBean chatMessageBean = new ChatMessageBean(message); // this is the bean I am using for chatbot app's messages
chatList.add(chatMessageBean);
chatMessageListAdapter = new ChatMessageListAdapter(chatList);// this is the adapter for recycler view that I am using for app's messages
chatRecyclerView.setAdapter(chatMessageListAdapter);
chatRecyclerView.setLayoutManager(new LinearLayoutManager(this));
aiRequest.setQuery(message);
new AsyncTask<AIRequest, Void, AIResponse>() {
#Override
protected AIResponse doInBackground(AIRequest... aiRequests) {
final AIRequest request = aiRequests[0];
try {
final AIResponse response = aiDataService.request(aiRequest);
return response;
} catch (AIServiceException e) {
}
return null;
}
#Override
protected void onPostExecute(AIResponse response) {
if (response != null) {
Result result = response.getResult();
String reply = result.getFulfillment().getSpeech();
ChatMessageBean chatMessageBean = new ChatMessageBean(reply.trim());
chatList.add(chatMessageBean);
chatMessageListAdapter = new ChatMessageListAdapter(chatList);
chatRecyclerView.setLayoutManager(new LinearLayoutManager(PersonaAssistantChatActivity.this));
chatRecyclerView.setAdapter(chatMessageListAdapter);
textToSpeech.speak(reply,TextToSpeech.QUEUE_FLUSH,null);
if(reply.trim().equalsIgnoreCase(API_ACCESS_STRING)){ //API_ACCESS_STRING is the string after which I have to get response from my own defined intents. So I am cheking if the reply is equal to API_ACCESS_STRING
String intentName=result.getMetadata().getIntentName();
switch(intentName){
case "AvailableEmployees":
Log.d(TAG, "CallIntents: AvailableEmployees:"+intentName);
String jobName=result.getStringParameter("JobName");
String date = result.getStringParameter("Date");
Log.d(TAG,"JobName:"+jobName+"date: "+date); // When I send voice input here I get jobName="AvailableEmployees" automatically, and dialog flow doesnot ask for jobName, where as with text input I get everything right.
}
}
}
}
}.execute(aiRequest);
} else {
Toast.makeText(getApplicationContext(), "Please enter some text first or record your message", Toast.LENGTH_LONG).show();
}
}
#Override
public void onResult(AIResponse result) {
String message= result.getResult().getResolvedQuery().toString().trim();
sendMessage(message);//sending message with voice input
}
#Override
public void onError(AIError error) {
Log.i(TAG, ": onError" + error);
}
#Override
public void onAudioLevel(float level) {
Log.i(TAG, ": onAudioLevel:" + level);
}
#Override
public void onListeningStarted() {
Log.i(TAG, ": onListeningStarted");
}
#Override
public void onListeningCanceled() {
Log.i(TAG, ": onListeningCanceled");
}
#Override
public void onListeningFinished() {
Log.i(TAG, ": onListeningFinished");
}
}
You can not call sendMessage(message);//sending message with voice input in the onResult method. This method is called when aiService finishes listening and has already sent a request to Dialogflow and you get the response. When you call aiService.startListening(); the service detect what the user is saying and sends it to Dialogflow.
If you want to know the text "aiService" is sending to Dialogflow you have to use PartialResultsListener and implement it:
#Override
public void onPartialResults(final List<String> partialResults) {
if (!partialResults.isEmpty()) {
String partialResult = partialResults.get(0);
}
}
That way you will get what the user says, but be aware as the method will be called BEFORE onListeningFinished() ends.
Best of luck playing with Handler.postDelayed() :)
Theres edit text field. It has to work like this:
1) if it is empty - nothing happen
2) if user put some NEW text starts method of TextWatcher with HTTP request which takes JSON object. Also the value of String will put in sharedpreference
3) if user open activity when sharedpreference already have value of previous string it has to just set text from that string and don't start method of TextWatcher with HTTP request.
So there are three conditions and progrmm has to make request only in case when value of string is not tha same as in shared pref. Now it sends request even if person just open app. I want to avoid wrong requests and make request only after new value of string.
THE MAIN QUESTION: How to launch HTTP request code ONLY in case if value in textfield is not the same as in sharedpref?
P.S. If you think my question is bad. Please tell me in notes NOT JUST MAKE -1 please. Teach new programmers
Here is the code
public class MainActivity extends AppCompatActivity {
AppCompatButton chooseLanguageButton;
AppCompatButton cleanButton;
AppCompatEditText translatedTextOutput;
AppCompatEditText translatedTextInput;
String translatedInputString;
RequestQueue requestQueue;
final String TAG = "myTag";
String language;
SharedPreferences mSettings;
SharedPreferences textReference;
SharedPreferences translateReference;
SharedPreferences longLangReference;
SharedPreferences shortLangReference;
final String SAVED_TEXT = "text";
final String SAVED_TRANSLATION = "translation";
final String LANGUAGE_LONG = "lang_long";
final String LANGUAGE_SHORT = "lang_short";
public static final String APP_PREFERENCES = "mysettings";
private ProgressBar progressBar;
private Timer timer;
private TextWatcher searchTextWatcher = new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
Log.v(TAG, "in afterTextChanged");
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if (translatedTextInput.getText().length() != 0){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
requestQueue = Volley.newRequestQueue(MainActivity.this);
sendJsonRequest();
}
});
}
InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
in.hideSoftInputFromWindow(translatedTextInput.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}, 600);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (timer != null) {
timer.cancel();
}
saveText();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "in Oncreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chooseLanguageButton = (AppCompatButton) findViewById(R.id.choose_language_button);
cleanButton = (AppCompatButton) findViewById(R.id.clean_button);
translatedTextOutput = (AppCompatEditText) findViewById(R.id.translated_text_field);
translatedTextInput = (AppCompatEditText) findViewById(R.id.translation_input_edit);
int textLength = translatedTextInput.getText().length();
translatedTextInput.setSelection(textLength);
translatedTextInput.addTextChangedListener(searchTextWatcher);
chooseLanguageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.v(TAG, "in chooseLanguageListener");
Intent intent = new Intent(MainActivity.this, ChooseLanguageList.class);
startActivity(intent);
}
});
cleanButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
translatedTextInput.setText("");
translatedTextOutput.setText("");
}
});
mSettings = getSharedPreferences(APP_PREFERENCES, Context.MODE_PRIVATE);
if (mSettings.contains(LANGUAGE_LONG)){
Log.v(TAG, "here");
chooseLanguageButton.setText(mSettings.getString(LANGUAGE_LONG,""));
} else {
Log.v(TAG, "THERE");
chooseLanguageButton.setText("Choose language");
}
if (mSettings.contains(SAVED_TEXT)){
Log.v(TAG, "here");
translatedTextInput.setText(mSettings.getString(SAVED_TEXT,""));
} else {
Log.v(TAG, "boooooom");
}
if (mSettings.contains(SAVED_TRANSLATION)){
Log.v(TAG, "here in TRANSLATION FIELD" + mSettings.getString(SAVED_TRANSLATION,""));
translatedTextOutput.setText(mSettings.getString(SAVED_TRANSLATION,""));
} else {
Log.v(TAG, "boooooom");
}
}
#Override
protected void onResume() {
super.onResume();
translatedTextInput.post(new Runnable() {
#Override
public void run() {
Selection.setSelection(translatedTextInput, );
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mSettings = null;
}
void saveText() {
// mSettings = getSharedPreferences(SAVED_TEXT, MODE_PRIVATE);
SharedPreferences.Editor ed = mSettings.edit();
ed.putString(SAVED_TEXT, translatedTextInput.getText().toString());
ed.putString(SAVED_TRANSLATION, translatedTextOutput.getText().toString());
ed.apply();
Log.v(TAG, "Text saved==========>" + translatedTextInput.getText().toString());
Toast.makeText(this, "Text saved", Toast.LENGTH_SHORT).show();
}
void loadText() {
textReference = getSharedPreferences(SAVED_TEXT, MODE_PRIVATE);
translatedTextInput.setText(mSettings.getString(SAVED_TEXT,""));
translateReference = getSharedPreferences(SAVED_TRANSLATION, MODE_PRIVATE);
translatedTextOutput.setText(mSettings.getString(SAVED_TRANSLATION,""));
Log.v(TAG, "IN LOAD TEXT METHOD" + mSettings.getString(SAVED_TEXT,""));
Log.v(TAG, "IN LOAD TRANSLATION METHOD" + mSettings.getString(SAVED_TRANSLATION,""));
}
public void sendJsonRequest() {
Log.v(TAG, "in sendJsonObject");
Intent myIntent = getIntent();
// language = myIntent.getStringExtra("short");
shortLangReference = getSharedPreferences(LANGUAGE_SHORT, MODE_PRIVATE);
language = mSettings.getString(LANGUAGE_SHORT,"");
Log.v(getClass().getSimpleName(), "language short = " + language);
translatedInputString = translatedTextInput.getText().toString().replace(" ","+");
String url = String.format(getApplicationContext().getResources().getString(R.string.request_template),
String.format(getApplicationContext().getResources().getString(R.string.query_Template), translatedInputString, language ));
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.v(TAG, "Inside OnResponse" + response.toString());
JSONArray results = null;
try {
results = response.getJSONObject("data").getJSONArray("translations");
for (int i=0,j=results.length();i<j;i++) {
String webTitle = results.getJSONObject(i).getString("translatedText");
translatedTextOutput.setText(webTitle);
}
} catch (JSONException e) {
Log.e(TAG, "Error :" + e);
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (error instanceof NetworkError) {
Log.e(TAG, "NetworkError");
} else if (error instanceof ServerError) {
Log.e(TAG, "The server could not be found. Please try again after some time!!");
} else if (error instanceof AuthFailureError) {
Log.e(TAG, "AuthFailureError");
} else if (error instanceof ParseError) {
Log.e(TAG, "Parsing error! Please try again after some time!!");
} else if (error instanceof NoConnectionError) {
Log.e(TAG, "NoConnectionError!");
} else if (error instanceof TimeoutError) {
Log.e(TAG, "Connection TimeOut! Please check your internet connection.");
}
}
});
requestQueue.add(jsObjRequest);
}
}
I want to create a service that should listens for hotword in background such that when i say hello it should invoke an activity, how can i do this, about voiceInteractionService but I have read that Its not available to use, is it true? could anyone tell me the way i should solve this problem? Its about hotword detector
I have been following this
Tried this:
public class InteractionService extends VoiceInteractionService {
static final String TAG = "InteractionService" ;
private AlwaysOnHotwordDetector mHotwordDetector;
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "service started");
}
#Override
public void onReady() {
super.onReady();
Log.i(TAG, "Creating " + this);
mHotwordDetector = createAlwaysOnHotwordDetector("Hello"
, Locale.forLanguageTag("en-US"), mHotwordCallback);
Log.i(TAG, "onReady");
}
private final AlwaysOnHotwordDetector.Callback mHotwordCallback =
new AlwaysOnHotwordDetector.Callback() {
#Override
public void onAvailabilityChanged(int status) {
Log.i(TAG, "onAvailabilityChanged(" + status + ")");
hotwordAvailabilityChangeHelper(status);
}
#Override
public void onDetected(AlwaysOnHotwordDetector
.EventPayload eventPayload) {
Log.i(TAG, "onDetected");
}
#Override
public void onError() {
Log.i(TAG, "onError");
}
#Override
public void onRecognitionPaused() {
Log.i(TAG, "onRecognitionPaused");
}
#Override
public void onRecognitionResumed() {
Log.i(TAG, "onRecognitionResumed");
}
};
private void hotwordAvailabilityChangeHelper(int status) {
Log.i(TAG, "Hotword availability = " + status);
switch (status) {
case AlwaysOnHotwordDetector.STATE_HARDWARE_UNAVAILABLE:
Log.i(TAG, "STATE_HARDWARE_UNAVAILABLE");
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNSUPPORTED:
Log.i(TAG, "STATE_KEYPHRASE_UNSUPPORTED");
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED");
Intent enroll = mHotwordDetector.createEnrollIntent();
Log.i(TAG, "Need to enroll with " + enroll);
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
Log.i(TAG, "STATE_KEYPHRASE_ENROLLED - starting recognition");
if (mHotwordDetector.startRecognition(0)) {
Log.i(TAG, "startRecognition succeeded");
} else {
Log.i(TAG, "startRecognition failed");
}
break;
}
// final static AlwaysOnHotwordDetector.Callback
}}
Porcupine's service demo does exactly this.
Hey I have some problem with Gcm intent service at calling `subscribeToTopicP class, that always getting null pointer exception.
Here is my code:
GcmIntentService.java
private static final String TAG = GcmIntentService.class.getSimpleName();
public GcmIntentService() {
super(TAG);
}
public static final String KEY = "key";
public static final String TOPIC = "topic";
public static final String SUBSCRIBE = "subscribe";
public static final String UNSUBSCRIBE = "unsubscribe";
public SessionManager session;
#Override
protected void onHandleIntent(Intent intent) {
session = new SessionManager(getApplicationContext());
String key = intent.getStringExtra(KEY);
switch (key) {
case SUBSCRIBE:
// subscribe to a topic
String topic = intent.getStringExtra(TOPIC);
subscribeToTopic(topic);
break;
case UNSUBSCRIBE:
break;
default:
// if key is specified, register with GCM
registerGCM();
}
}
/**
* Registering with GCM and obtaining the gcm registration id
*/
private void registerGCM() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Log.e(TAG, "GCM Registration Token: " + token);
// sending the registration id to our server
sendRegistrationToServer(token);
sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, true).apply();
} catch (Exception e) {
Log.e(TAG, "Failed to complete token refresh", e);
sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
private void sendRegistrationToServer(final String token) {
// checking for valid login session
session.isLoggedIn();
HashMap<String, String> user = session.getUserDetails();
String UserId = user.get(SessionManager.KEY_ID);
String endPoint = EndPoints.UPDATE_USER_GCM.replace("_ID_", UserId);
Log.e(TAG, "endpoint: " + endPoint);
StringRequest strReq = new StringRequest(Request.Method.PUT, endPoint, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e(TAG, "response: " + response);
try {
JSONObject obj = new JSONObject(response);
// check for error
if (obj.getBoolean("error") == false) {
// broadcasting token sent to server
Intent registrationComplete = new Intent(Config.SENT_TOKEN_TO_SERVER);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(registrationComplete);
} else {
Toast.makeText(getApplicationContext(), "Unable to send gcm registration id to our sever. " + obj.getJSONObject("error").getString("message"), Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
Log.e(TAG, "json parsing error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Json parse error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
Log.e(TAG, "Volley error: " + error.getMessage() + ", code: " + networkResponse);
Toast.makeText(getApplicationContext(), "Volley error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("UserGcmRegistrationId", token);
Log.e(TAG, "params: " + params.toString());
return params;
}
};
//Adding request to request queue
Volley.newRequestQueue(getApplicationContext()).add(strReq);
}
/**
* Subscribe to a topic
*/
public static void subscribeToTopic(String topic) {
GcmPubSub pubSub = GcmPubSub.getInstance(MyApplication.getInstance().getApplicationContext());
InstanceID instanceID = InstanceID.getInstance(MyApplication.getInstance().getApplicationContext());
String token = null;
try {
token = instanceID.getToken(MyApplication.getInstance().getApplicationContext().getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null) {
pubSub.subscribe(token, "/topics/" + topic, null);
Log.e(TAG, "Subscribed to topic: " + topic);
} else {
Log.e(TAG, "error: gcm registration id is null");
}
} catch (IOException e) {
Log.e(TAG, "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage());
Toast.makeText(MyApplication.getInstance().getApplicationContext(), "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void unsubscribeFromTopic(String topic) {
GcmPubSub pubSub = GcmPubSub.getInstance(getApplicationContext());
InstanceID instanceID = InstanceID.getInstance(getApplicationContext());
String token = null;
try {
token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null) {
pubSub.unsubscribe(token, "");
Log.e(TAG, "Unsubscribed from topic: " + topic);
} else {
Log.e(TAG, "error: gcm registration id is null");
}
} catch (IOException e) {
Log.e(TAG, "Topic unsubscribe error. Topic: " + topic + ", error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
My LogCat Error :
E/AndroidRuntime: FATAL EXCEPTION: IntentService[GcmIntentService]
Process: com.nvitek.www.aspirasirakyat, PID: 25962
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:107)
at com.nvitek.www.aspirasirakyat.gcm.GcmIntentService.subscribeToTopic(GcmIntentService.java:155)
at com.nvitek.www.aspirasirakyat.gcm.GcmIntentService.onHandleIntent(GcmIntentService.java:56)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
MyApplication.java
public static final String TAG = MyApplication.class.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
private SessionManager pref;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
if(mInstance==null)
{
mInstance=new MyApplication();
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public SessionManager getPrefManager() {
if (pref == null) {
pref = new SessionManager(this);
}
return pref;
}
And here my ActivityDashboard.java
//JSON TAGS
public static final String TAG_IMAGE_URL = "image";
public static final String TAG_TITLE = "title";
public static final String TAG_FNAME = "fname";
public static final String TAG_LNAME = "lname";
public static final String TAG_CONTENT = "content";
public static final String TAG_DATE = "date";
public static final String TAG_ID = "id";
private String TAG = ActivityDashboard.class.getSimpleName();
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private BroadcastReceiver mRegistrationBroadcastReceiver;
private List<ListItem> listItems;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
//Volley Request Queue
private RequestQueue requestQueue;
private Boolean exit = false;
SessionManager session;
JSONArray users = null;
DrawerLayout drawerLayout;
NavigationView mNavigationView;
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
session = new SessionManager(getApplicationContext());
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_menu_white);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigationView = (NavigationView) findViewById(R.id.navigation);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
Intent intent;
switch (menuItem.getItemId()) {
case R.id.navigation_item_1:
intent = new Intent(ActivityDashboard.this, ActivityDashboard.class);
startActivity(intent);
return true;
/* case R.id.navigation_item_2:
intent = new Intent(ActivityDashboard.this, ActivityDashboard.class);
startActivity(intent);
return true; */
case R.id.navigation_item_3:
intent = new Intent(ActivityDashboard.this, ActivityStatistic.class);
startActivity(intent);
return true;
case R.id.navigation_item_4:
intent = new Intent(ActivityDashboard.this, ActivityProfile.class);
startActivity(intent);
return true;
case R.id.navigation_item_5:
session.logoutUser();
return true;
default:
return true;
}
}
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Loading...", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
gotoAdd(view);
}
});
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
subscribeToGlobalTopic();
} else if (intent.getAction().equals(Config.SENT_TOKEN_TO_SERVER)) {
// gcm registration id is stored in our server's MySQL
Log.e(TAG, "GCM registration id is sent to our server");
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
handlePushNotification(intent);
}
}
};
}
#Override
public void onStart() {
super.onStart();
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(ActivityDashboard.this, recyclerView, new ClickListener() {
#Override
public void onListClick(View v, int position) {
Intent intent = new Intent(ActivityDashboard.this, ActivityPreviewPost.class);
intent.putExtra("Url_Key", EndPoints.COMMENTS + "?id=" + listItems.get(position).getId());
intent.putExtra("Id_Key", listItems.get(position).getId());
intent.putExtra("Photo_Key", listItems.get(position).getImageUrl());
intent.putExtra("Title_Key", listItems.get(position).getTitle());
intent.putExtra("FName_Key", listItems.get(position).getFName());
intent.putExtra("LName_Key", listItems.get(position).getLName());
intent.putExtra("Date_Key", listItems.get(position).getDate());
intent.putExtra("Content_Key", listItems.get(position).getContent());
startActivity(intent);
}
#Override
public void onListLongClick(View v, int position) {
}
}));
//Initializing our list
listItems = new ArrayList<>();
requestQueue = Volley.newRequestQueue(this);
//Calling method to get data to fetch data
if (checkPlayServices()) {
registerGCM();
getData();
}
//initializing our adapter
adapter = new CardAdapter(listItems, this);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
}
/**
* Handles new push notification
*/
private void handlePushNotification(Intent intent) {
int type = intent.getIntExtra("type", -1);
// if the push is of chat room message
// simply update the UI unread messages count
if (type == Config.PUSH_TYPE_CHATROOM) {
ListComment listComment = (ListComment) intent.getSerializableExtra("CommentContent");
String chatRoomId = intent.getStringExtra("TimelineId");
if (listComment != null && chatRoomId != null) {
updateRow(chatRoomId, listComment);
}
} else if (type == Config.PUSH_TYPE_USER) {
// push belongs to user alone
// just showing the message in a toast
ListComment listComment = (ListComment) intent.getSerializableExtra("CommentContent");
Toast.makeText(getApplicationContext(), "New push: " + listComment.getCommentContent(), Toast.LENGTH_LONG).show();
}
}
private void updateRow(String chatRoomId, ListComment listComment) {
for (ListItem cr : listItems) {
if (cr.getId().equals(chatRoomId)) {
int index = listItems.indexOf(cr);
cr.setLastMessage(listComment.getCommentContent());
cr.setUnreadCount(cr.getUnreadCount() + 1);
listItems.remove(index);
listItems.add(index, cr);
break;
}
}
adapter.notifyDataSetChanged();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
drawerLayout.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
private JsonArrayRequest getDataFromServer() {
//JsonArrayRequest of volley
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(EndPoints.TIMELINES,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//Calling method parseData to parse the json response
parseData(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ActivityDashboard.this, "No More Items Available", Toast.LENGTH_SHORT).show();
}
});
return jsonArrayRequest;
}
//This method will get data from the web api
private void getData() {
//Adding the method to the queue by calling the method getDataFromServer
requestQueue.add(getDataFromServer());
}
//This method will parse json data
private void parseData(JSONArray array) {
for (int i = 0; i < array.length(); i++) {
//Creating the superhero object
ListItem listItem = new ListItem();
JSONObject json = null;
try {
//Getting json
json = array.getJSONObject(i);
//Adding data to the superhero object
listItem.setId(json.getString(TAG_ID));
listItem.setImageUrl(json.getString(TAG_IMAGE_URL));
listItem.setTitle(json.getString(TAG_TITLE));
listItem.setFName(json.getString(TAG_FNAME));
listItem.setLName(json.getString(TAG_LNAME));
listItem.setContent(json.getString(TAG_CONTENT));
listItem.setDate(json.getString(TAG_DATE));
} catch (JSONException e) {
e.printStackTrace();
}
//Adding the superhero object to the list
listItems.add(listItem);
}
//Notifying the adapter that data has been added or changed
adapter.notifyDataSetChanged();
subscribeToAllTopics();
}
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector mGestureDetector;
private ClickListener mClickListener;
public RecyclerTouchListener(final Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.mClickListener = clickListener;
mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(),e.getY());
if (child!=null && clickListener!=null){
clickListener.onListLongClick(child, recyclerView.getChildAdapterPosition(child));
}
super.onLongPress(e);
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child!=null && mClickListener!=null && mGestureDetector.onTouchEvent(e)){
mClickListener.onListClick(child, rv.getChildAdapterPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
public void gotoAdd(View view) {
Intent intent = new Intent(this, ActivityAddPost.class);
Log.e("aspirasi", "change activity");
startActivity(intent);
}
// subscribing to global topic
private void subscribeToGlobalTopic() {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra(GcmIntentService.KEY, GcmIntentService.SUBSCRIBE);
intent.putExtra(GcmIntentService.TOPIC, Config.TOPIC_GLOBAL);
startService(intent);
}
// Subscribing to all chat room topics
// each topic name starts with `topic_` followed by the ID of the chat room
// Ex: topic_1, topic_2
private void subscribeToAllTopics() {
for (ListItem cr : listItems) {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra(GcmIntentService.KEY, GcmIntentService.SUBSCRIBE);
intent.putExtra(GcmIntentService.TOPIC, "topic_" + cr.getId());
startService(intent);
}
}
#Override
protected void onResume() {
super.onResume();
// register GCM registration complete receiver
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.REGISTRATION_COMPLETE));
// register new push message receiver
// by doing this, the activity will be notified each time a new message arrives
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.PUSH_NOTIFICATION));
}
#Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
super.onPause();
}
// starting the service to register with GCM
private void registerGCM() {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra("key", "register");
startService(intent);
}
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
Log.i(TAG, "This device is not supported. Google Play Services not installed!");
Toast.makeText(getApplicationContext(), "This device is not supported. Google Play Services not installed!", Toast.LENGTH_LONG).show();
finish();
}
return false;
}
return true;
}
#Override
public void onStop() {
super.onStop();
}
public static interface ClickListener{
public void onListClick(View v, int position);
public void onListLongClick(View v, int position);
}
#Override
public void onBackPressed() {
if (exit) {
finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.", Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
}
// Before 2.0
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (exit) {
finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.", Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
return true;
}
return super.onKeyUp(keyCode, event);
}
This issue is due to variable not being instantiated. You are using the activity as a Context too early. You need to wait until onCreate() or later in the activity lifecycle. You can't call getApplicationContext() until after onCreate() is called. The Activity is not fully initialized until then.
I am having problem with chatting app , I am trying to run chat receiver functionality using handler such that as soon as messages are received they are taken care of and displayed on screen . But it fails when I try to go back and resume the chatting, since Handler keeps on running so is the message object associated with it , and it fails to reinitialize it. Following is the code :
public class hotListener extends ListActivity {
private HotspotService service;
private XMPPConnection connection;
private IBinder binder;
private Handler mHandler = new Handler();
private ArrayList<String> messages = new ArrayList<String>();
ArrayList<ChatMessage> messagex= new ArrayList<ChatMessage>();
ChattingAdapter adaptex= new ChattingAdapter(hotListener.this, messagex);;
HotspotService.MyBinder binderx;
Intent mIntent ;
private ListView listview;
EditText sender_message ;
String msg;
Thread t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listener);
setListAdapter(adaptex);
System.out.println("inside on create");
Button send_button = (Button) findViewById(R.id.chat_send_message);
sender_message = (EditText) findViewById(R.id.chat_input);
send_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
msg = sender_message.getText().toString();
sender_message.setText("");
if(!(msg.length()==0)){
messagex.add(new ChatMessage(msg, true));
//addNewMessage(new ChatMessage(msg, true));
adaptex.notifyDataSetChanged();
getListView().setSelection(messagex.size()-1);
}
}
});
if(!isMyServiceRunning()){
System.out.println("seems like service not running");
startService(new Intent(this,HotspotService.class));
System.out.print(" now started ");
}
}
#Override
protected void onStart(){
super.onStart();
System.out.println("in onstart");
}
private void receivespots(XMPPConnection connection2, final ChattingAdapter adaptex2) {
connection2.getChatManager().addChatListener(new ChatManagerListener() {
#Override
public void chatCreated(Chat arg0, boolean arg1) {
arg0.addMessageListener(new MessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
//final String from = message.getFrom();
final String body = message.getBody();
mHandler.post(new Runnable() {
#Override
public void run() {
messagex.add(new ChatMessage(body, false));
for(int i=0;i<messagex.size();i++){
ChatMessage xc = messagex.get(i);
System.out.println(xc.message);
}
adaptex.notifyDataSetChanged();
getListView().setSelection(messagex.size()-1);
Toast.makeText(hotListener.this,body,Toast.LENGTH_SHORT).show();
}
});
}
});
}
});
}
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for(RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)){
if(HotspotService.class.getName().equals(service.service.getClassName())){
return true;
}
}
return false;
}
#Override
protected void onResume() {
bindService(new Intent(this, HotspotService.class), mConnection, Context.BIND_AUTO_CREATE);
adaptex.notifyDataSetChanged();
System.out.println("inside on resume");
super.onResume();
}
#Override
protected void onDestroy(){
super.onDestroy();
System.out.println("in on destroy");
unbindService(mConnection);
mHandler.removeCallbacksAndMessages(null);
}
#Override
protected void onPause() {
System.out.println("inside on pause");
super.onPause();
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
connection = null;
service = null;
}
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
service = ((HotspotService.MyBinder)binder).getService();
connection = service.getConnection();
receivespots(connection,adaptex);
}
};
}
Is it right way to run such methods ? Definitely not , I can also try to save messages in sqlite and reload on display but that will also fail , since messagex associated with mhandler does not reinitializes and fails to display any message received on screen after resume of activity . It does work properly for first time . But moment messagex is used in handler it keeps on appending messages to old messagex and fails to display after resume on activity