I know the AlarmManagerBroadcastReceiver will stay system to keep watch over SMS after I installed the .apk
Will the AlarmManagerBroadcastReceiver expend battery even if I never receive s SMS?
Do I need disable the AlarmManagerBroadcastReceiver when I stop watch SMS ?
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.enabledisablebroadcastreceiver"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.code4reference.enabledisablebroadcastreceiver.EnableDisableBroadcastReceiver"
android:label="#string/title_activity_enable_disable_boradcast_receiver" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Broadcast receiver -->
<receiver android:name="com.code4reference.enabledisablebroadcastreceiver.AlarmManagerBroadcastReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<service android:name="com.code4reference.enabledisablebroadcastreceiver.MyInternetServer"></service>
</application>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
</manifest>
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
import android.util.Log;
public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {
private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction() != null && ACTION.compareToIgnoreCase(intent.getAction()) == 0) {
Object[] pduArray = (Object[]) intent.getExtras().get("pdus");
SmsMessage[] messages = new SmsMessage[pduArray.length];
for (int i = 0; i < pduArray.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pduArray[i]);
//Log.d("CWCGR1",
// "From: " + messages[i].getOriginatingAddress()+
// " Msg: " + messages[i].getMessageBody());
HandleMsg(context,messages[i].getOriginatingAddress(), messages[i].getMessageBody());
}
}
}
private void HandleMsg(Context context,String address, String body ){
Intent msgIntent = new Intent(context,MyInternetServer.class);
msgIntent.putExtra("address", address);
msgIntent.putExtra("body", body);
context.startService(msgIntent);
}
}
import com.example.enabledisablebroadcastreceiver.R;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class EnableDisableBroadcastReceiver extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnExit=(Button)findViewById(R.id.btnExit);
btnExit.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
}
});
}
public void enableBroadcastReceiver(View view){
ComponentName receiver = new ComponentName(this, AlarmManagerBroadcastReceiver.class);
PackageManager pm = this.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
Toast.makeText(this, "Enabled broadcast receiver", Toast.LENGTH_SHORT).show();
}
public void disableBroadcastReceiver(View view){
ComponentName receiver = new ComponentName(this, AlarmManagerBroadcastReceiver.class);
PackageManager pm = this.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
Toast.makeText(this, "Disabled broadcst receiver", Toast.LENGTH_SHORT).show();
}
}
As discussed here, an incoming SMS belongs to a special group of low-level system events that will cause the CPU to wake from the battery-saving "sleep mode" (this group includes incoming calls, incoming mobile data packets and AlarmManager events). The device's GSM radio will listen to incoming SMS regardless of your broadcast receiver being set or not. When an SMS arrives, the system will choose which receiver(s) will handle it. Thus, having a SMS broadcast receiver registered has no impact in the battery consumption. Besides, energy consumption due to a registered receiver in memory is not significant.
You can unregister the broadcast receiver programmatically if there is a functional requirement to do so.
Because you have fined your AlarmManagerBroadcastReceiver in the android manifest, android will wake up your app and call the AlarmManagerBroadcastReceiver every time an sms is received.
If no SMS are received, your app won't be woken up so there won't be any impact on battery.
If you want control over when to receive those broadcasts, register and unregister your receiver programmatically through the registerReceiver(BroadcastReceiver receiver, IntentFilter filter) method on a Context (e.g. Activity).
Related
We have a requirement to show an acknoldgement screen after user share some texts on Messaging apps such as Whatsapp, Telegram, SMS etc..
We have been using the react-native-share library for this and it works fine on non Huawei devices. However, Huawei devices doesn't return success/failure when user share hence the app gives issues on Huawei devices.
Upon checking the react-native-share library internal codes, it seems the BroadcastReceiver onReceive method does not get triggered when user choose and app on HuaweiChooser.
I created the following sample code to simulate this and on Non-Huawei devices this code's onReceive method get triggered but not in Huawei devices.
Appreciate any help regarding this.
This is the Sample code
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button shareButton = findViewById(R.id.button);
shareButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent chooser;
IntentSender intentSender = MyReceiver.getIntentSender(getApplicationContext());
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
chooser = Intent.createChooser(sendIntent,"Sharing Rocks",intentSender);
chooser.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
}else{
chooser = Intent.createChooser(sendIntent,"Sharing Rocks");
}
startActivityForResult(chooser, 1234);
}
});
}
}
Receiver.Java
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
private static MyReceiver myReceiver;
private static final String EXTRA_RECEIVER_TOKEN = "receiver_token";
public static IntentSender getIntentSender(Context context){
String intentAction = context.getPackageName()+"_ACTION";
myReceiver = new MyReceiver();
context.registerReceiver(myReceiver, new IntentFilter(intentAction));
Intent intent = new Intent(intentAction);
intent.setPackage(context.getPackageName());
intent.putExtra(EXTRA_RECEIVER_TOKEN,myReceiver.hashCode());
PendingIntent callback = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return callback.getIntentSender();
}
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("//// Inside onReceive");
ComponentName target = intent.getParcelableExtra(Intent.EXTRA_CHOSEN_COMPONENT);
System.out.println("//// target : " + target);
}
}
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lk.infinitx.huaweisharetest">
<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/Theme.HuaweiShareTest">
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true"></receiver>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I change chooser title with "null" and my problem solved.
val chooser = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
Intent.createChooser(sendIntent, null, pendingIntent.intentSender)
} else {
Intent.createChooser(sendIntent, null)
}
I am trying to make a simple app which will notify if there is internet connection available or not on internet connectivity change. i have found some solution on internet and tries to implement them but somehow its not working. my broadcast receiver which i have registered on my manifest file is not calling on network connectivity change.
Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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=".NetworkStateChangeReceiver">
<intent-filter >
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
Broadcast Receiver
package com.gdm.internetconnectivitycheck;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import static android.content.Context.CONNECTIVITY_SERVICE;
public class NetworkStateChangeReceiver extends BroadcastReceiver {
public static final String NETWORK_AVAILABLE_ACTION = "com.gdm.retailalfageek.NetworkAvailable";
public static final String IS_NETWORK_AVAILABLE = "isNetworkAvailable";
#Override
public void onReceive(Context context, Intent intent) {
Intent networkStateIntent = new Intent(NETWORK_AVAILABLE_ACTION);
networkStateIntent.putExtra(IS_NETWORK_AVAILABLE, isConnectedToInternet(context));
LocalBroadcastManager.getInstance(context).sendBroadcast(networkStateIntent);
Log.e("Network Available ", "On receive called");
}
private boolean isConnectedToInternet(Context context) {
try {
if (context != null) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
return false;
} catch (Exception e) {
Log.e(NetworkStateChangeReceiver.class.getName(), e.getMessage());
return false;
}
}
}
Main Activity
package com.gdm.internetconnectivitycheck;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import static com.gdm.internetconnectivitycheck.NetworkStateChangeReceiver.IS_NETWORK_AVAILABLE;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter(NetworkStateChangeReceiver.NETWORK_AVAILABLE_ACTION);
LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
boolean isNetworkAvailable = intent.getBooleanExtra(IS_NETWORK_AVAILABLE, false);
String networkStatus = isNetworkAvailable ? "connected" : "disconnected";
Snackbar.make(findViewById(R.id.main_activity), "Network Status: " + networkStatus, Snackbar.LENGTH_LONG).show();
}
}, intentFilter);
}
}
Apps targeting Android 7.0 (API level 24) and higher must register the
following broadcasts with
registerReceiver(BroadcastReceiver,IntentFilter)
Declaring a receiver in the manifest does not work.
CONNECTIVITY_ACTION
Beginning with Android 8.0 (API level 26), the
system imposes additional restrictions on manifest-declared receivers.
If your app targets API level 26 or higher, you cannot use the
manifest to declare a receiver for most implicit broadcasts
(broadcasts that do not target your app specifically). You can still
use a context-registered reciever when the user is actively using your
app.
directly from official doc.
you need to register for CONNECTIVITY_CHANGE action at runtime from activity.
using registerReceiver.
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(new NetworkStateChangeReceiver(), filter);
And don't forget to unregister.
I have been working on an application that use to receive SMS and show a Toast using Broadcast Receiver and i have an activity with no purpose, when i removed that activity and build the apk and run on my phone, application is not responding when SMS is received (no Toast showing), although remaining code is same as it was previously. Can anyone help please i am so stuck and couldn't help myself reading hundreds of answers. I studied i should create a service but still no Toast is appearing. below is my code. I can not have any GUI in my application even don't want to have auto kill activity.
BroadcastReceiver.java
package com.test.testservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsReceiver extends BroadcastReceiver {
public static final String SMS_BUNDLE = "pdus";
private static final String LOG = "SmsBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Bundle intentExtras = intent.getExtras();
if (intentExtras != null) {
Object[] sms = (Object[]) intentExtras.get(SMS_BUNDLE);
if (sms != null)
{
String smsMessageStr = "";
for (int i = 0; i < sms.length; ++i)
{
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
String smsBody = smsMessage.getMessageBody().toString();
String address = smsMessage.getOriginatingAddress();
smsMessageStr += "SMS From: " + address + "\n";
smsMessageStr += smsBody + "\n";
}
Toast.makeText(context, smsMessageStr, Toast.LENGTH_LONG).show();
//MyService objService=new MyService();
//objService.startService(intent);
//objService.stopService(intent);
Intent myIntent = new Intent(context, MyService.class);
//myIntent.putExtra("Sender", Sender);
//myIntent.putExtra("Fullsms", Fullsms);
context.startService(myIntent);
}
}
}
}
MyService.java
package com.test.testservice;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private static final String LOG = "MyService";
#Override
public boolean stopService(Intent name) {
if (super.stopService(name))
{
Toast.makeText(this,"HELLO stopService",Toast.LENGTH_LONG).show();
Log.i(LOG, "stopService");
return true;
}
else return false;
}
#Override
public ComponentName startService(Intent service) {
return super.startService(service);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this,"HELLO onCreate",Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this,"HELLO onStart",Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.testservice">
<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">
<receiver android:name=".SmsReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.REBOOT"/>
</intent-filter>
</receiver>
</application>
<service android:name="com.test.testservice.service.MyService"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</manifest>
Unless you are creating your own phone, or your own custom ROM, you need the activity. Your BroadcastReceiver will not work when your app is first installed. It will only start to work once the user has launched your activity (or something else uses an explicit Intent to start one of your components).
I can not have any GUI in my application
Then your app will not work on Android 3.1+ devices, which make up the vast majority of the Android device ecosystem.
I want to receive notification when the messages arrives with using Broadcast Receiver. I wrote this code but it doesnt work;
I added this code in my AndroidManifest class;
<receiver android:name=".receiver.SMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
And my SMSReceiver class;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle pudsBundle = intent.getExtras();
Object[] pdus = (Object[]) pudsBundle.get("pdus");
SmsMessage messages = SmsMessage.createFromPdu((byte[]) pdus[0]);
Toast.makeText(context, "New SMS: " + messages.getMessageBody(),
Toast.LENGTH_LONG).show();
Log.d(getClass().getName().toString(), "SMS Arrived");
}
}
This code must show me a Toast Message when SMS arrived. How can i fix this problem?
Thank you.
You must have the permissions:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
If you want to send sms you will need permission :
<uses-permission android:name="android.permission.SEND_SMS" />
I think you need to register your broadcast receiver. Hope for help.
#Override
public void onResume() {
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));
}
I try to implement the network receiver, here is my following code:
package com.example.androidtablayout;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
public class NetworkReceiver extends BroadcastReceiver { // <1>
public static final String TAG = "NetworkReceiver";
boolean isConnected = true;
Context c;
#Override
public void onReceive(Context context, Intent intent) {
boolean isNetworkDown = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); // <2>
if (isNetworkDown) {
Log.d(TAG, "onReceive: NOT connected, stopping UpdaterService");
// context.stopService(new Intent(context, UpdaterService.class)); // <3>
} else {
Log.d(TAG, "onReceive: connected, starting UpdaterService");
// context.startService(new Intent(context, UpdaterService.class)); // <4>
}
}
}
In the Manifest.xml
<application>
<receiver android:name=".NetworkReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
My problem is when I switch off the wifi, the log still shows that "Connected",
I think the the network receiver didn't receiver the intenet connectivity correctly.Any help will be greatly appreciated.
Here is a sample class that shows you how to do it. I think this is exactly what you need and it might help resolve your issue. In this sample the BroadcastReceiver is registered programmatically instead of the Manifest, but I think it won't be a problem for you.
Let me know if works.