Android Activity Not Found Exception and BroadcastReceiver - android

i have some functionality in my program i want to expose but i did't seem to get the receiver working.
i tried the Manifest/Receiver:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nohkumado.intstringsynchro" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:resizeableActivity = "true">
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".IntStringReceiver" android:exported="true" android:enabled="true">
<intent-filter>
<action android:name="com.nohkumado.intstringsynchro.EDIT_STRINGXML"/>
</intent-filter>
<intent-filter>
<action android:name="com.nohkumado.intstringsynchro.ADD_STRINGXML"/>
<action android:name="com.nohkumado.intstringsynchro.DEL_STRINGXML"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</receiver>
</application>
</manifest>
package com.nohkumado.intstringsynchro;
import android.content.*;
import android.widget.*;
import android.util.*;
public class IntStringReceiver extends BroadcastReceiver
{
public static final String TAG = "Receiver";
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Intent Detected:"+intent.getAction(), Toast.LENGTH_LONG).show();
switch (intent.getAction())
{
case "com.nohkumado.intstringsynchro.EDIT_STRINGXML":
{
Intent intentStartMainActivity = new Intent(context, MainActivity.class);
intentStartMainActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentStartMainActivity);
break;
}
case("com.nohkumado.intstringsynchro.ADD_STRINGXML"):
{
Toast.makeText(context, "add token "+intent.getExtras(), Toast.LENGTH_LONG).show();
break;
}
case("com.nohkumado.intstringsynchro.DEL_STRINGXML"):
{
Toast.makeText(context, "del token "+intent.getExtras(), Toast.LENGTH_LONG).show();
break;
}
default:
{
Toast.makeText(context, "no idea what to do with "+intent, Toast.LENGTH_LONG).show();
Log.d(TAG,"no idea what to do with "+intent);
}//default
}// switch (intent.getAction())
}// public void onReceive(Context context, Intent intent)
}//class
as pointed out,i had, erroneously, in the receiver part put a
<category android:name="android.intent.category.DEFAULT"/>
which meant that in the best case only the first intent filter got fired, and not the others.... removed that
now as an other app, i created a small Tester, it has only 3 buttons to trigger the 3 actions i want to pass on as intents, since it was only a small test, i bound the onClick event in the layout file:
package com.nohkumado.istester;
import android.app.*;
import android.content.*;
import android.net.*;
import android.os.*;
import android.view.*;
import android.widget.*;
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}//onCreate
public void callIntString()
{
callIntString(null);
}
public void callIntString(View but)
{
Toast.makeText(this, "call int string", Toast.LENGTH_SHORT).show();
String name="com.nohkumado.intstringsynchro.EDIT_STRINGXML";
Intent callIt = new Intent(name);
try
{
startActivity(callIt);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(this, "no available activity"+callIt, Toast.LENGTH_SHORT).show();
//callGooglePlayStore();
}
}
private void callGooglePlayStore()
{
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.android.vending");
ComponentName comp = new ComponentName("com.android.vending", "com.google.android.finsky.activities.LaunchUrlHandlerActivity"); // package name and activity
launchIntent.setComponent(comp);
launchIntent.setData(Uri.parse("market://details?id=com.nohkumado.intstringsynchro"));
startActivity(launchIntent);
}//callIntString
}
and here was my understanding problem, instead of using startActivity, i should have tried sendBroadcast(launchIntent);
Ok, to close this up...
first, i was not completely aware, that the activity contract in the manifest, opens a way for anyone to call on this activity.
Next, i have a specific application, that i want to open up to others, meaning editing the strings.xml files of android projects, and i wanted to propose the equivalent of a REST API, with LIST/EDIT, ADD, DEL.
Now, if we work with activities, the easiest way to get a handle on my activity from outside is, i think, like this:
Intent call = pm.getLaunchIntentForPackage("com.nohkumado.intstringsynchro");
followed by some putExtra calls to insert a token identifying a specific action, and an eventual value to perform on....
finished by a startActivity
this way, the default activity is started, regardless of its name, and the intent passed on, that can be read in the onCreate method of the MainActivity.
To implement my REST API, i tryed to make 3 entry points to my app, one for each type of access, only the LIST/EDIT firing up a UI, the 2 others spawning a series of Asynctasks doing the work in background. But this meant, that an eventual user has to know wich activities to address.
So i reverted to using the putExtra of the intent with a token/value pair to implement my REST-like API.....
For educations sake i tryed out the way over the broadcast mechanism, the advantage beeing that on the client side there seems no risk of crash, no need to catch a ActivityNotFound Exception, and, from a typo in my code, i noticed that the intent activity doesn't need to be bound to my actual app, i can choose any name i want.
For this, on the client side i needed to :
String name="com.nohkumado.intstringsynchro.EDIT_STRINGXML";
Intent callIt = new Intent(name);
sendBroadcast(callIt);
but on my app side i need to implement a complete BroadCastreceiver....
On the other side, this mechanism was extremely slow, giving the whole operation a very sluggish feel
Please correct me if i got it right this time, and i am open to suggestions if there a better ways to achieve my goal to propose to others those LIST/EDIT, ADD and REMOVE functionalities?

