I'm trying to put an app on google and they reject it in addition to not giving me a concrete answer.
It's an SMS-sending app. I don't keep any user data.
The user fills in 3 fields and is sent to a predefined toll-free number, which sends a reply.
The part of the number and the answer is not up to the app: it is just to facilitate the user's work.
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SEND_SMS"/>
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#drawable/tres"
android:label="#string/app_name"
android:roundIcon="#drawable/tres"
android:supportsRtl="true"
android:theme="#style/Theme.FieldLocalize"
tools:targetApi="31">
<!-- Sample AdMob app ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-4545343114224253~3369918696"/>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
private void requerirPermissao() {
if (!permissaoConcedida()) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.SEND_SMS}, 1);
}
}
private boolean permissaoConcedida() {
return ContextCompat.checkSelfPermission(this, android.Manifest.permission.SEND_SMS)
== PackageManager.PERMISSION_GRANTED;
}
Related
Sadly, Android 11 storage restrictions are too hard and confusing.
I'm trying to pick a document using the below code
fun onFile(activity: AppCompatActivity?, fragmentContext: Fragment?, isMultiple: Boolean?, pFileMimeTypes: Array<String>?): Intent {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
action = Intent.ACTION_OPEN_DOCUMENT
addCategory(Intent.CATEGORY_OPENABLE)
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, isMultiple ?: false)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
val fileMimeTypes = pFileMimeTypes ?: FileUtil.mimeTypes
intent.type = if (fileMimeTypes.size == 1) fileMimeTypes[0] else "*/*"
if (!fileMimeTypes.isNullOrEmpty()) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, fileMimeTypes)
}
val list = activity?.packageManager?.queryIntentActivities(intent, PackageManager.MATCH_ALL)
if (list?.size!! > 0) {
if (fragmentContext == null) {
activity.startActivityForResult(
Intent.createChooser(
intent,
activity.getString(R.string.m_selectFile_txt)
), FILE_CODE
)
} else {
fragmentContext.startActivityForResult(
Intent.createChooser(
intent,
activity.getString(R.string.m_selectFile_txt)
), FILE_CODE
)
}
}
// returning intent is not being used anywhere else
return intent
}
Although I have all files access permission Environment.isExternalStorageManager() but still after selecting document(PDF) from the external storage (download or any folder), OnActvityResult is being called with result code 0. I need the Uri of the selected document to proceed further.
For any other reference, below is my manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="*****Hidden*******">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_STORAGE_PERMISSION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:exported="true"
android:name=".Main2Activity"
android:launchMode="singleTask"
android:label="#string/title_activity_main2"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:theme="#style/AppTheme.NoActionBar">
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.attachmentmanager"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider"
tools:replace="android:resource" />
</provider>
</application>
<queries>
<intent>
<action android:name="android.intent.action.OPEN_DOCUMENT" />
<!-- If you don't know the MIME type in advance, set "mimeType" to "*/*". -->
<data android:mimeType="*/*" />
</intent>
<intent>
<action android:name="android.intent.action.PICK" />
<!-- If you don't know the MIME type in advance, set "mimeType" to "*/*". -->
<data android:mimeType="*/*" />
</intent>
</queries>
</manifest>
I must be missing some point. Everything is working fine below Android 11
Thanks in Advance.
startActivityForResult is deprecated
Refer this link
Use Activity Results API
Official Docs
I am moving from SDK version 30 to 31 and I add android:exported in intent-filter but still I am getting this error:
Merging Errors: Error: android:exported needs to be explicitly specified for . Apps targeting Android 12 and higher are required to specify an explicit value for android:exported when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.mycompany.webviewapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:name=".App"
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">
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
<activity android:name="com.mycompany.webviewapp.SplashActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.mycompany.webviewapp.MainActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.VIEW"></action>
</intent-filter>
</activity>
<service android:name="com.mycompany.webviewapp.FCM.MyFirebaseMessagingService">
</service>
<meta-data android:name="applovin.sdk.key"
android:value="sdk api here"/>
</application>
</manifest>
The reason is because some of the dependency libraries that you're using have elements which do not have "android:exported" attribute.
You need to do this:
Lower the version in your gradle to 30 and sync and build.
Go to your AndroidManifest.xml file and click on "Merged Manifest".
Find items such as Activity, Receiver, Service, etc that don't have "android:exported" attribute.
Then add them to your AndroidManifest.xml file in this way.
<activity
android:name="SomeActivity"
android:exported="false"
tools:node="merge"
tools:replace="android:exported" />
Now you can increase your version to 31.
I resolve my issue. I just check the merged manifest and look for reciver. In onesignal, I found out reciver with intent filter defined without android:exported. I just add android:exported="false".
I'm trying to integrate flurry into my android app. I'm using the recommended setting and have repositories{jcenter()} and
// Required for Flurry Analytics integration
compile 'com.flurry.android:analytics:8.2.0#aar'
// Optional - If you want to use the Ads SDK
compile 'com.flurry.android:ads:8.2.0#aar'
in the gradle as the docs suggest. I keep getting errors in the that Application is not resolved. The docs really blow and I'm not 100% sure what going on. I've never integrated flurry before can someone please help! I put the manifest and the class i'm using below. I know it doesn't have a key I'm still working on removing errors. I'm dumping the that class in the main file for simplicity for now.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tempconversion.october.com.myapplication">
<!-- Required permissions - Internet access -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- Highly Recommended permission - External memory pre-caching -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- Optional permission - Location based ad targeting -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="F to C and K"
android:roundIcon="#mipmap/ic_launcher_round"
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>
</application>
</manifest>
class in main file
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
new FlurryAgent.Builder()
.withLogEnabled(true)
.withCaptureUncaughtExceptions(true)
.withContinueSessionMillis(10)
.withLogLevel(VERBOSE)
.build(this, FLURRY_API_KEY);
}
}
Declare the application name in manifest.xml file.
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="F to C and K"
android:roundIcon="#mipmap/ic_launcher_round"
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>
</application>
I am trying to use gcm to push notifications on android devices. So far I have registered with gcm and sent my back-end the necessary information to make a post request to the gcm severs which builds a 200 response. All the steps have come together except the client side receiving the message. I don't get the message. Displayed here is my gcm listener class:
import com.google.android.gms.gcm.GcmListenerService;
public class MyGcmListenerService extends GcmListenerService {
public static final int MESSAGE_NOTIFICATION_ID = 435345;
private static final String TAG = "MyGcmListenerService";
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
sendNotification(from,message);
}
private void sendNotification(String title, String body) {
Context context = getBaseContext();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher).setContentTitle(title)
.setContentText(body);
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(MESSAGE_NOTIFICATION_ID, mBuilder.build());
}
}
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.google.android.c2dm.permission.RECEIVE"/>
<permission android:name="com.example.caesar.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.example.caesar.gcm.permission.C2D_MESSAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<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>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<recieve android:name = ".GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="com.example.caesar.gcm" />
</intent-filter>
</recieve>
</application>
// new manifest file
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.google.android.c2dm.permission.RECEIVE"/>
<permission android:name="com.example.caesar.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.example.caesar.gcm.permission.C2D_MESSAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<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>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<reciever
android:name = "com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="com.example.caesar.gcm" />
</intent-filter>
</reciever>
<service
android:name="com.example.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name="com.example.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
</application>
Actually looking at this further it looks like you haven't setup the receiver correctly. Seems you need to include at least.
<service
android:name="com.example.MyGcmListenerService "
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
And for the rest just follow that link.
You have to put your resgistration intent service at the end of yout Manifest file. Like this example:
<service
android:name="com.example.gcm.RegistrationIntentService"
android:exported="false">
</service>
Hope that help you, more information, you can visit this link and you can view an example of RegistrationIntentService here.
I'm using GCM in my android application and when I try to register the device with GCM (with the command gcm.register(SENDER_ID)) I get the SEVICE_NOT_AVAILABLE error, I tried what someone suggested here (the accepted solution) and I did get the registration id.
Why is it like that?
Android manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.appspot.smartgan"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="com.appspot.smartgan.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.appspot.smartgan.permission.C2D_MESSAGE" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light" >
<activity
android:name="com.appspot.smartgan.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=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.appspot.smartgan" />
</intent-filter>
</receiver>
<service
android:name=".GcmIntentService"
android:enabled="true" />
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name="com.appspot.smartgan.LoginActivity"
android:label="#string/title_activity_login"
android:windowSoftInputMode="adjustResize|stateVisible" >
</activity>
<activity
android:name="com.appspot.smartgan.ChildActivity"
android:label="#string/title_activity_child" >
</activity>
</application>
</manifest>
register method:
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String message = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
message = "Device registered, registration ID=" + regid;
Log.d("SMARTGAN_PLAY", "register completed");
// send registration id to the server
sendRegistrationIdToServer();
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException e) {
message = "Error:" + e.getMessage();
}
return message;
}
}.execute(null, null, null);
}
I think issue is regarding allowed IP addresses mentioned in your Google API project.
Please check details of the project and remove IP address if present under restrict use to IP address. I faced similar problem.
If you are receiving a Register ID it means you have registered the device successfully to the GCM.
Edit:
Here is a good tutorial for GCM: http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
<receiver
android:name="rockit.app.beardallstreetprimary.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="rockit.app.beardallstreetprimary" />
</intent-filter>
</receiver>
<service android:name="com.google.android.gcm.GCMIntentService" android:enabled="true" />
My GCM is set up based on the Tutorial i linked above so if you read through that aswell it should work for you it looks like your not far off. I will say the Manifest is very picky and you need to ensure that you link your Packages fully.
Also you dont need the Register Intent