I'm studying Android.
I try to implement a Custom static Broadcast Receiver but it is not working.
I search for some issue from Google but I can't find something to solve this.
I work on Android 7.0 Min Level 24 Target Level 28
In fact, MyStaticReceiver isn't launching when I start the Activity (no log)
MyDynamicReceiver work perfectly
Do you have a solution?
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.receiver">
<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="test.receiver.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyStaticReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="#string/StaticAction" />
</intent-filter>
</receiver>
</application>
</manifest>
MainActivity.java :
public class MainActivity extends Activity {
public final static boolean Debug = true;
public final static String TAG = "TagDebug";
private MyDynamicReceiver dynamicReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ComponentName receiver = new ComponentName(this, MyStaticReceiver.class);
PackageManager pm = this.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
#Override
protected void onResume() {
super.onResume();
if (Debug) Log.i(TAG, "MainActivity:onResume");
configureDynamicReceiver();
}
#Override
protected void onDestroy(){
super.onDestroy();
if (Debug) Log.i(TAG, "MainActivity:onDestroy");
unregisterReceiver(dynamicReceiver);
}
public void onClickButton(View v) {
if (Debug) Log.i(TAG, "MainActivity:onClickButton");
Intent staticIntent = new Intent();
staticIntent.setAction(getString(R.string.StaticAction));
sendBroadcast(staticIntent);
Intent dynamicIntent = new Intent();
dynamicIntent.setAction(getString(R.string.DynamicAction));
sendBroadcast(dynamicIntent);
}
public void configureDynamicReceiver() {
if( dynamicReceiver == null ) {
dynamicReceiver = new MyDynamicReceiver();
}
IntentFilter filter = new IntentFilter(getString(R.string.DynamicAction));
registerReceiver(dynamicReceiver, filter);
}
}
MyStaticReceiver.java (MyDynamicReceiver is the same ...)
public class MyStaticReceiver extends BroadcastReceiver {
public final static boolean Debug = true;
public final static String TAG = "TagDebug";
public MyStaticReceiver() {
if (Debug) Log.i(TAG, "MyStaticReceiver");
}
#Override
public void onReceive(Context context, Intent intent) {
if (Debug) Log.i(TAG, "MyStaticReceiver:onReceive");
}
}
You are actually sending an implicit broadcast, therefore the receiver declared in the manifest will not work.
If your app targets Android 8.0 (API level 26) or higher, you cannot use the manifest
to declare a receiver for most implicit broadcasts (broadcasts that
don't target your app specifically). You can still use a
context-registered receiver when the user is actively using your app. Link
You don't face any issue with MyDynamicReceiver because it is context-registered receiver.
But to make it work for MyStaticReceiver, you can try sending an explicit broadcast by passing the component name in the constructor of the Intent.
Intent staticIntent = new Intent(this, MyStaticReceiver.class);
staticIntent.setAction(getString(R.string.StaticAction));
sendBroadcast(staticIntent);
Related
I'm stuck with something that seems easy. I want to create a simple app that contains of two buttons: one to start a service and a second one to stop it. I've created my NotifyService class:
public class NotifyService extends Service {
public NotifyService() {
}
private static final String SMS_RECEIVED="android.provider.Telephony.SMS_RECEIVED";
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
displayNotification(intent);
}
};
private void displayNotification(Intent intent)
{
if(intent.getAction().equals(SMS_RECEIVED)) {
int NOTIFICATION=R.string.local_service_started;
//notification creating
Notification.Builder notificationBuilder = new Notification.Builder(this)
.setContentText("Otrzymano smsa!")
.setContentTitle("SMS!")
.setSmallIcon(android.R.drawable.btn_plus);
Notification note = notificationBuilder.build();
//getting system service
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//displaying notification
notificationManager.notify(NOTIFICATION, note);
}
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
#Override
public void onCreate() {
super.onCreate();
registerReceiver(broadcastReceiver,new IntentFilter(SMS_RECEIVED));
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
And here's the code for my MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startServiceBtn(View view)
{
Intent intent = new Intent(this,NotifyService.class);
startService(intent);
}
public void stopServiceBtn(View view)
{
Intent intent = new Intent(this,NotifyService.class);
stopService(intent);
}
And the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.pablo.myapplication" >
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<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" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".NotifyService"
android:enabled="true"
android:exported="true" >
</service>
</application>
Unfortunately, every time I'm simulating a sending of an sms through Android Device Monitor, it doesn't work, it shows me the default system notification (that by the way is shown even without the permission in manifest- ist that right behavior?)
EDIT:
In Android Device Monitor it still keeps showin Permission Denial: ... requires android.permission.RECEIVE_SMS due to sender.com android.... Yet, I've added this into intent filter, then I don't know why it's happening.
The answer to this question was related to some other matters with permissions that I had last times and it's connected with new permission politics with Marshmallow. More info here.
So the problem can be solver by switching to lower sdk version or calling appriopriate methods (look into above link) in runtime.
The function "onReceive" is called when BroadcastReceiver is Registered in the Manifest but NOT called if registered dynamically.
The code that works is below:
public class EyeGesture extends BroadcastReceiver {
//Eye Gesture
private static IntentFilter eyeGestureIntent;
private static Context eyeGestureContext;
private static StringBuilder gestureInfo = null;
private static BroadcastReceiver broadcastReceiver;
// public void startEyeListening() {
//Eye Gesture
//}
#Override
public void onReceive(Context context, Intent intent) {
// this = context;
if (intent.getStringExtra("gesture").equals("WINK")) {
Log.e("WINKED ","");
}else {
Log.e("SOMETHING", "is detected " + intent.getStringExtra("gesture"));
}
//Disable Camera Snapshot
// abortBroadcast();
}
public void stopEyeListening() {
eyeGestureContext.unregisterReceiver(broadcastReceiver);
eyeGestureIntent = null;
eyeGestureContext = null;
gestureInfo = null;
}
}
Below is the Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.inno.inno.glassplugin" >
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainFunct"
android:icon="#drawable/ic_glass_logo"
android:label="#string/title_activity_main_funct" >
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger" />
</activity>
<receiver android:name="com.inno.inno.glassplugin.EyeGesture">
<intent-filter>
<action android:name="com.google.android.glass.action.EYE_GESTURE" />
</intent-filter>
</receiver>
</application>
</manifest>
The problem is that "onReceive" is NOT called when registered dynamically. I have to do this in a dynamic way.
Below is the code that is NOT working code.
public class EyeGesture extends Activity {
//Eye Gesture
IntentFilter eyeGestureIntentFilter;
Context eyeGestureContext;
BroadcastReceiver broadcastReceiver;
public EyeGesture(){
Log.e("CONSTRUCTOR ", "");
eyeGestureContext = MainFunct.getCurrentContext();
eyeGestureIntentFilter = new IntentFilter("com.google.glass.action.EYE_GESTURE");
eyeGestureIntentFilter.setPriority(1000);
startRunning();
}
void startRunning(){
eyeGestureContext.registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("Received ", " Something");
}
},eyeGestureIntentFilter);
}
#Override
public void onResume(){
super.onResume();
}
#Override
public void onPause(){
super.onPause();
unregisterReceiver(broadcastReceiver);
}
public void stopEyeListening() {
eyeGestureContext.unregisterReceiver(broadcastReceiver);
eyeGestureIntentFilter = null;
eyeGestureContext = null;
}
}
Also, I don't want to extend BroadcastReceiver from this class. Why am I not receiving anything if registered dynamically. I also removed the following line from the Manifest:
<receiver android:name="com.inno.inno.glassplugin.EyeGesture">
<intent-filter>
<action android:name="com.google.android.glass.action.EYE_GESTURE" />
</intent-filter>
</receiver>
but still, it is not working. There is no error or exception thrown.
What am I doing wrong?
Are you using explicit intent? It seems that dynamically registered broadcast receivers cannot receive explicit intents. Implicit intents work.
For reference: http://streamingcon.blogspot.com/2014/04/dynamic-broadcastreceiver-registration.html
If the issue is not explicit intents but if you are using LocalBroadcastManager for sendBroadcast then make sure that the registerReceiver is also called of LocalBroadcastManager and not of Context
Try using ApplicationContext instead of Activity.
Modyifing line:
eyeGestureContext = MainFunct.getCurrentContext();
I would try things in this order:
eyeGestureContext = getApplicationContext();
eyeGestureContext = getApplication();
If above does not work I would extend the Application and do:
public class MyExtendedApplication extends Application {
private static MyExtendedApplication instance;
public static MyExtendedApplication getInstance() {
return instance;
}
}
This works for me with global "android.net.conn.CONNECTIVITY_CHANGE" broadcast
Context c = MyExtendedApplication.getInstance();
c.registerReceiver(
connectivtyChangedReceiver,
connectivityFilter);
so should also for you with "com.google.android.glass.action.EYE_GESTURE"
Watching adb logcat in XE21.3, it looks like com.google.android.glass.action.EYE_GESTURE intent never hits the event bus; instead, it skips straight to com.google.glass.action.TAKE_PICTURE, which is the same intent as the camera button. So it looks like the eye-gesture API was removed without announcement.
The receiver should extend the BroadcastReceiver class.
Define the receiver in the manifest
In the code (maybe onCreate), register the receiver
Create a receiver object
Define the intent filters
call RegisterReceiver() passing in the receiver and the intent filters
I'm developing an app and i need another external application with a broadcast receiver only. Here is my code:
app1:
Intent intent = new Intent();
intent.setAction("com.blabla.myaction");
intent.putExtra("extra", "test");
sendBroadcast(intent);
app2 (The one with the receiver):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.test" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<receiver
android:name=".myReceiver">
<intent-filter>
<action android:name="com.blabla.myaction" />
</intent-filter>
</receiver>
</manifest>
public class myReceiver extends BroadcastReceiver {
private Context mContext;
public static final String ACTION = "com.blabla.myaction";
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
if (ACTION.equals(intent.getAction())) {
Log.e("lala", "received");
String extra = intent.getStringExtra("extra");
if (packageName != null) {
Log.e("lala", extra);
}
}
}
With this, i doesn't get the "received" log nor the extra. Why?
You "recieving application has to have been started at least once.
You may want to review https://developer.android.com/reference/android/content/BroadcastReceiver.html.
My English is poor. I cannot start an android service in a boot time and I do not know the problem. I was trying example codes, but without success. Can somebody send me a project in Java that runs? Other code works for other people but on my tablet smartphone emulator it does not work. Does a problem exist in android 4.0?
This is my code:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.service22"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="internalOnly"
>
<supports-screens android:largeScreens="false" android:normalScreens="true" android:smallScreens="false"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application android:icon="#drawable/ic_launcher" android:label="#string/app_name">
<service android:name="com.example.MyService">
<intent-filter>
<action android:name="com.example.MyService">
</action>
</intent-filter>
</service>
<receiver android:name="com.example.MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED">
</action>
<category android:name="android.intent.category.HOME">
</category>
</intent-filter>
</receiver>
</application>
</manifest>
public class MyService extends Service
{
private static final String LOG_TAG = "::Monitor";
#Override
public void onCreate() {
super.onCreate();
Log.e(LOG_TAG, "Service created.");
}
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
for (int i = 0 ; i < 20 ; i++)
{
mensaje();
}
Log.e(LOG_TAG, "Service started.");
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.e(LOG_TAG, "Service destroyed.");
}
#Override
public IBinder onBind(Intent intent)
{
Log.e(LOG_TAG, "Service bind.");
return null;
}
public void mensaje()
{
Toast.makeText(this, "Hola", Toast.LENGTH_LONG).show();
}
}
public class MyReceiver extends BroadcastReceiver
{
public MyReceiver()
{
}
String LOG_TAG = "::StartAtBootServiceReceiver";
#Override
public void onReceive(Context context, Intent intent)
{
Log.e(LOG_TAG, "onReceive:");
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent i = new Intent();
i.setAction("com.example.MyService");
context.startService(i);
}
}
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class OnBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("OnBootReceiver", "Hi, Mom!");
}
}
and manifest file
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:icon="#drawable/cw"
android:label="#string/app_name">
<receiver android:name=".OnBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
I think:
Intent i = new Intent();
i.setAction("com.example.MyService");
context.startService(i);
is not enough,you must set intent class name like that:
Intent i = new Intent();
i.setClassName("com.example", "com.example.MyService");
i.setAction("com.example.MyService");
context.startService(i);
pls try that.
IMPORTANT: Android OS 3.1+ remains ignorent about your broadcast receivers in following cases:
1.User has never started the application explicitly at least once.
2.User has "force closed" the application.
Issue has nothing to do to your implementation. This is a potential security hole in Android that Google has closed :)
I try to play with Service in Android, my application contain an Activity with a button so that it can do action when I press it.
The core component is the ExtractingURLService , which extends IntentService framework class.
I have overrided the onHandleIntent() method, so that it can handle intent passed to it properly.
Code:
public class ExtractingURLService extends IntentService {
private static final String TAG = "ExtractingURLService";
public ExtractingURLService(String name) {
super("ExtractingURLService");
}
#Override
protected void onHandleIntent(Intent intent) {
// do something here !
}
}
}
The Android Manifest file is :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="example.service.urlextraction"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.INTERNET"/>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".ServiceExample02Activity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ExtractingURLService" android:enabled="true"></service>
</application>
</manifest>
In my only Activity class, I call the service by using:
Intent startServiceIntent = new Intent(this, ExtractingURLService.class);
startService(startServiceIntent);
That's all my work, but when deploy, the runtime error I received was:
04-09 16:24:05.751: ERROR/AndroidRuntime(1078): Caused by:
java.lang.InstantiationException:
example.service.urlextraction.ExtractingURLService
What I should do with that ??
Add full path of Service
<service android:name="com.foo.services.ExtractingURLService" android:enabled="true"></service>
Intent Service should look like this:
package com.foo.services;
import android.app.IntentService;
import android.content.Intent;
public class ExtractingURLService extends IntentService {
private static final String TAG = "ExtractingURLService";
public ExtractingURLService() {
super("ExtractingURLService");
}
#Override
protected void onHandleIntent(Intent intent) {
// do something here !
}
}
You can add try and catch block to avoid crash.Its work for me
try {
Intent intent = new Intent(DashboardActivity.this, MyService.class);
startService(intent);
}catch (IllegalStateException e){
}catch (Exception ee){
}