what is the drawback of sendSticyBroadcast() in Android? - broadcastreceiver

I am developing an android application in API Level 21, i am broadcasting a message but some unusual things happens. like another application can using it.
Can anyone help me out in How to send a Sticky Broadcast in API 21.
//MyActivity.java
class myActivity extends Activity {
//MyDialog dialog initialized in onCreate
...
private class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//toast "Broadcast received"
}
}
}
//MyDialog.java
class MyDialog extends Dialog {
//m_context = incoming context from MyActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new View.OnCLickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
m_context.sendStickyBroadcast(intent);
}
});
}
}
//AndroidManifest.xml
<activity android:name=".MyActivity" />
<receiver android:name="MyReceiver" android:enabled="true">
<intent-filter >
<action android:name="android.intent.action.RUN"/>
</intent-filter>
</receiver>

Yes i have foud he answer after googling a lot.
This method was deprecated in API level 21. Sticky broadcasts should not be used. They provide no security (anyone can access them), no protection (anyone can modify them), and many other problems. The recommended pattern is to use a non-sticky broadcast to report that something has changed, with another mechanism for apps to retrieve the current value whenever desired.

Related

Broadcast Receiver is not registering in android oreo

SmsBroadcastReceiver was not triggering when i received otp in oreo. I have explicitly registered my receiver in fragment instead of not only in manifest.
public class MyFragment extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
intentFilter = new IntentFilter();
intentFilter.addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
smsBroadcastReceiver = new SmsBroadcastReceiver();
getActivity().registerReceiver(smsBroadcastReceiver,intentFilter);
return inflater.inflate(
R.layout.fragment_two, container, false);
}
}
Here it's my SmsReceiverBroadcast class
public class SmsBroadcastReceiver extends BroadcastReceiver {
public SmsBroadcastReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("onRecieve","Otp has been received");
}
} catch (Exception e) {
}
}
}
And in my manifest,
<receiver
android:name=".receiver.SmsBroadcastReceiver"
android:enabled="true"
android:exported="false"
>
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
I'm not getting any trigger in override onReceive() method for the Broadcast receiver. I have found that we need to register a broadcast receiver explicitly. I register my receiver using registerBroadcast().It is not working for me.Also, I referred https://developer.android.com/about/versions/oreo/background.html
I have also tried
Do I need to add any other permission to register and triggering the receiver whenever I receive otp?Is my intent filters action(Telephony.Sms.Intents.SMS_RECIEVED_ACTION) correct?

How to start a lockscreen activity instantaneously after reboot?

I want to start a lockscreen activity after device reboot side by side with the startup notifications like Messages,Viber notifications,Whatsapp etc.How to do this ??.I have made a broadcast receiver which receives BOOT_COMPLETED action and upon that it starts a service that registers the same receiver again with Intent.ACTION_SCREEN_OFF and Intent.ACTION_SCREEN_ON intent filter and that receiver starts the lockscreen activity.Here is my code:
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" ></uses-permission>
<receiver>
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
and of course I declared the service in the manifest.
Here is my Broadcast Receiver class
public class LockScreenBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("BroadCastReceiver", "ReceivedIntent");
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Intent myIntent = new Intent(context, LockScreenActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
myIntent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
if (!LockScreenActivity.isActivityRunning) {
context.startActivity(myIntent);
}else{
Log.d("BroadCasrReceiver","LockScreenActivity is running");
}
}else if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Log.v("LockScreenBroadReceiver","boot completed");
Intent startServiceIntent = new Intent(context,LockScreenService.class);
context.startService(startServiceIntent);
}
}
}
and the service class :
public class LockScreenService extends Service {
LockScreenBroadCastReceiver broadCastReciever;
public static boolean isRunning;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
isRunning = true;
registerReceiver();
}
#Override
public void onDestroy() {
super.onDestroy();
isRunning = false;
unregisterReceiver(broadCastReciever);
Log.d("LockScreenReceiver", "ReceiverUnregistered");
sendBroadcast(new Intent("RestartLockScreenService"));
}
private void registerReceiver(){
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
broadCastReciever = new LockScreenBroadCastReceiver();
registerReceiver(broadCastReciever,intentFilter);
Log.d("LockScreenReceiver", "ReceiverRegistered");
}
}
This approach is working.However,It's very slow as the broadcast receiver listens to BOOT_COMPLETED broadcast which waits until the device is fully up and working.So,you may lock and unlock the phone several times before you get the lockscreen working.Any ideas??
You can use the intentFilter instace of BootComplate in manifist like this:
<action android:name="android.intent.action.USER_PRESENT" />
I had the same issue. It was fixed by including
<category android:name="android.intent.category.DEFAULT" />
on the receiver. The is a slight delay of 6 seconds on reboot which I'm trying to narrow down.
I hope this works for you

How to make my service run?