the reports back an activity not found exception
Apparently, you do not have an activity with an <intent-filter> for an action string of com.nohkumado.intstringsynchro.EDIT_STRINGXML. Your manifest in the question certainly does not have such an activity. Your manifest in the question has a <receiver> element with an odd <intent-filter> that, among other things includes that action. However, <receiver> and <activity> are not the same thing.
Either change your code to send a broadcast, or change your code to have an activity with that action string.

Related

Can't close Android app after restart

I have MainActivity declared with following HOME, DEFAULT category, and MAIN Action. I also do select the app as default launcher. When I click back press it closes MainActivity as expected. But if I leave MainActivity running and restart the device, I cannot get out of MainActivity! Pressing onBackPress() in which I call finish(), pauses the activity as expected. But then I see onCreate called(), onResume() and MainActivity is back up like a clown! What I can do? This only happens after restart of device when activity is left running.
I'm doing everything I can to get rid of this activity including inside
onBackPressed(){
ActivityCompat.finishAffinity(MainActivity.this);
finish();
}
I have seen suggestion to FLAG_ACTIVITY_CLEAR_TOP but its the OS that starts the Activity in the first place, not me.
I cannot leave the app at all!
Add this code in your onBackPressed() method.
Intent intentExit = new Intent(Intent.ACTION_MAIN);
intentExit.addCategory(Intent.CATEGORY_HOME);
intentExit.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intentExit);
finish();
This is just an idea, don't know whether it will work perfectly
Try creating a broadcast receiver
Get the event of phone restart
Close the app
In Manifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
BootCompleteReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.putExtra("close_activity",true);
context.startActivity(i);
}
}
MainActivity.java add this block
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(intent.getBooleanExtra("close_activity",false)){
this.finish();
}
}
References:
Android BroadcastReceiver, auto run service after reboot of device
Close application from broadcast receiver

Callback from BroadcastReceiver beetwen Apps?

