Broadcast Receiver - MainActivity is not an enclosing class - java

I know this was asked numerous times, but I couldn't find the right answer for me.
I'm only in my third semester of my bachelor degree, so not that much knowledge yet.
Currently having my first Android course after I finished my beginner Java course (emphasis on beginner).
Due to Corona there is next to no Tutor support and the script is lacking decent explanations.
Im struggling with implementing my first Broadcast receiver. It's supposed to make a toast when a power cord is plugged in.
I tried a dynamic receiver so I registered the Receiver in my MainActivity as follows:
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.content.Intent;
public class MainActivity extends AppCompatActivity {
[...]
private PowerConnectedReceiver mPowerConnectedReceiver;
public void onResume() {
super.onResume();
IntentFilter powerFilter = new IntentFilter(Intent.ACTION_POWER_CONNECTED );
mPowerConnectedReceiver = new PowerConnectedReceiver();
getApplicationContext().registerReceiver(mPowerConnectedReceiver , powerFilter);
}
#Override
protected void onPause() {
getApplicationContext().unregisterReceiver(mPowerConnectedReceiver);
super.onPause();
}
With the Broadcast Receiver looking as follows and this is where the error pops up. It says for the Context of the Toast that MainActivity is not an enclosed class.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
import static android.widget.Toast.LENGTH_LONG;
public class PowerConnectedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MainActivity.this, "POWER CONNECTED received", LENGTH_LONG ).show();
}
}
This is the way of implementing that is taught in the script.
As I mentioned I am fairly new to programming and this might be something totally obvious, but I'm not seeing it.
The only thing I tried was changing it to MainAcivity.class, but that did nothing.
Thanks for support.

Your code is correct, but in the toast message you have to use context of the receiver i.e the first parameter of the onReceive method.
Update your toast message from:
Toast.makeText(MainActivity.this, "POWER CONNECTED received", LENGTH_LONG ).show();
to
Toast.makeText(context, "POWER CONNECTED received", LENGTH_LONG ).show();

Related

Wi-fi Scan Broadcast Receiver not Working

I am currently working on a simple Wi-fi scanner android application
with min API level 26 and target API level 28.
I want real time update in scan results so i have created a broadcast receiver but it is not working as intended.
Note: I have already tried
Wifi scan results broadcast receiver not working, Broadcast receiver with wifi scan not working
PLEASE NOTE THAT I WANT EXPLICIT BROADCAST RECEIVER NOT VIA MANIFEST FILE
I will be grateful to you.
Below is my java code:
package com.example.quickshare;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class ActivitySend extends AppCompatActivity {
WifiManager wifiManager;
ListView ScanList;
List<ScanResult> results;
ListAdapter listAdapter;
WifiReceiver wifiReceiver;
IntentFilter intentFilter;
TextView msg;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send);
wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
CheckWifiStatus();
msg = findViewById(R.id.wifiStatus);
intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
intentFilter.addAction(WifiManager.EXTRA_RESULTS_UPDATED);
try {
getApplicationContext().registerReceiver(wifiReceiver, intentFilter);
}
catch(Exception e){
System.out.println(e);
}
boolean success = wifiManager.startScan();
if(success)
Toast.makeText(ActivitySend.this, "Scanning", Toast.LENGTH_SHORT).show();
}
#Override
protected void onResume() {
super.onResume();
CheckWifiStatus();
registerReceiver(wifiReceiver, intentFilter);
wifiManager.startScan();
results = wifiManager.getScanResults();
if (results.size() > 0)
Toast.makeText(ActivitySend.this, "Scan Successful", Toast.LENGTH_LONG).show();
else
Toast.makeText(ActivitySend.this, "No Device Available", Toast.LENGTH_LONG).show();
ScanList = findViewById(R.id.ScanList);
listAdapter = new ListAdapter(getApplicationContext(), results);
ScanList.setAdapter(listAdapter);
ScanList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(ActivitySend.this, "Selected" + results.get(position).SSID, Toast.LENGTH_LONG).show();
//TODO: Establish Connection with selected SSID
}
});
}
class WifiReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(ActivitySend.this,"Available Device list changed",Toast.LENGTH_LONG).show();
//TODO: Append SSID of new Available APs in ListView and arrange a callback to onResume().
}
}
public void CheckWifiStatus(){
if (!wifiManager.isWifiEnabled()){
wifiManager.setWifiEnabled(true);
Toast.makeText(ActivitySend.this, "Wifi turned 'On' Successfully", Toast.LENGTH_SHORT).show();
msg.setText("Wifi Status : ON");
}
}
#Override
protected void onPause() {
unregisterReceiver(wifiReceiver);
super.onPause();
}
}
Using Above java code i can scan available APs if they are available before launching the activity.
After Launching this activity nothing changes in scan result and it keep showing previously fetched results even if i turn off that AP.
In order to detect your AP being disconnected, your intentFilter is lacking the ConnectivityManager.CONNECTIVITY_ACTION.
You can listen
to these action with the following line:
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Also, you need to add brackets to your else code blocks, i.e.
if {
// ...
} else {
Toast.makeText(ActivitySend.this, "No Device Available", Toast.LENGTH_LONG).show();
ScanList = findViewById(R.id.ScanList);
// ...
}