I want to start a service when the power is connected to my device and show a notification but my app is doing nothing or I do not what is happenig, so please help me, I am new in the android world, maybe I miss something, mi code is the following:
My manifest:
<receiver android:name="com.tlm.grhs_client.WiFiMonitor">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
</intent-filter>
</receiver>
My Broadcast Reciever:
public class WiFiMonitor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null && info.getType() == ConnectivityManager.TYPE_WIFI) {
if (info.isConnected()) {
//iniciar servicio
Intent serviceIntent = new Intent(context, ClientService.class);
context.startService(serviceIntent);
}
else {
//parar servicio
Intent serviceIntent = new Intent(context, ClientService.class);
context.stopService(serviceIntent);
}
}
}
}
and my service class is this:
public class ClientService extends Service {
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
Toast.makeText(this, "Servicio fue creado", Toast.LENGTH_LONG).show();
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#SuppressLint("NewApi")
#Override
public void onStart(Intent intent, int startId) {
// Perform your long running operations here.
Toast.makeText(this, "Servicio iniciado", Toast.LENGTH_LONG).show();
Notification.Builder notiBuilder = new Notification.Builder(this);
notiBuilder.setContentTitle("Prueba");
notiBuilder.setContentText("Esto es una prueba");
Notification notificacion = notiBuilder.build();
NotificationManager manager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE);
manager.notify(1, notificacion);
}
#Override
public void onDestroy() {
Toast.makeText(this, "Servicio destruido", Toast.LENGTH_LONG).show();
}
}
I turn on the wifi and establish the connection but the notification doesn't shows.
Android notifications in this manner require a small icon, along with a title and some text as per the documentation at http://developer.android.com/guide/topics/ui/notifiers/notifications.html
Add an icon but otherwise the code (on a quick glance) looks like it should work.

Start Activity Intent from Android Application

I have an activity that holds a handler that I need to be running for the whole app. What I need to do is call the handler activity whenever main activity starts up, then upon executing a function at handler activity, handler activity should start the intent into second activity.
This is my code:
public class MyApp extends Application {
public void onCreate() {
h = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle b = msg.getData();
Log.d("tag",b.getString("msg"));
//THIS IS WHERE I WANT TO OPEN SECONDACTIVITY
}
};
}
}
MyApp is a global Application class I use to run a socket connection across the whole app. It needs to be alive as long as the app is running.
Its simple
Intent intent = new Intent(YourActivityClass.this, SECONDACTIVITY.class);
startActivity(intent);
public class MyApp extends Application {
public void onCreate() {
h = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle b = msg.getData();
Log.d("tag",b.getString("msg"));
Intent myIntent = new Intent(this, YourSecondActivity.class);
startActivity(myIntent);
}
};
}
}
Also add this to your manifest file
<activity android:name=".YourSecondActivity" />
Well, It turns out that I need to add: i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent i = new Intent(MyApp.this, SecondActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
Because From MainActivity, I called MyApp (An class to maintain global application state). Then in MyApp, I process something and then I call SecondActivity.
First You add the activity information in AndroidManifest.xml LIKE
<activity
android:name="com.assignment.matchnumber.PlayActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.assignment.matchnumber.PLAY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Then put this in your MyApp activity where you want.
Intent openPlayActivity = new Intent("com.assignment.matchnumber.PLAY");
startActivity(openPlayActivity);
thanks
--Sajib

How to access an already-running Application Context from a Sync Adapter service in Android?

I have an app that consists of several activities, and I use the Application Context (entended from the Application Class, and I made it persistent) to share data and objects between all the activities. I use the Application Class instead of a background service for several good reasons, which I won't go into here.
I also recently added an custom contact sync adapter to my app. It's under the same package, in the same APK. So, I set it up to access the Application Context just like everything else in my app to give it access to all the shared data and objects. However, even though it works (mostly), it creates a new instance of the Application Context. So there are basically 2 separate instances of my application running, and the data isn't shared between them.
I think that the problem is that my Applicattion never starts the sync service, the OS does. All my other activities are either started by the application, or the main activity accesses the Application Context when it launches, and then the App Context controls everything else. Is there a way to have the sync service access the existing Application Context, instead of creating the new instance of it?
Here's the basic structure of my app:
The application
package com.mycomany.myapp;
public class MyApp extends Application{
...
}
Activity1
package com.mycomany.myapp;
public class MyActivity1 extends Activity{
MyApp a;
#Override
public void onCreate(Bundle savedInstanceState){
a = (MyApp) getApplicationContext();
...
}
}
SyncAdapterService
package com.mycomany.myapp;
public class SyncAdapterService extends Service {
private static SyncAdapterImpl sSyncAdapter = null;
private static final Object sSyncAdapterLock = new Object();
private static ContentResolver mContentResolver = null;
private static MyApp a;
public SyncAdapterService() {
super();
}
private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
private Context mContext;
public SyncAdapterImpl(Context context) {
super(context, true);
mContext = context;
}
#Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
try {
SyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
} catch (OperationCanceledException e) {}
}
}
#Override
public void onCreate() {
super.onCreate();
synchronized (sSyncAdapterLock) {
if(a == null){
a = (MyApp) getApplicationContext();
}
if (sSyncAdapter == null) {
sSyncAdapter = new SyncAdapterImpl(getApplicationContext());
}
}
}
#Override
public IBinder onBind(Intent intent) {
return sSyncAdapter.getSyncAdapterBinder();
}
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
throws OperationCanceledException {
...
}
}
Have you copy&pasted this training for the SyncAdapter http://developer.android.com/training/sync-adapters/creating-sync-adapter.html?
At the end there is this XML Snippet:
<service
android:name="com.example.android.datasync.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>com.example.android.datasync.provider
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="#xml/syncadapter" />
</service>
With the attribute android:process=":sync" meaning you create a separate sync process. Remove it and you're good to go.
You might want to look into binding the service to your Application context. That way, if your application context does not exist, the service won't exist, as it runs in the same process (that of the Application) . See bindSerivce()
If your service is a remote one try using callbacks
Are you still having this problem?
If the service is declared in your manifest file without specifying a different android:process, isn't it supposed to run in the default process defined by your task?
Can't you in that case just use getApplicationContext to get what you need?
I have my sync adapter implemented in this way and it is working