Disable 10 seconds timeout on BroadcastReceiver. Android Development - java

I have a IncomingSmsReceiver class that receives a sms message but the problem is it takes a while to receive the text message, I know that the BroadcastReceiver class automatically stop the process if it's listening for more the 10 seconds, is there any way to disable this?
heres my code:
public class IncomingSmsReceiver extends BroadcastReceiver {
private ShowDialogInterface callback;
public void onReceive(Context context, Intent intent) {
if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
String messageBody = "no data";
String messageFrom = "no data";
for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
messageBody = smsMessage.getMessageBody();
messageFrom = smsMessage.getDisplayOriginatingAddress();
}
if(callback != null) {
callback.smsDetails(messageFrom, messageBody);
}
}
}
public void registerReceiver(ShowDialogInterface receiverCallback) {
this.callback = receiverCallback;
}
// Show different UI elements to notifying the user of an incoming SMS
public interface ShowDialogInterface {
void smsDetails(String from, String message);
}
}
Here is my debug error:
enter image description here
Best Regards,
Noob Android_dev

You can start service from your BroadcastReceiver and do all job in it. It's a standard way to do such things.

Related

Using Android WorkManager to run a function if Connection is stable

I currently have an Android application where the user takes a picture of an item which is then overlayed with some information and saved as a bitmap.
I then have a function that sends this image using email to a shared mailbox that has been set-up.
One problem that my company was having is that sometimes there are black spots where the WI-FI cuts out and therefore the app is unable to send the image.
I have been advised to use Android WorkManager in order to schedule syncing the images that have not been sent.
The problem is I cant send only the bitmap to the Worker class as I need to run the full "sendfile()" function so that it sends as an email?
Here is some code that I am trying (adapted from a tutorial by SimplifiedCoding:
Here is some of the code I have tried:
MyWorker - Worker Class:
public class MyWorker extends Worker {
//a public static string that will be used as the key
//for sending and receiving data
public static final String TASK_DESC = "task_desc";
public MyWorker(#NonNull Context context, #NonNull
WorkerParameters workerParams) {
super(context, workerParams);
}
#NonNull
#Override
public Result doWork() {
Camera1 camera1 = new Camera1();
camera1.sendPortraitImage();
// //getting the input data
// String taskDesc =
getInputData().getString(TASK_DESC);
//
// displayNotification("My Worker",
taskDesc);
// return Result.SUCCESS;
}
private void displayNotification(String title, String task) {
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("simplifiedcoding", "simplifiedcoding", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder notification = new NotificationCompat.Builder(getApplicationContext(), "simplifiedcoding")
.setContentTitle(title)
.setContentText(task)
.setSmallIcon(R.mipmap.ic_launcher);
notificationManager.notify(1, notification.build());
}
}
WorkloadMangerSetUp() and SendFile() functions::
public void WorkManagerSetUp() {
//WORKMANAGERCODE
//creating a data object
//to pass the data with workRequest
//we can put as many variables needed
Data data = new Data.Builder()
.putString(MyWorker.TASK_DESC, fileLoc)
.build();
//creating constraints
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) // you can add as many constraints as you want
.build();
final OneTimeWorkRequest workRequest =
new OneTimeWorkRequest.Builder(MyWorker.class)
.setInputData(data)
.setConstraints(constraints)
.build();
}
public void sendPortraitImage(View vw){
send.setVisibility(View.GONE);
buttonCamera.setVisibility(View.GONE);
bitmap_view = ScreenShott.getInstance().takeScreenShotOfRootView(vw, null);
//TextViewTypeHeader.setVisibility(View.GONE);
//TextViewTypeNo.setVisibility(View.GONE);
//TextViewImageHeader.setVisibility(View.GONE);
//TextViewImageNo.setVisibility(View.GONE);
saveImageToExternalStorage(bitmap_view);
Toast.makeText(getApplicationContext(), "Saved successfully, Check gallery", Toast.LENGTH_SHORT).show();
email = email_auth.EMAIL_FROM;
sub = TypeHeader + " - " + TypeNo + " - " + ImageNo;
msg = "Test AlmaPix";
fileLoc = file.getAbsolutePath();
SharedPreferences info = this.getSharedPreferences("info", MODE_PRIVATE);
info.edit().putString("info", fileLoc).commit();
mail mail = new mail(this,email ,sub, msg);
mail.execute();
WorkManagerSetUp();
WorkManager.getInstance().enqueue(workRequest);
}
What i am trying to achieve is that I am able to run the sendFile() function in the MyWorker class so that any emails that weren't sent are sent when the WI-FI connection is active again.
Any help or suggestions i'd be very greatful!