How to create service Detaction call always running after killed app over api 26 in android studio java

i am using this code
and this code running if app active in screen
and if closed the code is not running
how to fix this like truecaller app is running in background if killed app
package com.islamelwakeel.detectcall;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
showToast(context,"Call started...");
}
else if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE)){
showToast(context,"Call ended...");
}
else if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)){
showToast(context,"Incoming call...");
Log.d("call","Incoming call...");
}
}
void showToast(Context context,String message){
Toast toast=Toast.makeText(context,message,Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER,0,0);
toast.show();
}
}
My service was also killed. I tried many methods, but I discovered one method that worked. I used a service that receives calls from the system to check if my service is still running. If it doesn't work, start it. New Service. For example, NotificationListenerService will have it. There will be some events all the time. And I can write code to restart my service there
Ex.
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
if(!isMyserviceRunning){
startService();
}
}

How to make foreground Services work in MIUI?

I've been messing around with android services and facing a problem while running foreground Services in MIUI 10(Testing Device: Redmi note 5 pro)
Basically Service runs as long as the user is interacting with activity but as soon as user kills activity, foreground service also gets killed.
I read some other answers regarding the same issues,
which state that in devices like Xaomi, Oppo, lenovo, LG, honor etc.
You need to enable "AutoRun" permission for the app
Which I tried with no success. I also tried the following with no success at all:
Disabled MIUI optimization
Disabled Power saving
Removed Battery restrictions for the app
Freed the memory (Total: 3GB, Available:
2GB)
What worked for me was enabling the: "Don't keep activites" in the Developer options but in real world application you probably wouldn't ask users to enable this option since it affects user experience.
By the way, I tested my app in other devices such as pixel, nexus etc(Android studio emulators) And They all worked fine. It's only my device which is causing this issue.
Download link for the app for debugging purposes: https://anonfile.com/d4k511p1bd/app-debug_apk
Source Code
File: MainActivity.java
package com.myname.foregroundserviceexample;
import android.content.Intent;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private EditText editTextInput;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextInput = findViewById(R.id.edit_text_input);
}
public void startService(View v) {
String input = editTextInput.getText().toString();
Intent serviceIntent = new Intent(this, ExampleService.class);
serviceIntent.putExtra("inputExtra", input);
ContextCompat.startForegroundService(this, serviceIntent);
}
public void stopService(View v) {
Intent serviceIntent = new Intent(this, ExampleService.class);
stopService(serviceIntent);
}
}
File: ExampleService.java
package com.myname.foregroundserviceexample;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import static com.myname.foregroundserviceexample.App.CHANNEL_ID;
public class ExampleService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Example Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(pendingIntent)
.build();
// Starting Foreground Service
startForeground(1, notification);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
File: App.java
package com.myname.foregroundserviceexample;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
public class App extends Application {
public static final String CHANNEL_ID = "exampleServiceChannel";
#Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Example Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
I know there's a way around this by enabling "Don't keep activities" in Developing options but I genuinely don't want the user to enable this in their device, Also I would gladly accept any alternative or code improvements to make the foreground Service work in MIUI 10.
Thankyou
EDIT:
Here's the project link: https://anonfile.com/y5Rd4bp3b9/ForegroundServiceExample_zip
And this is the tutorial I was following on YouTube: https://www.youtube.com/watch?v=FbpD5RZtbCc
Maybe you should try to call Service#startForeground at the begining of your service creation in the onCreate/onStartIntent
See this post Context.startForegroundService() did not then call Service.startForeground() for more information.
If you are facing an error like this.
Permission Denial: startForeground requires android.permission.FOREGROUND_SERVICE
Then you have to add this in your manifest file.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"></uses-permission>
Hope it's work for you.

android studio media player null object reference

I ran into trouble when trying to use the media player in Android Studio, it seems like i haven't initialize the media player properly, which caused the app to crash (on phones running on Android 8.0) when SoundFXPlayer.setVolume() function is called. However, the app worked properly in emulator (API 26 - 28) , and most of the phone i tested (phones with on API 26-27) , EXCEPT phones that run on Android 8.0 (API 28) .
To summarize
1. How to initialize media player properly
2. Why my code work on emulator but not on phone.
i am new to stackoverflow and not experienced in programming, sorry if didn't gave enough details.
Error message as follow:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.garmischwong.buttongame/com.example.garmischwong.buttongame.MenuActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.media.MediaPlayer.setVolume(float, float)' on a null object
reference
package com.example.garmischwong.buttongame;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MenuActivity extends AppCompatActivity {
private Button gameButton;
public int SoundFXVolume;
public MediaPlayer SoundFXPlayer;
public static final String GAME_PREF = "gamePref" ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
gameButton = findViewById(R.id.gameButton);
SoundFXPlayer = MediaPlayer.create(this, R.raw.menu_selection_click);
loadSoundFX();
SoundFXPlayer.setVolume((float)SoundFXVolume/100,(float)SoundFXVolume/100);
}
public void goToGameAct(View view)
{
//////Intent to game///////
SoundFXPlayer.start();
Intent goToGameIntent = new Intent(MenuActivity.this, GameActivity.class);
startActivity(goToGameIntent);
finish();
}
public void loadSoundFX()
{
SharedPreferences gamePref = getSharedPreferences(String.valueOf(GAME_PREF), MODE_PRIVATE);
SoundFXVolume = gamePref.getInt("Sound_FX_Volume", 30);
}
Most likely audio format is not being supported. You can use 8bit and 16bit linear PCM. Here is more information on supported media formats:supported media formats
The solution is to re-encode the mp3 files.

make progressdialog while waiting to receive SMS

I am new to Android and Java. The following code is to send and wait for receiving SMS. As the process may takes about 3 minutes, I need to have a progressDialog until SMS is received. Could you send me an applet to do this ?
package com.examples.TOLD;
import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import android.telephony.SmsManager;
import android.util.Log;
import android.widget.TextView;
public class Sms extends Activity {
/** Called when the activity is first created. */
static TextView smsReceive;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.sms);
Intent i = getIntent();
// Receiving the Data
String reg = i.getStringExtra("reg");
String port = i.getStringExtra("port");
String smsMessage =
"REG=" + reg +
"PORT=" + port;
// Show SMS sent message on screen
TextView smsSend = (TextView) findViewById(R.id.smsSend);
smsSend.setText(smsMessage);
Log.i("smsSend",String.valueOf(smsSend.getText()));
// Send SMS message
SmsManager sm = SmsManager.getDefault();
String number = "5556";
sm.sendTextMessage(number, null, smsMessage, null, null);
// Receive SMS message
smsReceive = (TextView) findViewById(R.id.smsReceive);
}
public static void updateMessageBox(String msg)
{
smsReceive.append(msg);
}
}
Here is another class to receive SMS:
package com.examples.TOLD;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
public class SmsReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent)
{
Bundle bundle=intent.getExtras();
Object[] messages=(Object[])bundle.get("pdus");
SmsMessage[] sms = new SmsMessage[messages.length];
for(int n=0;n<messages.length;n++){
sms[n]=SmsMessage.createFromPdu((byte[]) messages[n]);
}
for(SmsMessage msg:sms){
String num = msg.getOriginatingAddress();
Log.i("SMS sender",num);
if (num.equals("15555215556")) {
Sms.updateMessageBox("\nFrom: " + msg.getOriginatingAddress() +
"\n" + "Message: " + msg.getMessageBody() + "\n");}
}
}
}
I think you can try to reconsider your approach. You can't expect user will be waiting for up to 3 minutes for the SMS. So you code looks right (except the part of the static method cos I explain you later), but once your message is sent, I'd show a message that your app is waiting for the message, and when the message is received in the SmsReceiver, you can communicate with the Sms activity.
But, you shouldn't use that static method to update the content of the activity for several reasons (UI can't be updated in background or most important when the SmsReceiver is fired SMS activity can even non exist). The right way would be sending an intent from the receiver. You can see a detailed step by step example in the pdf contained in this link in the section Receiving SMS messages.
I Don't think sending and receiving should be in the main thread. You can use AsyncTask to receive the message in background. you can show the dialog before starting the task and
close it after recieving
Lookup http://developer.android.com/reference/android/os/AsyncTask.html for painless background threading.
Simply display your progress dialog in OnPreExecute and dismiss it when the task reaches OnPostExecute.

Categories

Resources