I am new to android programming and I am trying to build an app which changes the profile on receiving a message from the user. The app basically has one activity and a broadcast receiver. I am prompting the user to set a password for changing the profile and the password is saved in a Shared Preference which I am using inside MainActivity. I am not able to retrieve the password stored in shared preference in the broadcast receiver class.Also, I can only use Shared Preference for storing the password.The code for MainActivity , Broadcast Receiver , layout and Android manifest file is given below. Thanks a lot for your help.
MainActivity.java
public class MainActivity extends AppCompatActivity {
public EditText setPass;
public Button submit;
public static String password;
SharedPreferences sharedPreferences;
boolean b=false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setPass=(EditText)findViewById(R.id.setPassEditId);
submit=(Button)findViewById(R.id.submitButtonId);
sharedPreferences= getApplicationContext().getSharedPreferences("Pritom",Context.MODE_PRIVATE);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
password=setPass.getText().toString();
SharedPreferences.Editor editor=sharedPreferences.edit();
editor.putString("password",password);
editor.commit();
Toast.makeText(getApplicationContext(),"Password saved successfully"+password,Toast.LENGTH_LONG).show();
//b=sharedPreferences.contains("password")?true:false;
//Toast.makeText(getApplicationContext(),"b:"+b,Toast.LENGTH_LONG).show();
}
});
}
}
Here,in MainActivity class the variable b returns true which means that the shared preference exists.
MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
public AudioManager audioManager;
public String me = "";
public String last = "";
public static final String SMS_BUNDLE = "pdus";
public SharedPreferences sharedPreferences;
public static final String MyPREFERENCES = "MyPrefs";
boolean b = false;
#Override
public void onReceive(Context context, Intent intent) {
sharedPreferences = context.getSharedPreferences("Pritom", context.MODE_PRIVATE);
String pass3 = sharedPreferences.getString("password", null);
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "n";
String smsBody = msgs[i].getMessageBody().toString();
if (smsBody.equals("#general" + pass3)) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setRingerMode(audioManager.RINGER_MODE_NORMAL);
}
}
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}
The problem here is that pass3 which retrieves the value from shared preference returns nothing for which the if statement for checking the message does not work.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
Please help me. Thank you.
//Inside onReceive method
sharedPreferences = context.getSharedPreferences("Pritom", context.MODE_PRIVATE);
// Instead of this line, use
sharedPreferences= getApplicationContext().getSharedPreferences("Pritom", Context.MODE_PRIVATE);
There is possibility that you receives broadcast before setting up password.
Broadcast receiver registered on SMS received that means it calls when SMS received.
What when sms is received and you still don't assign password to shared preference? In that case you are not able to get password from preference.
Please check that scenario and make some changes to that.
Related
I have to make a simple App for school.
It has to show a toast when a call is received.
The phone call receiver doesn't display anything.
I have this in my manifest, so permissions shouldn't be the issue
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<receiver
android:name=".ReceptorLlamadas"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
The code for my broadcastReceiver
public class ReceptorLlamadas extends BroadcastReceiver {
Context context;
#Override
public void onReceive(Context c, Intent intent) {
try {
TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
LlamadaListener listener = new LlamadaListener();
manager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
Log.e("PhoneCallError", "onReceive: ", e);
}
}
private class LlamadaListener extends PhoneStateListener {
public void onCallStateChanged(int state, String phoneNumber) {
if (state == 1) {
String mensaje = "Llamada entrante del número: " + phoneNumber;
int duracion = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, mensaje, duracion);
toast.show();
}
}
}
}
Sorry if I messed up the formatting
Edit: forgot to include some code
You need to declare Broadcast Receiver in Android Manifest as well just like this in Application tag:
<receiver
android:name=".ReceptorLlamadas"
android:enabled="true" />
I have my main activity that start a service (Location service) and I want that service to broadcast the new location each time a new location is found.
Thanks to the log I know the service is working and I have new locations every seconds or so, but I never get the broadcast.
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = "mainActivity";
private CMBroadcastReceiver mMessageReceiver = new CMBroadcastReceiver();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// Start Service
startService(new Intent(this, LocationService.class));
super.onCreate(savedInstanceState);
}
#Override
public void onResume()
{
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, new IntentFilter(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE));
super.onResume();
}
#Override
public void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
}
CMBroadcastReceiver.java
public class CMBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CMBroadcastReceiver";
public static final String RECEIVE_LOCATION_UPDATE = "LOCATION_UPDATES";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received broadcast");
String action = intent.getAction();
if (action.equals(RECEIVE_LOCATION_UPDATE))
{
Log.i(TAG, "Received location update from service!");
}
}
}
LocationService.java
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.i(TAG, "onLocationChanged " + location);
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Log.i(TAG, "Broadcast sent");
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyclemapapp.gpstracker">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar">
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LocationService" android:process=":location_service" />
</application>
I the log I can see that "Broadcast Sent" But I never get the "Broadcast Received"
Any help will would be greatly appreciated.
EDIT:
Edited how the intent was created in the location service as Shaishav suggested.
Still doesn't work.
LocalBroadcastManager does not work across processes. Your Service is running in a separate process.
You can either run your Service in the same process as the Activity - by removing the process attribute from the <service> element - or use some sort of IPC instead - e.g., by sending and receiving the broadcasts on a Context instead of LocalBroadcastManager.
In your LocationService, send local broadcast using:
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
<service android:name=".LocationService" android:process=":location_service" />
Your service is in a separate process from the activity. LocalBroadcastManager is only for use in one process. Either remove android:process from the <service>, or use some IPC mechanism (e.g., system broadcasts, properly secured).
Im trying to create a notification from an edittext and broadcast receiver. In my first Activity the user should input a message and push the broadcast button. I want to take that string and create a notification from it and open a new activity that displays the message. I am doing all the notification work in my broadcast receiver class.
I have looked around onlne at examples and other peoples code but im not sure what im not getting right. The application loads up just fine and the broadcast button sends the broadcast to the receiver and Logs the string but the notification is never created.
Thanks for any help.
Broadcast class that sends broadcast message:
public class BroadcastReceiverActivity extends Activity
{
EditText et;
Button btn1;
public static String BString = "HappyHemingway";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast_receiver);
et = (EditText)findViewById(R.id.et1);
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String message = et.getText().toString();
send(message);
}
});
}
/*
* This function creates an intent and
* sends a broadcast from the message
* parameter passed in.
*/
protected void send(String msg)
{
Log.i("msg", msg);
Intent i = new Intent();
i.putExtra("message",msg);
i.setAction(BString);
sendBroadcast(i);
}
}
Receiver class that creates notification:
public class Receiver extends BroadcastReceiver
{
// #SuppressLint("NewApi")
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action!=null&&action.equals("HappyHemingway"))
{
String msg = intent.getStringExtra("message");
Log.i("Received",msg);
Intent i = new Intent(context,ViewNotification.class);
i.putExtra("message",msg);
PendingIntent pi = PendingIntent.getActivity(context, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(context).
setSmallIcon(0).setAutoCancel(true).setTicker(msg).
setWhen(System.currentTimeMillis()).setContentTitle("New Notification!").
setContentText(msg).setContentIntent(pi);
NotificationManager mgr = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification n = builder.build();
mgr.notify(0, n);
Log.i("Received again",msg);
}
}
}
notification viewer class that is never launched
public class ViewNotification extends Activity
{
String text;
TextView txttext;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.viewnotification);
NotificationManager notificationmanager;
notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationmanager.cancel(0);
Intent i = getIntent();
text = i.getStringExtra("message");
txttext = (TextView) findViewById(R.id.text);
txttext.setText(text);
Log.i("made it", "made it made it made it");
}
}
manifest
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".BroadcastReceiverActivity"
android:label="#string/app_name" >
<action android:name="android.intent" />
<category android:name="android.intent.category.LAUNCHER" />
</activity>
<activity android:name=".ViewNotification"></activity>
<receiver android:name="Receiver">
<intent-filter>
<action android:name="HappyHemingway">
</action>
</intent-filter>
</receiver>
</application>
</manifest>
Hopefully its just a simple error I'm overlooking.This is my first time using Android Studio instead of Eclipse but I dont see how that could make any difference under than my unfamiliarity with the IDE.
Anything helps
thanks.
I'm not sure why I had setSmallIcon(0.)
When I changed it to setSmallIcon(R.drawable.ic_launcher) everything worked fine.
Is there any way to develop an app that starts up when a user receives a phone call? I can't really go into details about the idea but was wondering if there was some call that would allow that to happen.
You can use a Broadcast Receiver for thatlike this
public class PhoneStatReceiver extends BroadcastReceiver{
private static final String TAG = "PhoneStatReceiver";
private static boolean incomingFlag = false;
private static String incoming_number = null;
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){
incomingFlag = false;
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i(TAG, "call OUT:"+phoneNumber);
}else{
TelephonyManager tm = (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);
switch (tm.getCallState()) {
case TelephonyManager.CALL_STATE_RINGING:
incomingFlag = true;//标识当前是来电
incoming_number = intent.getStringExtra("incoming_number");
Log.i(TAG, "RINGING :"+ incoming_number);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if(incomingFlag){
Log.i(TAG, "incoming ACCEPT :"+ incoming_number);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if(incomingFlag){
Log.i(TAG, "incoming IDLE");
}
break;
}
}
}
}
Register this receiver in AndroidManifest like this
<receiver android:name=".filter.PhoneStatReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission>
Yes We can start an diffrent app when User receives a phone call.Example :- Truecaller,Mobile no. Tracker apps.
You can use Services for this.
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
final Context cont = context;
final Intent in = intent;
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(cont, MainActivity.class);
i.putExtras(in);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
cont.startActivity(i);
}
}, 1000);
}
}
}
You must implement this handler with postDelayed so that your activity screen can be on top of native call screen. If you dont want this to happen then you must remove this handler.
Add these to your manifest--
<receiver
android:name=".CallReceiver"
android:enabled="true" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
and
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_INCOMING_CALLS" />
You have to use another extra_state for onreceiving call. This is for ringing state.
I am using getHotelName() and setHotelName() to store data in the application and then access it. In my main activity that is categorized as Launcher both the methods and the getApplication() works in this activity. But when I try to access the getApplication from a different activity which is called from the main activity it gives a force close error.
This is my manifest file :
<application android:icon="#drawable/icon" android:label="#string/app_short_name" android:name="RestaurantNetwork" android:allowClearUserData="true" android:theme="#android:style/Theme.Black" >
<activity android:name="RestaurantActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="NetworkCommunication"></activity>
<uses-permission android:name="android.permission.INTERNET" />
</application>
In the main activity
RestaurantNetwork application = (RestaurantNetwork) getApplication();
application.setHotelName(this.hotelname.getText().toString());
Intent intent = new Intent(view.getContext(), NetworkCommunication.class);
startActivity(intent);
In the NetworkCommunication activity
public class NetworkCommunication extends Activity {
RestaurantNetwork application = (RestaurantNetwork) getApplication();
String hotelname = application.getHotelName().toString();
#Override
public void onCreate(Bundle savedInstanceState) {
I solved it using intent.extra, yes i had to get rid of the getApplication(). Would still like to know why there was an error in the prev method
in my main activity
this.hotelname = (EditText) findViewById(R.id.HotelName);
//RestaurantNetwork application = (RestaurantNetwork)getApplication();
//application.setHotelName(this.hotelname.getText().toString());
Intent intent = new Intent(view.getContext(), NetworkCommunication.class);
intent.putExtra("hotelName",this.hotelname.getText().toString());
startActivity(intent);
in my second activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.searchresults);
String value = null;
Bundle extras = getIntent().getExtras();
if(extras !=null)
{
value = extras.getString("hotelName");
}
Toast.makeText(getApplicationContext(),value, Toast.LENGTH_SHORT).show();