I want to allow other Apps to integrate with mine and I'm writing a dummy "consumer" app but I cant achieve to return a callback to notify the "consumer" app if everything went well.
So my DUMMY_APP has a simple layout with 2 buttons a success call, and a call with a wrong EXTRA param.
To make DUMMY_APP to call MAIN_APP I use sendBroadcast
// MainActivity class
private static final String REQUIRED_ACTION = "com.basetis.afr.intent.action.INIT_TEXT_FLOW";
onCreate....
Button btnSuccess = (Button)findViewById(R.id.button_success_call);
btnSuccess.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
i.setAction(REQUIRED_ACTION);
i.putExtra(Intent.EXTRA_TEXT, textToBeRead);
sendBroadcast(i);
}
});
So MAIN_APP has the corresponding BroadcastReceiver that is receiving fine.
// BlinkingReadReceiver class
private static final String CALLBACK_CALL_AFR_ACTION = "com.basetis.afr.intent.action.CALLBACK_CALL_AFR_ACTION";
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent();
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.d(TAG, "SUCCESS send callback");
i.setAction(CALLBACK_CALL_AFR_ACTION);
i.putExtra(CALL_AFR_SUCCESS_EXTRA, CALL_AFR_SUCCESS_EXTRA_DESC);
i.setType("text/plain");
context.sendBroadcast(i);
}
So the DUMMY_APP BroadcastReceiver never receive nothing :(
So I configured Manifests like that:
DUMMY_APP
<receiver android:name=".MainBroadcastReceiver" android:enabled="true">
<intent-filter>
<action android:name="com.basetis.afr.intent.action.CALLBACK_CALL_AFR_ACTION"></action>
</intent-filter>
</receiver>
MAIN_APP
<receiver android:name=".BlinkingReadReceiver" android:enabled="true">
<intent-filter>
<action android:name="com.basetis.afr.intent.action.INIT_TEXT_FLOW"></action>
</intent-filter>
</receiver>
Sometimes I receive this error (afrsender is de DUMMY_APP) but seems sort of random...
Performing stop of activity that is not resumed: {com.basetis.afrsender.afrsender/com.basetis.afrsender.afrsender.MainActivity}
java.lang.RuntimeException: Performing stop of activity that is not resumed
Any suggestions about how to achieve this two way App communication?
Thank you very much.
As stated in the document
Starting from Android 3.1, the system's package manager keeps track of applications
that are in a stopped state and provides a means of controlling their launch from
background processes and other applications.
That means that till the app is not started manually by the user your app will be in force stop state and it won't receive any broadcast.
That's why your dummy app is not receiving and broadcast sent by main app.
Check here for more reference

BroadcastReceiver is not working

I have implemented this broadcast reciever:
public class ServiceManager extends BroadcastReceiver {
private final String BOOT_ACTION = "android.intent.action.BOOT_COMPLETED";
private final String BOOT_ACTION_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
private final String BOOT_ACTION_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
#Override
public void onReceive(Context context, Intent intent) {
// All registered broadcasts are received by this
String action = intent.getAction();
if (action.equalsIgnoreCase(BOOT_ACTION) || action.equalsIgnoreCase(BOOT_ACTION_FIRST_LAUNCH) ||
action.equalsIgnoreCase(BOOT_ACTION_RESTARTED)) {
// TODO: Action
}
}
}
AndroidManifest.xml
<receiver android:name="package.service.ServiceManager" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" />
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
</intent-filter>
</receiver>
The BOOT_COMPLETED action is working right, but, the PACKAGE_FIRST_LAUNCH and PACKAGE_RESTARTED are not working. I need to launch my broadcast receiver when I launch my app, that's why I'm using these actions. But, when I launch or restart the app, the receiver is not working. It only works when I restart my mobile phone. Are there something wrong in my source?
FYI: PACKAGE_FIRST_LAUNCH is only sent to the installer package, i.e. whatever you used to install the application - for most end users that would be Android Market.
Edit:
Oh, and for "PACKAGE_RESTARTED", break that one out into its own <intent-filter> and add a
<data android:scheme="package"/>
since that one comes with an URI and an explicit scheme.
Logically it seems that PACKAGE_FIRST_LAUNCH will be broadcasted once your app is run for the first time after boot/reboot. And PACKAGE_RESTARTED should be broadcasted if your application activity stack is removed and then your app is clicked to start again (like restart).
However, you may simply achieve this by broadcasting a custom action string when ever your app is launched (perhaps from your first activity).
Manifest:
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></>
...
<receiver android:name=".AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
...
Receiver:
package YourPackage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoStart extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
{
// Your code
}
}
}
The intent android.intent.action.PACKAGE_FIRST_LAUNCH is introduced in Android API Level 12. If you are using lesser API Level it will not work. So change your project settings accordingly.

Display toast on Android broadcast when screen is on.