Send message with Telegram API and store session (NOT with bot API)

I want to implement a very simple Java Telegram Client, which is capable of sending and receiving messages and store the sessions across multiple starts. I already managed to authenticate and receive messages
api = new TelegramApi(apiState, new AppInfo(API_ID, "console", "1", "1", "en"), new ApiCallback() {
#Override
public void onAuthCancelled(TelegramApi api) {
Log.d(TAG, "-----------------CANCELLED----------------");
Log.d(TAG, api.getApiContext().toString());
}
#Override
public void onUpdatesInvalidated(TelegramApi api) {
Log.d(TAG, "-----------------INVALIDATED----------------");
Log.d(TAG, api.getApiContext().toString());
}
#Override
public void onUpdate(TLAbsUpdates tlAbsUpdates) {
Log.d(TAG, "-----------------UPDATE----------------");
Log.d(TAG, tlAbsUpdates.toString());
if (tlAbsUpdates instanceof TLUpdateShortMessage) {
Log.d(TAG, "-----------------UPDATE CHAT MESSAGE----------------");
int senderId = ((TLUpdateShortMessage) tlAbsUpdates).getUserId();
Log.d(TAG, "Message from " + senderId);
String message = ((TLUpdateShortMessage) tlAbsUpdates).getMessage();
Log.d(TAG, message);
activity.appendMessage(TAG, message);
}
}
});
api.switchToDc(2);
TLConfig config = null;
try {
config = api.doRpcCallNonAuth(new TLRequestHelpGetConfig());
} catch (TimeoutException | IOException e) {
e.printStackTrace();
}
apiState.updateSettings(config);
However, I struggle to send messages to another user. For the beginning, it would be enough if I could send a message back to the user, who sent me a message before (by retrieving the senderId, as you can see in the onUpdate method before). However, if someone could also help me with retrieving the ids of my saved contacts, it would be perfect.
Furthermore, I want to store the sessions accross multiple startups, since I get a FLOOD_WAIT error (420), if I test my code to often.
For this I used https://github.com/rubenlagus/TelegramApi/blob/51713e9b6eb9e0ae0d4bbbe3d4deffff9b7f01e4/src/main/java/org/telegram/bot/kernel/engine/MemoryApiState.java and its used classes (e.g. TLPersistence), which stores and loads the ApiState. However, apparently it does not store the signin status, since I always have to authenticate my number every time I update the code.
By the way, I am using Api layer 66 (https://github.com/rubenlagus/TelegramApi/releases).
UPDATE 1:
Problems with sending messages solved myself:
private void sendMessageToUser(int userId, String message) {
TLInputPeerUser peer = new TLInputPeerUser();
peer.setUserId(userId);
TLRequestMessagesSendMessage messageRequest = new TLRequestMessagesSendMessage();
messageRequest.setFlags(0);
messageRequest.setPeer(peer);
messageRequest.setRandomId(new SecureRandom().nextLong());
messageRequest.setMessage(message);
api.doRpcCallNonAuth(messageRequest, 1500, new RpcCallback<TLAbsUpdates>() {
#Override
public void onResult(TLAbsUpdates tlAbsUpdates) {
Log.d(TAG, "-----------------------MESSAGE SENT-----------------------");
}
#Override
public void onError(int i, String s) {
Log.d(TAG, "-----------------------MESSAGE SENT ERROR-----------------------");
Log.d(TAG, String.valueOf(i));
if(s != null) {
Log.d(TAG, s);
}
}
});
}
However, now I am stuck at finding the userIds of my contacts.
After first update this is left:
Saving the session state (and signin state)
Find userIds of contacts
Update 2:
I managed to fetch the users, with which there are already dialogs. This is enough for my use case, however, loading all contacts would be perfect. This is how to load users from existing dialogs:
private int getUserId(String phone) throws InterruptedException {
TLRequestMessagesGetDialogs dialogs = new TLRequestMessagesGetDialogs();
dialogs.setOffsetId(0);
dialogs.setLimit(20);
dialogs.setOffsetPeer(new TLInputPeerUser());
CountDownLatch latch = new CountDownLatch(1);
api.doRpcCallNonAuth(dialogs, 1500, new RpcCallback<TLAbsDialogs>() {
#Override
public void onResult(TLAbsDialogs tlAbsDialogs) {
Log.d(TAG, "----------------------getUsers--------------------");
for(TLAbsUser absUser : ((TLDialogs) tlAbsDialogs).getUsers()) {
users.add((TLUser) absUser);
}
latch.countDown();
}
#Override
public void onError(int i, String s) {
Log.d(TAG, "----------------------getUsers ERROR--------------------");
latch.countDown();
}
});
latch.await();
for(TLUser user : users) {
if(user.getPhone().equals(phone)) {
return user.getId();
}
}
return 0;
}
After second update this is left:
Saving the session state (and signin state)
Get user ids from contacts instead of dialogs

Jade Agent Communication: Making the agent reply

I am doing a project MAS project on jade.
I have 2 agents one to send and one to receive.
How do i make agent 1 send a message to agent 2, for example "1000", and only when agent 2 receives the "1000", agent 2 will reply with for example, "turn off"?
My sugestion is to create agent1 with a RequestPerformer behaviour and agent2 with a CyclicBehaviour to listen messages.
agent1 behaviour content can be like this:
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
cfp.addReceiver(/*agent2AID*/);
cfp.setContent("1000");
cfp.setConversationId(1000);
cfp.setReplyWith("cfp" + System.currentTimeMillis()); // Unique value
myAgent.send(cfp);
mt = MessageTemplate.and(MessageTemplate.MatchConversationId(targetProduct),
MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
agent2 behaviour can be like this:
private class CFPServer extends CyclicBehaviour {
private static final long serialVersionUID = 1L;
public void action() {
MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.CFP);
ACLMessage msg = myAgent.receive(mt);
if (msg != null) {
// CFP Message received. Process it
String title = msg.getContent();
ACLMessage reply = msg.createReply();
// The requested fruit is NOT available for sale.
reply.setPerformative(ACLMessage.INFORM);
reply.setContent("turn off");
myAgent.send(reply);
} else {
block();
}
}
}
The related problem is very well discussed and solved in many ways, you can check out the following implementation of a simple Contract Net Protocol where you can find send and reply functions:
https://github.com/clebercbr/tp_cnp/blob/master/src/java/
See that the agent initiator is like agent1 and participant and rejector are like your agent2
I do not recommend to write a cyclic behaviour for messageReception, it will burn the proc for nothing. A simpleBehaviour with done() at false and a block() in the action() is much more efficient.
Regarding your pb, something like that should work :
public class ReceiveMessageBehaviour extends SimpleBehaviour{
private boolean finished=false;
/**
*
* This behaviour is a one Shot.
* It receives a message tagged with an inform performative, print the content in the console and destroy itself if its equal to 1000
* #param myagent
*/
public ReceiveMessageBehaviour(final Agent myagent) {
super(myagent);
}
public void action() {
//1) receive the message
final MessageTemplate msg Template = MessageTemplate.MatchPerformative(ACLMessage.INFORM);
final ACLMessage msg = this.myAgent.receive(msgTemplate);
//2) check its caracts
if (msg != null && msg.getContent().equals("1000")) {
System.out.println(this.myAgent.getLocalName()+"<----Result received from "+msg.getSender().getLocalName()+" ,content= "+msg.getContent());
this.finished=true;
//3) answer
final ACLMessage msg2 = new ACLMessage(ACLMessage.INFORM);
msg2.setSender(this.myAgent.getAID());
msg2.addReceiver(new AID(msg.getSender().getLocalName(), AID.ISLOCALNAME));
msg2.setContent("turn off");
this.myAgent.send(msg2);
}else{
block();// the behaviour goes to sleep until the arrival of a new message in the agent's Inbox.
}
}
public boolean done() { return finished;}
}
I'm new to these JADE related components. But I would like to add the simplest code that we can use to solve this problem using oneShotBehaviour and Cyclicehaviour.
The following code enables simple communication among two clients.
Agent A-Class:-
public class Agent_A extends Agent{
protected void setup(){
System.out.println(getAID().getName()+" is ready.");
addBehaviour(new AgentA_SendMessage());
addBehaviour(new AgentA_ReceiveMessage());
}
public class AgentA_SendMessage extends OneShotBehaviour{
#Override
public void action(){
ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
msg.addReceiver(new AID("AgentB",AID.ISLOCALNAME));
msg.setContent("1000");
send(msg);
}
}
public class AgentA_ReceiveMessage extends CyclicBehaviour{
Scanner scn2 = new Scanner(System.in);
#Override
public void action(){
ACLMessage remsg = myAgent.receive();
if(remsg!=null){
String reply = remsg.getContent();
System.out.println("Reply From "+remsg.getSender()+" :- "+reply);
}
else{
block();
}
}
}
}
Agent B Class:-
public class Agent_B extends Agent{
protected void setup(){
System.out.println("Hello Seller Agent : "+getAID().getName()+" is ready.");
addBehaviour(new AgentB_ReceiveMessage());
}
public class AgentB_ReceiveMessage extends CyclicBehaviour{
#Override
public void action(){
ACLMessage remsg = myAgent.receive();
if(remsg!=null){
System.out.println(""+remsg);
ACLMessage reply = remsg.createReply();
reply.setPerformative(ACLMessage.INFORM);
String price = remsg.getContent();
reply.setContent("off");
send(reply);
}else{
block();
}
}
}
}

Android app did not receive data from SignalR hub

I already read these topics:
how to use SignalR in Android
Android Client doesn't get data but .net client getting data from SignalR server
I write a simple chat system with Android that works with SignalR.
It is supposed to the clients send messages (by calling SendMessage method on the server) and the server should call the NewMessage method on the clients.
Here is my ChatHub class (simplified) written in C#.
public class ChatHub : Hub
{
// Store the clients connections Id
static readonly List<string> _connectedClients;
public override Task OnConnected()
{
// Keep connections id
// This section works fine and when the android device connects to the server,
// Its connection id will stored.
_connectedClients.Add(Context.ConnectionId)
//... other codes
}
public void SendMessage(string message)
{
foreach (var connectionId in _connectedClients)
{
// according to the logs
// android device connection id exists here
// and it works fine.
Clients.Client(connectionId).NewMessage(message);
}
}
}
When the android client connects to the server, On the OnConnected method, the connection id will be stored in the _connectedClients and it works fine.
In the SendMessage method of the ChatHub class, We have the android device connection id, and I'm sure that the android device is within the list
And here is my Andoird codes:
public class ChatActivity extends AppCompatActivity
{
// private fields
HubConnection connection;
HubProxy hub;
ClientTransport transport;
protected void onCreate(Bundle savedInstanceState) {
Logger logger = new Logger() {
#Override
public void log(String message, LogLevel logLevel) {
Log.e("SignalR", message);
}
};
Platform.loadPlatformComponent(new AndroidPlatformComponent());
connection = new HubConnection("192.168.1.100");
hub = connection.createHubProxy("chatHub"); // case insensitivity
transport = new LongPollingTransport(connection.getLogger());
// no difference when using this:
//transport = new ServerSentEventsTransport(connection.getLogger());
// this event never fired!
hub.subscribe(new Object() {
public void NewMessage(String message)
{
Log.d("<Debug", "new message received in subscribe"); // won't work!
}
}
// this event never fired!
hub.on("NewMessage", new SubscriptionHandler() {
#Override
public void run() {
Log.d("<Debug", "new message received in `on`"); // won't work!
}
});
// connect to the server that works fine.
SignalRFuture<Void> awaitConnection = connection.start(transport);
try {
awaitConnection.get(); // seems useless when using this or not!
}
catch (Exception ex) {
}
// this method works fine.
hub.invoke("sendMessage", "this is a test message to the server")
.done(new Action<Void>() {
#Override
public void run(Void aVoid) throws Exception {
Log.d("<Debug", "message sent."); // Works fine
}
});
}
}
In the above java code, invoking the sendMessage on the server works fine and the server get the messages.
But the only problem is that the hub.on(...) or hub.subscribe(...) events are never be called by the server.
In a simple description, My app can send message, but can not receive message from the others.
Any suggestion will be appreciated.
For the futures this is the way I finally achieved the answer (please first read the question android codes):
public class ChatActivity extends AppCompatActivity
{
// private fields
HubConnection connection;
HubProxy hub;
ClientTransport transport;
protected void onCreate(Bundle savedInstanceState) {
Logger logger = new Logger() {
#Override
public void log(String message, LogLevel logLevel) {
Log.e("SignalR", message);
}
};
Platform.loadPlatformComponent(new AndroidPlatformComponent());
connection = new HubConnection("192.168.1.100");
hub = connection.createHubProxy("chatHub"); // case insensitivity
/* ****new codes here**** */
hub.subscribe(this);
transport = new LongPollingTransport(connection.getLogger());
/* ****new codes here**** */
connection.start(transport);
/* ****new codes here**** */
/* ****seems useless but should be here!**** */
hub.subscribe(new Object() {
#SuppressWarnings("unused")
public void newMessage(final String message, final String messageId, final String chatId,
final String senderUserId, final String fileUrl, final String replyToMessageId) {
}
});
/* ********************** */
/* ****new codes here**** */
/* **** the main method that I fetch data from server**** */
connection.received(new MessageReceivedHandler() {
#Override
public void onMessageReceived(final JsonElement json) {
runOnUiThread(new Runnable() {
public void run() {
JsonObject jsonObject = json.getAsJsonObject();
Log.e("<Debug>", "response = " + jsonObject.toString());
}
});
}
});
/* ********************** */
}
}
!important note:
The priority of the codes is important. this is how I fix my problem in this topic.
You does not provider parameters in your client-side which should be same as your side-site. The code should be below:
hub.on("NewMessage", new SubscriptionHandler1<String>() {
#Override
public void run(String message) {
Log.d("<Debug", "new message received in `on`");
}
},String.class); //do not forget say the String class in the end

Android Bluetooth Chat App & Sending Spotify Song Names

I'm am fairly new to Android, and I'm trying to develop an app for a small project of mine using an example Bluetooth Chat App and Spotify Media Notifications. I could not provide the links because stack overflow did not let me but they are available online with a quick google search. I was wondering why I was getting this exception and is there any solution to this?
java.lang.NullPointerException
The line numbers correspond to each of the pieces of code below:
Line 269 if (message.length() > 0)
Line 56 public class BluetoothChatFragment extends Fragment
Line 131 sendMessage(artistName);
How my code is set up:
I have a static broadcast receiver set up exactly like the Spotify link below. I grab the song name and artist and package them into strings. Then I have another broadcast receiver in my Bluetooth fragment. I used another one because I did not know how to get the string into the Bluetooth fragment because I needed to call sendMessage() a private method in the fragment class. It seems like the exception is throwing when I call sendMessage(string) in my fragment.
Static Spotify Broadcast Receiver
package com.example.android.bluetoothchat;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.example.android.common.logger.Log;
public class MyBroadcastReceiver extends BroadcastReceiver {
static final class BroadcastTypes {
static final String SPOTIFY_PACKAGE = "com.spotify.music";
static final String PLAYBACK_STATE_CHANGED = SPOTIFY_PACKAGE + ".playbackstatechanged";
static final String QUEUE_CHANGED = SPOTIFY_PACKAGE + ".queuechanged";
static final String METADATA_CHANGED = SPOTIFY_PACKAGE + ".metadatachanged";
}
#Override
public void onReceive(Context context, Intent intent) {
// This is sent with all broadcasts, regardless of type. The value is taken from
// System.currentTimeMillis(), which you can compare to in order to determine how
// old the event is.
long timeSentInMs = intent.getLongExtra("timeSent", 0L);
Intent sendBack = new Intent("Received");
String action = intent.getAction();
String artistName;
String trackName;
if (action.equals(BroadcastTypes.METADATA_CHANGED)) {
artistName = intent.getStringExtra("artist");
trackName = intent.getStringExtra("track");
String msg = "S a " + artistName + '\0';
String msg2 = "S n " + trackName + '\0';
Log.d("Song", msg);
Log.d("Artist", msg2);
sendBack.putExtra("Song", msg);
sendBack.putExtra("Artist", msg2);
} else if (action.equals(BroadcastTypes.PLAYBACK_STATE_CHANGED)) {
boolean playing = intent.getBooleanExtra("playing", false);
// Do something with extracted information
if(playing) {
Log.d("Playing", "S p\0");
sendBack.putExtra("Playing", "S p\0");
}
else {
Log.d("Playing", "S s\0");
sendBack.putExtra("Playing", "S s\0");
}
}
context.sendBroadcast(sendBack);
}
}
Broadcast Receiver in Fragment:
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String artistName = intent.getStringExtra("Song");
String trackName = intent.getStringExtra("Artist");
String playing = intent.getStringExtra("Playing");
Log.d("Please", artistName);
Log.d("Please", trackName);
Log.d("Please", playing);
sendMessage(artistName);
sendMessage(trackName);
sendMessage(playing);
}
};
sendMessage Method():
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
Any help would be much appreciated!
http://developer.android.com/samples/BluetoothChat/index.html
To me it looks like sendMessage gets called with null instead of an actual string. Note that intent.getStringExtra(some_string) can return null, if some_string cannot be found.

Categories