I have added READ_PHONE_STATE permission in my project.
Scenario:
I am just opening my application and I get Permission alert “Allow My Application to make and manage phone calls ?"
Now I am moving my application in background and again opening by tap on My Application icon
Result: “Allow My Application to make and manage phone calls ?" Permission pop up get disappears.
Can any one tell why this behaviour?
Note: I am using launchMode="singleInstance" and when using launchMode="standard" all is working fine.
Sharing my code :
<?xml version="1.0" encoding="utf-8"?>
<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" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
public class MainActivity extends AppCompatActivity {
public static final Integer REQUEST_CODE_FOR_PERMISSION = 0x1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
askForPermission(this, Manifest.permission.READ_PHONE_STATE, REQUEST_CODE_FOR_PERMISSION);
}
public static void askForPermission(Activity context, String permission, Integer requestCode) {
if ((Build.VERSION.SDK_INT >= 23) && (context != null) && (TextUtils.isEmpty(permission) == false)) {
ActivityCompat.requestPermissions(context, new String[]{permission}, requestCode);
}
}}
Based on singleTask behaviour
If an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance.
https://developer.android.com/guide/components/activities/tasks-and-back-stack#TaskLaunchModes
I was able to fix this issue by handling the code in
onNewIntent(Intent intent)
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
askForPermission(this, Manifest.permission.READ_PHONE_STATE, REQUEST_CODE_FOR_PERMISSION);
}
Try this,
public class MainActivity extends AppCompatActivity {
public static final Integer REQUEST_CODE_FOR_PERMISSION = 0x1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#override
private void onResume(){
askForPermission(this, Manifest.permission.READ_PHONE_STATE, REQUEST_CODE_FOR_PERMISSION);
}
public static void askForPermission(Activity context, String permission, Integer requestCode) {
if ((Build.VERSION.SDK_INT >= 23) && (context != null) && (TextUtils.isEmpty(permission) == false)) {
ActivityCompat.requestPermissions(context, new String[]{permission}, requestCode);
}
}}
Call finish() in onBackPressed()
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
This will launch activity again and your code will work in onCreate()
Use Runtime Permission like this:
public class MainActivity extends Activity {
private static final int PERMISSION_REQUEST_CODE = 200;
Context context;
Activity activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
activity = this;
setContentView(R.layout.activity_splash);
if (!checkPermission()) {
OpenActivity();
} else {
if (checkPermission()) {
requestPermissionAndContinue();
} else {
OpenActivity();
}
}
}
private boolean checkPermission() {
return ContextCompat.checkSelfPermission(this, READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED;
}
private void requestPermissionAndContinue() {
if (ContextCompat.checkSelfPermission(this, READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, READ_PHONE_STATE)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
alertBuilder.setCancelable(true);
alertBuilder.setTitle("Permission necessary");
alertBuilder.setMessage("STORAGE permission is necessary to write event!!!");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(SplashActivityANother.this, new String[]{READ_PHONE_STATE,
}, PERMISSION_REQUEST_CODE);
}
});
AlertDialog alert = alertBuilder.create();
alert.show();
Log.e("", "permission denied, show dialog");
} else {
ActivityCompat.requestPermissions(this, new String[]{READ_PHONE_STATE
}, PERMISSION_REQUEST_CODE);
}
} else {
OpenActivity();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
if (permissions.length > 0 && grantResults.length > 0) {
boolean flag = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
flag = false;
}
}
if (flag) {
OpenActivity();
} else {
finish();
}
} else {
finish();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void OpenActivity() {
Intent i = new Intent(MainActivity.this, SecondActivity.class);
startActivity(i);
}
}
and Add
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> in to menifist file.
Hope this Helps you
Related
How can I check permission for every activity ???
I am trying to make a video player app. I am trying to get External Storage on Android 11 and the lower version. When I am clicking on the button it is asking for permission for both android 11 and the lower version (ex: Kitkat). But the problem is when I am going to the next activity after granting permission and turning off the storage permission from settings in the background. It was not asking for any permission for this new activity.
If anyone has any solution please help me I was shared my code bellow
My permission activity(MainActivity.java) and I want to check permission in (activity_allow_access.java).
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int STORAGE_PERMISSION_CODE = 100;
final static int REQUEST_CODE = 333;
private Button signIn;
public static String PREFS_NAME="MyPrefsFile";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
signIn = findViewById(R.id.button);
signIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (checkPermission()) {
startActivity(new Intent(MainActivity.this,AllowAccessActivity.class));
finish();
} else {
requestPermission();
}
}
});
}
private void requestPermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
try {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package",this.getPackageName(),null);
intent.setData(uri);
storageActivityResultLauncher.launch(intent);
} catch (Exception e) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
storageActivityResultLauncher.launch(intent);
}
}else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},STORAGE_PERMISSION_CODE);
}
}
private ActivityResultLauncher<Intent> storageActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.R){
if(Environment.isExternalStorageManager()){
startActivity(new Intent(MainActivity.this,AllowAccessActivity.class));
finish();
}
else{
Toast.makeText(MainActivity.this, "storage permission required", Toast.LENGTH_SHORT).show();
}
}
}
}
);
public boolean checkPermission(){
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.R){
return Environment.isExternalStorageManager();
}else {
int write = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int read = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
return write == PackageManager.PERMISSION_GRANTED && read == PackageManager.PERMISSION_GRANTED;
}
}
private boolean checkStoragePermission(){
boolean result = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED);
return result;
}
#SuppressLint("MissingSuperCall")
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == STORAGE_PERMISSION_CODE){
if (grantResults.length >0){
boolean write = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean read = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if(write && read) {
startActivity(new Intent(MainActivity.this,AllowAccessActivity.class));
finish();
} else {
requestPermission();
}
}
}
}
#Override
protected void onResume() {
super.onResume();
if (checkPermission()) {
startActivity(new Intent(MainActivity.this,AllowAccessActivity.class));
finish();
}
}
}
AllowAccessActivity.java
public class AllowAccessActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_allow_access);
}
}
public class Splash extends AppCompatActivity {
private static final String MANAGE_EXTERNAL_STORAGE_PERMISSION = "android:manage_external_storage";
private final Handler handler = new Handler();
private static final int REQUEST_PERMISSIONS = 1234;
private static final String[] PERMISSIONS = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_activity);
//To hide action Bar(Tool Bar)
getSupportActionBar().hide();
if (!arePermissionDenied()){
next();
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && arePermissionDenied()) {
// If Android 11 Request for Manage File Access Permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_PERMISSIONS);
return;
}
requestPermissions(PERMISSIONS, REQUEST_PERMISSIONS);
}
}
#Override
protected void onResume() {
super.onResume();
if (!arePermissionDenied()) {
next();
}
}
#RequiresApi(api = Build.VERSION_CODES.R)
boolean checkStorageApi30() {
AppOpsManager appOps = getApplicationContext().getSystemService(AppOpsManager.class);
int mode = appOps.unsafeCheckOpNoThrow(
MANAGE_EXTERNAL_STORAGE_PERMISSION,
getApplicationContext().getApplicationInfo().uid,
getApplicationContext().getPackageName()
);
return mode != AppOpsManager.MODE_ALLOWED;
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onRequestPermissionsResult
(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSIONS && grantResults.length > 0) {
if (arePermissionDenied()) {
// Clear Data of Application, So that it can request for permissions again
((ActivityManager) Objects.requireNonNull(this.getSystemService(ACTIVITY_SERVICE))).clearApplicationUserData();
recreate();
} else {
next();
}
}
}
private boolean arePermissionDenied() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return checkStorageApi30();
}
for (String permissions : PERMISSIONS) {
if (ActivityCompat.checkSelfPermission(getApplicationContext(),
permissions) != PackageManager.PERMISSION_GRANTED) {
return true;
}
}
return false;
}
private void next() {
handler.postDelayed(() -> {
startActivity(new Intent(Splash.this, MainActivity.class));
finish();
}, 1000);
}
}
When I run the app there is an Fatal exception error,
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.CALL dat=tel0710000001 }
Error message
private static final int REQUEST_CALL = 1;
private TextView callText;
private AppCompatButton callTo;
callTo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
CallButton();[enter image description here][1]
}
});
}
private void CallButton() {
String number = callText.getText().toString();
if (number.trim().length()>0){
if(ContextCompat.checkSelfPermission(MyProfileActivity.this, Manifest.permission.CALL_PHONE )!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MyProfileActivity.this,new String[]{Manifest.permission.CALL_PHONE},REQUEST_CALL);
}
else {
String dial = "tel" + number;
startActivity(new Intent(Intent.ACTION_CALL, Uri.parse(dial)));
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CALL) {
if (grantResults.length > 0) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
CallButton();
}
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
}
AndroidManifest
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
try add this in your manifest.xml :
<uses-permission android:name="android.permission.CALL_PHONE" />
But, in the Reference, this permission is classified who "Protection level: dangerous", I recommend use this:
Kotlin:
val i = Intent(Intent.ACTION_DIAL)
i.data = Uri.parse("tel:$phone")
startActivity(i)
Java:
Intent i =new Intent(Intent.ACTION_CALL);
i.setData(Uri("tel:"+phone));
startActivity(i);
I am developing an app in which I am tracking location using the tower location.
So I am using the geo location api to track the location and accessing the phone state to get the network details.
This worked well, suddenly it started giving the security exception for LOCATION_HARDWARE permission.
I also tried to give the permission in manifest as well as requesting the permission runtime. But at runtime it asks for only location and the phone state permission not for the location_hardware permission. And then it crashes with security exception.
I am not getting for which purpose it is asking for the location_hardware permission.
I am stuck up here.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpUI();
public void setUpUI()
{
TrackingJob.schedulePeriodic(); // crashing here
}
}
}
}
Tracking Job :
public class TrackingJob extends Job {
static final String TAG = "tracking";
#NonNull
#Override
protected Result onRunJob(Params params) {
Intent pi = new Intent(getContext(), GetLocationService.class);
getContext().startService(pi);
return Result.SUCCESS;
}
public static void schedulePeriodic() {
new JobRequest.Builder(TrackingJob.TAG)
.setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(15))
.setUpdateCurrent(true)
.setPersisted(true)
.build()
.schedule();
}
}
GetLocationServer :
public class GetLocationService extends IntentService {
String networkSubType = "";
SessionData mSessionData;
private SharedPreferences preferences;
public GetLocationService() {
super("GetLocationService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
if (ContextCompat.checkSelfPermission(GetLocationService.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(GetLocationService.this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mSessionData = new SessionData(GetLocationService.this);
Calendar calendarSet = Calendar.getInstance();
Calendar calendarNow = Calendar.getInstance();
calendarSet.set(Calendar.HOUR_OF_DAY, 7); // hour
calendarSet.set(Calendar.MINUTE, 00); // minute
calendarSet.set(Calendar.SECOND, 0); // second
Calendar calendarEnd = Calendar.getInstance();
calendarEnd.set(Calendar.HOUR_OF_DAY, 20); // hour
calendarEnd.set(Calendar.MINUTE, 00); // minute
calendarEnd.set(Calendar.SECOND, 0); // second
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(calendarNow.getTime());
// Output "Wed Sep 26 14:23:28 EST 2012"
String currentTime = format1.format(calendarNow.getTime());
System.out.println(currentTime);
if (calendarNow.compareTo(calendarSet) >= 0 && calendarNow.compareTo(calendarEnd) <= 0) {
TelephonyManager telephonyManager = (TelephonyManager) GetLocationService.this.getSystemService(Context.TELEPHONY_SERVICE);
GsmCellLocation cellLocation = (GsmCellLocation) telephonyManager.getCellLocation();
ConnectivityManager connectivityManager = (ConnectivityManager) GetLocationService.this.getSystemService(Context.CONNECTIVITY_SERVICE);//?????????
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (cellLocation != null) {
int cellid = cellLocation.getCid();
int celllac = cellLocation.getLac();
if (activeNetInfo != null) {
networkSubType = activeNetInfo.getSubtypeName();
}
String networkOperator = telephonyManager.getNetworkOperator();
int mcc = Integer.parseInt(networkOperator.substring(0, 3));
int mnc = Integer.parseInt(networkOperator.substring(3));
String networkOperatorName = telephonyManager.getNetworkOperatorName();
int type = telephonyManager.getNetworkType();
Log.d("CellLocation", cellLocation.toString());
Log.d("GSM CELL ID", String.valueOf(cellid));
Log.d("GSM Location Code", String.valueOf(celllac));
Log.d("MCC", String.valueOf(mcc));
Log.d("MNC", String.valueOf(mnc));
Log.d("NetworkOperatorName", networkOperatorName);
Log.d("radioType", String.valueOf(type));
Log.d("Network subtype name", networkSubType);
AddLocationAsyncTask addLocationAsyncTask = new AddLocationAsyncTask(GetLocationService.this);
addLocationAsyncTask.execute(mSessionData.getString("user_id", ""), String.valueOf(cellid), String.valueOf(celllac), String.valueOf(mcc), String.valueOf(mnc),
networkOperatorName, networkSubType, currentTime);
// LocationUtility.scheduleJob(getApplicationContext());
}
}
}
}
}
How can I solve this? Please help with this.
Thank you..
EDIT : Runtime permissions:
public class StartUpActivity extends AppCompatActivity {
RelativeLayout relativeLayout;
public int mShortAnimationDuration = 5000;
private Button btnRegister,btnLogin;
private final static int MY_PERMISSIONS_REQUEST_ACCESS_LOCATION = 10;
private SessionData mSessionData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_up);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mSessionData = new SessionData(StartUpActivity.this);
if (ContextCompat.checkSelfPermission(StartUpActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(StartUpActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(StartUpActivity.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(StartUpActivity.this, Manifest.permission.LOCATION_HARDWARE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(StartUpActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE,Manifest.permission.LOCATION_HARDWARE},
MY_PERMISSIONS_REQUEST_ACCESS_LOCATION);
}
else {
if(!mSessionData.getString("user_id","").equals(""))
{
Intent i = (new Intent(StartUpActivity.this, MainActivity.class));
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
finish();
}
else {
setUpUI();
listeners();
}
}
}
public void setUpUI()
{
relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
btnLogin = (Button) findViewById(R.id.button_login);
btnRegister = (Button) findViewById(R.id.button_register);
}
public void listeners()
{
btnRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = (new Intent(StartUpActivity.this, SignUpActivity.class));
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
finish();
}
});
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = (new Intent(StartUpActivity.this, LoginActivity.class));
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
finish();
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_ACCESS_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
setUpUI();
listeners();
} else {
CommonUtils.showAlert(StartUpActivity.this,"Please accept the permissions to proceed.",getString(R.string.app_name));
ActivityCompat.requestPermissions(StartUpActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE,Manifest.permission.LOCATION_HARDWARE},
MY_PERMISSIONS_REQUEST_ACCESS_LOCATION);
}
return;
}
}
}
}
Manifest permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.location.network"/>
Quoted from here:
https://developer.android.com/guide/topics/manifest/uses-feature-element.html#permissions
If your app targets Android 5.0 (API level 21) or higher and uses the
ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in order to
receive location updates from the network or a GPS, respectively, you
must also explicitly declare that your app uses the
android.hardware.location.network or android.hardware.location.gps
hardware features.
Add it like this to your AndroidManifest.xml file outside of your <application/> tag:
<uses-feature android:name="android.hardware.location.network"/>
<application>
...
</application>
If the location feature is not a "must have" feature in your app in order for the app to work properly, also add this to the uses-feature tag - android:required="false"
You still have to ask for location permission at runtime
add ACCESS_FINE_LOCATION with targeting APIs 20 and below
My App goes like this:
When you first start the app, you'll see a button. Connecting or disconnecting the AC charger doesn't affect anything until you hit that Start button.
When you tap the Start button, the "service" is started.
Now if you remove the AC charger you will hear an alarm sound.
Connecting the AC with the device again should stop the alarm but it does NOT.
Now removing the AC again starts another alarm. The alarms overlap.
Can you help me find the bug?
Thanks
My work so far:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yousef.mustafa.antitheft">
<application
android:allowBackup="true"
android:icon="#mipmap/antitheft"
android:label="#string/app_name"
android:roundIcon="#mipmap/antitheft"
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=".PowerConnectionReceiver">
</receiver>
</application>
</manifest>
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button startServiceButton;
PowerConnectionReceiver powerConnectionReceiver;
BroadcastReceiver powerDisconnectedBroadcastReceiver;
BroadcastReceiver powerConnectedBroadcastReceiver;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
powerConnectionReceiver = new PowerConnectionReceiver(true);
startServiceButton = (ToggleButton) findViewById(R.id.startServiceButton);
powerDisconnectedBroadcastReceiver = new PowerConnectionReceiver(true);
powerConnectedBroadcastReceiver = new PowerConnectionReceiver(false);
startServiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (startServiceButton.isActivated()) {
unregisterReceiver(powerDisconnectedBroadcastReceiver);
unregisterReceiver(powerConnectedBroadcastReceiver);
Toast.makeText(MainActivity.this, "Service stopped", Toast.LENGTH_SHORT).show();
startServiceButton.setActivated(false);
} else {
monitorBatteryChanges();
}
}
});
}
private void monitorBatteryChanges() {
IntentFilter powerDisconnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_DISCONNECTED");
registerReceiver(powerDisconnectedBroadcastReceiver, powerDisconnectedIntentFilter);
IntentFilter powerConnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_CONNECTED");
registerReceiver(powerConnectedBroadcastReceiver, powerConnectedIntentFilter);
Toast.makeText(MainActivity.this, "Service started", Toast.LENGTH_SHORT).show();
startServiceButton.setActivated(true);
}
}
PowerConnectionReceiver.java
public class PowerConnectionReceiver extends BroadcastReceiver {
MediaPlayer mediaPlayer = new MediaPlayer();
// Determine whether the AC is disconnected or not
private boolean POWER_DISCONNECTED = true;
PowerConnectionReceiver(boolean disconnected) {
this.POWER_DISCONNECTED = disconnected;
}
#Override
public void onReceive(Context context, Intent intent) {
if (POWER_DISCONNECTED) {
mediaPlayer = MediaPlayer.create(context, R.raw.alarm_2);
Toast.makeText(context, "Alarm started", Toast.LENGTH_SHORT).show();
mediaPlayer.start();
mediaPlayer.setLooping(true);
//POWER_DISCONNECTED = false;
} else {
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
Toast.makeText(context, "Alarm stopped", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
The bug is in your complex code.
You register two different instances of PowerConnectionReceiver one for "connected" and another for "disconnected" events. So MediaPlayer is started in "connected" receiver, and you try to stop MediaPlayer in "disconected", but it doesn't play.
You should remove POWER_DISCONNECTED field, and handle event in a single instance of receiver. You can register a single receiver for multiple events and use intent.getAction() to check how to handle it.
UPD
Also you can make your receiver singleton, to prevent multiple registrations, and playing of multiple MediaPlayers
I was finally able to find a solution.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button startServiceButton;
BroadcastReceiver powerConnectionBroadcastReceiver;
IntentFilter powerDisconnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_DISCONNECTED");
IntentFilter powerConnectedIntentFilter = new IntentFilter("android.intent.action.ACTION_POWER_CONNECTED");
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startServiceButton = (ToggleButton) findViewById(R.id.startServiceButton);
powerConnectionBroadcastReceiver = new PowerConnectionBroadcastReceiver();
startServiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (startServiceButton.isActivated()) {
unregisterReceiver(powerConnectionBroadcastReceiver);
startServiceButton.setActivated(false);
Toast.makeText(MainActivity.this, "Service stopped", Toast.LENGTH_SHORT).show();
} else {
monitorBatteryChanges();
}
}
});
}
private void monitorBatteryChanges() {
registerReceiver(powerConnectionBroadcastReceiver, powerDisconnectedIntentFilter);
registerReceiver(powerConnectionBroadcastReceiver, powerConnectedIntentFilter);
startServiceButton.setActivated(true);
Toast.makeText(MainActivity.this, "Service started", Toast.LENGTH_SHORT).show();
}
}
PowerConnectionBroadcastReceiver.java
public class PowerConnectionBroadcastReceiver extends BroadcastReceiver {
MediaPlayer mediaPlayer;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
mediaPlayer = MediaPlayer.create(context, R.raw.alarm_1);
mediaPlayer.start();
mediaPlayer.setLooping(true);
Toast.makeText(context, "Alarm started", Toast.LENGTH_SHORT).show();
} else {
try {
if (mediaPlayer != null)
mediaPlayer.release();
Toast.makeText(context, "Alarm stopped", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
It may not be the best solution but it works :)
Thanks for the help.