Im trying to do a simple broadcast in Android to detect the screen is on. For me this is a learning excersize to understand the Android broadcast capabilities. Please help.
I have the Android XML
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".UsbddActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.SCREEN_ON"></action>
</intent-filter>
</receiver>
</application>
The main Java file
package usb.usbd;
import android.app.Activity;
import android.os.Bundle;
public class UsbddActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
The Broadcast class That supposed to display the toast.
package usb.usbd;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context arg0, Intent arg1) {
Toast.makeText( arg0, "worked", Toast.LENGTH_LONG).show();
run(arg0 );
}
public void run(Context arg0 ) {
Toast.makeText(arg0, "sss", Toast.LENGTH_SHORT).show();
}
}
It doesnt dislay any errors nor does it display the toast. How can i get the toast to display when the screen is turned on.
Have a look at this site: http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
First, unlike other broad casted intents, for Intent.ACTION_SCREEN_OFF and Intent.ACTION_SCREEN_ON you CANNOT declare them in your Android Manifest!
You could handle this by gaining the ReceiveBootComplete Permission, then starting a service with the onBootReceiver, which registers the Intent Filter. Sounds complicated, but there is also a good example on this site.
/edit: Ah, and I just saw that in the example it is done by onResume and onPause. It might be a way, but I wouldn't recommend it. See this question: Service and a BroadCastReceiver
It is explained there how to register a Receiver in your service.
This link covers how to start a service on boot: http://www.androidcompetencycenter.com/2009/06/start-service-at-boot/

Android BroadcastReceiver on startup - keep running when Activity is in Background

I'm monitoring incoming SMSs.
My app is working perfectly with a BroadcastReceiver. However it is working from an Activity and would like to keep the BroadcastReceiver running all the time (and not just when my Activity is running).
How can I achieve this? I've looked through the lifecycle of the BroadcastReceiver but all that is mentioned in the documentation is that the lifecycle is limited to the onReceive method, not the lifecycle of keeping the BroadcastReceiver checking for incoming SMS.
How can I make this persistent?
Thanks
You need to define a receiver in manifest with action name android.intent.action.BOOT_COMPLETED.
<!-- Start the Service if applicable on boot -->
<receiver android:name="com.prac.test.ServiceStarter">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Make sure also to include the completed boot permission.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Use Service for this to make anything persist. And use receivers to receive Boot Up events to restart the service again if system boots..
Code for Starting Service on boot up. Make Service do your work of checking sms or whatever you want. You need to do your work in MyPersistingService define it your self.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ServiceStarter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent("com.prac.test.MyPersistingService");
i.setClass(context, MyPersistingService.class);
context.startService(i);
}
}
Service or Boot Completed is not mandatory
In fact, you don't need to implement a Service or register to android.intent.action.BOOT_COMPLETED
Some examples shows how to register/unregister a BroadcastReceiver when activity is created and destroyed. However, this is useful for intents that you expect only when app is opened (for internal communication between Service/Activity for example).
However, in case of a SMS, you want to listen to the intent all the time (and not only when you app is opened).
There's another way
You can create a class which extends BroadcastReceiver and register to desired intents via AndroidManifest.xml. This way, the BroadcastReceiver will be indepedent from your Activity (and will not depend from Activity's Life Cycle)
This way, your BroadcastReceiver will be notified automatically by Android as soon as an SMS arrive even if your app is closed.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest>
...
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application>
....
<receiver android:name=".MyCustomBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
MyCustomBroadcastReceiver.java
public class MyCustomBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent != null) {
String action = intent.getAction();
if(action != null) {
if(action.equals("android.provider.Telephony.SMS_RECEIVED")) {
// DO YOUR STUFF
} else if (action.equals("ANOTHER ACTION")) {
// DO ANOTHER STUFF
}
}
}
}
}
Notes
You can add others intent-filters to AndroidManifest and handle all of them in same BroadcastReceiver.
Start a Service only if you will perform a long task. You just need to display a notification or update some database, just use the code above.
Add Broadcast Reciever in manifest:
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
Create Class BootReciever.java
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
// +++ Do Operation Here +++
}
}
}
Beside #Javanator answer I would like to include a case for Android version of (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) In my case this is working for Android SDK 29 (10)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context,FloatingWindow.class));
} else {
context.startService(new Intent(context, FloatingWindow.class));
}
use this code and also mention the broadcast in Manifest also:
public class BootService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Toast.makeText(context, "Boot Completed", Toast.LENGTH_SHORT).show();
//write code here
}
}
}
I just want to mention that in case of some Chinese phone brands (e.g. MI), you need to go to Settings and give autostart permission to your app.
Otherwise the battery optimisation feature will kill your service in background and broadcast receiver will not work.
So you can redirect your user to Settings and ask them to give that permission.

Categories

Resources