I'm trying to show a message when a user places a call using the standard android dialer.
I have the following code in my Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTestButtonListener();
Log.i(LOG_TAG, "Activity started...");
}
private void setTestButtonListener()
{
Button testButton = (Button)this.findViewById(R.id.testButton);
testButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
Log.i(LOG_TAG, "Clicked on test...");
Toast.makeText(getApplicationContext(), (CharSequence)"You clicked on the test button" ,Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+150));
MainActivity.this.sendOrderedBroadcast(intent, null);
MainActivity.this.startActivity(intent);
Log.i(LOG_TAG, "intent broadcasted... I think... ");
}
});
}
Then in the BroadcastReceiver (well a class that derives from it):
public class OnMakingCallReceiver extends BroadcastReceiver
{
private static final String LOG_TAG = OnMakingCallReceiver.class.getSimpleName() + "_LOG";
#Override
public void onReceive(Context context,Intent intent)
{
Log.i(LOG_TAG, " got here!");
}
}
And then in the AndroidManifest.xml
<uses-permission android:name="android.permission.CALL_PHONE" />
<receiver android:name=".OnMakingCallReceiver" android:priority="999">
<intent-filter>
<action android:name="android.intent.action.CALL"/>
</intent-filter>
</receiver>
I click the test button and I see this output.
Clicked on test...
intent broadcasted... I think...
And thats all. I expected to see "got here!".
Any ideas why I don't?
Did you define the receiver in your AndroidManifest.xml?
Also, ACTION_CALL_BUTTON is sent when you click on something that goes directly to the dialer. Are you sure you're doing that.
I used this in AndroidManifest.xml and it works. I think the key thing is the intent NEW_OUTGOING_CALL in the intent-filter.
<receiver android:name=".OnMakingCallReceiver" android:exported="true" android:enabled="true">
<intent-filter android:priority="999">
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="android.intent.action.ACTION_CALL" />
</intent-filter>
</receiver>
Probably ACTION_CALL could be removed. Also this may need to be added to the manifest:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
Related
I have my main activity that start a service (Location service) and I want that service to broadcast the new location each time a new location is found.
Thanks to the log I know the service is working and I have new locations every seconds or so, but I never get the broadcast.
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = "mainActivity";
private CMBroadcastReceiver mMessageReceiver = new CMBroadcastReceiver();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// Start Service
startService(new Intent(this, LocationService.class));
super.onCreate(savedInstanceState);
}
#Override
public void onResume()
{
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, new IntentFilter(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE));
super.onResume();
}
#Override
public void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
}
CMBroadcastReceiver.java
public class CMBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CMBroadcastReceiver";
public static final String RECEIVE_LOCATION_UPDATE = "LOCATION_UPDATES";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received broadcast");
String action = intent.getAction();
if (action.equals(RECEIVE_LOCATION_UPDATE))
{
Log.i(TAG, "Received location update from service!");
}
}
}
LocationService.java
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.i(TAG, "onLocationChanged " + location);
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Log.i(TAG, "Broadcast sent");
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyclemapapp.gpstracker">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar">
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LocationService" android:process=":location_service" />
</application>
I the log I can see that "Broadcast Sent" But I never get the "Broadcast Received"
Any help will would be greatly appreciated.
EDIT:
Edited how the intent was created in the location service as Shaishav suggested.
Still doesn't work.
LocalBroadcastManager does not work across processes. Your Service is running in a separate process.
You can either run your Service in the same process as the Activity - by removing the process attribute from the <service> element - or use some sort of IPC instead - e.g., by sending and receiving the broadcasts on a Context instead of LocalBroadcastManager.
In your LocationService, send local broadcast using:
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
<service android:name=".LocationService" android:process=":location_service" />
Your service is in a separate process from the activity. LocalBroadcastManager is only for use in one process. Either remove android:process from the <service>, or use some IPC mechanism (e.g., system broadcasts, properly secured).
I have an app with two activities: MainActivity, which contains a URL entry field where the user can enter a YouTube video URL and press a submit button, to start the second activity, VideoActivity, which displays some information about this video (fetched from another web server).
The app also has a feature to receive intent via the Youtube application. When user presses the share button within the Youtube app, my app appears in the share list. Upon pressing share from the Youtube app, MainActivity should be brought to the front, and the URL should be posted within the MainActivity's URL field.
However, this only happens correctly on the first share. If the app is in the background when user shares from Youtube app, they are taken to whatever the last visible activity was, whether it is MainActivity or VideoActivity, (and even if it is MainActivity, the URL is not posted into the URL field, but the field is left in whatever state it was in when the app was last visible).
Here is my current AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.youcmt.youdmcapp">
<uses-permission android:name="android.permission.INTERNET"/>
<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="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
<activity
android:name=".VideoActivity"
android:parentActivityName=".MainActivity"/>
<service
android:name=".FetchVideoService"
android:exported="false"/>
</application>
</manifest>
Here is my MainActivity.java code:
public class MainActivity extends AppCompatActivity {
private ResponseReceiver mReceiver;
private EditText mUrlEditText;
private Button mSearchButton;
private ProgressBar mProgressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
super.onCreate(savedInstanceState);
mUrlEditText = findViewById(R.id.url_search_et);
Intent intent = getIntent();
if (intent.getType()!=null &&
intent.getType().equals("text/plain")) {
Bundle extras = getIntent().getExtras();
String value = extras.getString(Intent.EXTRA_TEXT);
if(value!=null)
{
mUrlEditText.setText(value);
}
}
mProgressBar = findViewById(R.id.progress_bar);
mSearchButton = findViewById(R.id.search_button);
mSearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
askForVideo(mUrlEditText.getText().toString());
mSearchButton.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
} catch (Exception e) {
mUrlEditText.setText("");
mUrlEditText.setHint(e.getMessage());
e.printStackTrace();
}
}
});
}
#Override
protected void onResume() {
super.onResume();
//register the ResponseReceiver
mReceiver = new ResponseReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(FETCH_VIDEO_INFO);
registerReceiver(mReceiver, intentFilter);
}
private void askForVideo (String url) throws Exception {
try {
Intent intent = FetchVideoService.newIntent(this, url);
startService(intent);
} catch (Exception e) {
mUrlEditText.setText(e.getMessage());
}
}
public class ResponseReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(EXTRA_VIDEO_STATUS, FAIL);
mProgressBar.setVisibility(View.INVISIBLE);
mSearchButton.setVisibility(View.VISIBLE);
if(status==FAIL)
{
mUrlEditText.setText("");
mUrlEditText.setHint("Error retrieving video!");
}
else if(status==SUCCESS) {
Video video = intent.getParcelableExtra(EXTRA_VIDEO);
Intent videoActivityIntent =
VideoActivity.newIntent(getApplicationContext(), video);
startActivity(videoActivityIntent);
}
}
}
#Override
protected void onPause() {
unregisterReceiver(mReceiver);
super.onPause();
}
}
I do not think any of the other files will be useful in understanding the problem. Although this seems like something many app creators should have to deal with, I can find no answers to this problem. Please comment if you feel I should add any additional information and thank you in advance for any help!
Update: testing demonstrates that after the first use of "Share" from YouTube (and considering app remains in the background), the MainActivity no longer receives any new intent on further shares. However, my app is still brought to the foreground somehow. This is very confusing to me.
When you share from another app, your MainActivity is brought to the front and onNewIntent() is called on it. You don't override onNewIntent() so you never see the share Intent.
I'm trying for well over 10 hours now and I can't seem to think about anyhting else. I tried every possible example on the internet, but to no avail.
I have NotificationMonitor class extending NotificationListenerService and I wanted to send message from this service to main activity(and possible other activities and services in the future) using Intent mechanism. I post code below:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testpackage.test">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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>
<service android:name=".NotificationMonitor"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
MainActivity.java
public class MainActivity extends Activity {
private TextView txtView;
private NotificationReceiver nReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtView = (TextView) findViewById(R.id.textView);
//create receiver
nReceiver = new NotificationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.testpackage.test.NOTIFICATION_MONITOR");
registerReceiver(nReceiver,filter);
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(nReceiver);
}
public void buttonClicked(View v){
if(v.getId() == R.id.btnTestBroadcast){
//send test intent without category
Log.d("ActivityMain","Button clicked");
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
sendBroadcast(i);
}
}
class NotificationReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.d("ActivityMain","Intent received: "+intent.getAction()+" has extra: "+intent.hasExtra("info"));
if (intent.hasCategory("com.testpackage.test.TEST_CATEGORY")) {
if (intent.hasExtra("info")) {
txtView.setText(intent.getStringExtra("info"));
}
}
}
}
}
NotificationMonitor.java
public class NotificationMonitor extends NotificationListenerService {
private NotificationMonitorReceiver receiver;
#Override
public void onCreate() {
super.onCreate();
receiver = new NotificationMonitorReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.testpackage.test.NOTIFICATION_MONITOR");
registerReceiver(receiver,filter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
//do something
sendInfo("notification posted");
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
//do something
sendInfo("notification removed");
}
#Override
public void onListenerConnected() {
//service created and listener connected
Log.d("NM","Listener connected!");
sendInfo("listener connected");
}
private void sendInfo(String info) {
Log.d("NM", "sendInfo called!");
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
i.addCategory("com.testpackage.test.TEST_CATEGORY");
i.putExtra("info", info);
sendBroadcast(i);
}
class NotificationMonitorReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//no categories intents get replied
Log.d("NM","Intent received: "+intent.getAction()+" has categories: "+(intent.getCategories()!=null));
if (intent.getCategories() == null) {
Intent i = new Intent("com.testpackage.test.NOTIFICATION_MONITOR");
i.addCategory("com.testpackage.test.TEST_CATEGORY");
sendBroadcast(i);
}
}
}
}
After running this app in debug mode of course I need to re-enable notification permissions, so when I do I see in logcat:
10-10 16:22:46.428 7330-7381/com.testpackage.test D/NM: Listener connected!
10-10 16:22:46.428 7330-7381/com.testpackage.test D/NM: sendInfo called!
well, I should receive broadcast in my application, shouldn't I?
After I click button:
10-10 16:22:57.607 7330-7330/com.testpackage.test D/ActivityMain: Button clicked
10-10 16:22:57.612 7330-7330/com.testpackage.test D/ActivityMain: Intent received: com.testpackage.test.NOTIFICATION_MONITOR has extra: false
10-10 16:22:57.619 7330-7330/com.testpackage.test D/NM: Intent received: com.testpackage.test.NOTIFICATION_MONITOR has categories: false
so the Intent is properly created and send from main activity, received back by the same activity and NotificationListenerService, has no categories so should get replied but nothing happens like when sendInfo method is called.
Please help, I have no other ideas about what might be wrong.
edit: I tested with regular services and of course Broadcasts are working just fine. Is there by chance any possibility that you just can't sendBroadcast from this particular extended service class?
Oficially, I'm a moron. Answer is: I didn't set up Category filter in IntentFilter and this is why I received zero properly sent intents from my class. So, long story short, to "fix" this mistake all one needs to do is add:
filter.addCategory("com.testpackage.test.TEST_CATEGORY");
and that's it. Thank you for your attention.
I am trying to get notification content and store it into the database automatically, as soon as the notification is released from parse.com the data should be saved in the database whether the user clicks to view the notification or not.
This is what i have tried so far but still not working. It only save the content into a database when a user clicks on the notification.
Application.java
public class Application extends android.app.Application{
public Application() {
}
#SuppressWarnings("deprecation")
public void onCreate() {
super.onCreate();
// Initialize the Parse SDK.
Parse.initialize(this, "YwWVJ1IdukAXQx6WqksoRlA94k1OoJ6cHqdgsInHaTN", "fCh5pWNiSaHaFtuACufgs9va6wq31pte8nuaiCAG6Nb");
// Specify an Activity to handle all pushes by default.
PushService.setDefaultPushCallback(this, Notification.class);
}
}
FireBackground.java
public class FireBackground extends ParsePushBroadcastReceiver {
#Override
public void onPushOpen(Context context, Intent intent) {
Intent i = new Intent(context, Notification.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
Notification.java
public class Notification extends ListActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ParseAnalytics.trackAppOpened(getIntent());
Intent intent = getIntent();
Bundle extras = intent.getExtras();
String message="";
SQLiteDatabase db;
db = openOrCreateDatabase(
"notification.db"
, SQLiteDatabase.CREATE_IF_NECESSARY
, null
);
//CREATE TABLES AND INSERT MESSAGES INTO THE TABLES
String CREATE_TABLE_NOTICES = "CREATE TABLE IF NOT EXISTS notices ("
+ "ID INTEGER primary key AUTOINCREMENT,"
+ "NOTIFICATIONS TEXT)";
db.execSQL(CREATE_TABLE_NOTICES);
if(extras !=null){
String jsonData = extras.getString("com.parse.Data");
try{
JSONObject notification = new JSONObject(jsonData);
message = notification.getString("alert");
String sql =
"INSERT or replace INTO notices (NOTIFICATIONS) "
+ "VALUES('" + message + "')";
db.execSQL(sql);
}
catch(JSONException e){
Toast.makeText(getApplicationContext(), "Something went wrong with the notification", Toast.LENGTH_SHORT).show();
}
}
}
android manifest file
<application
android:name="com.parse.starter.Application"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppBaseTheme" >
<activity
android:name="com.parse.starter.Notification"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.parse.PushService" />
<receiver android:name=".HomeActivity"
android:exported="false" >
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.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" />
<!--
IMPORTANT: If you change the package name of this sample app,
change "com.parse.starter" in the lines
below to match the new package name.
-->
<category android:name="com.parse.starter" />
</intent-filter>
</receiver>
I would be grateful if anyone would direct me to use the correct method. Thanks
Your code for saving the notification data to your local database runs in the Activity. And the activity is started when the notification is opened, hence the nameonPushOpen. Hence, move the code that saves to the database to FireBackground in a method like onPushRecieved(...)
You should override onPushReceive method in your BroadcastReceiver and than get necessary data
from intent.
Here is my example with retreiving jsonData:
#Override
protected void onPushReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String jsonData = extras.getString("com.parse.Data");
DBServiceFlow.save(intent);
} catch (JSONException | ParseException e) {
Log.e(TAG, "", e);
}
}
Then you could implement your own Service with background thread to save your data. For example you could just use IntentService
public class DBService extends IntentService {
#Override
public void onHandleIntent(Intent intent) {
if (intent.getAction() == "com.tac.save_notification") {
//parse your json here...
DBHelper.save(...);
}
}
}
PS: never work with DB in main thread. (like you show in your Notification Activity)
I'm trying to send message to my phone with this app, without using network usage, but my code doesn't work. I followed some tutorial, check android dev and I haven't found anything (in my logcat I don't have error). Could you help me to find out my problem.
My information about compilation, compiler and phone:
Android Studio 1.0.1
API 19 Android 4.4.4 (kitkat)
Build 19
Android phone version 4.4.4
Manifest:
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
Function of my main activity:
Context context;
String sender;
String body;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get current context
context = this;
//App started
Toast.makeText(context, "Started", Toast.LENGTH_LONG).show();
CheckApp();
}
private void CheckApp() {
sender = "1234";
body = "Android sms body";
//Get my package name
final String myPackageName = getPackageName();
//Check if my app is the default sms app
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
//Get default sms app
String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(context);
//Change the default sms app to my app
Intent intent = new Intent( Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());
startActivity(intent);
//Write the sms
WriteSms(body, sender);
//Change my sms app to the last default sms app
Intent intent2 = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent2.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);
startActivity(intent2);
}
else{
//Write the sms
WriteSms(body, sender);
}
}
//Write the sms
private void WriteSms(String message, String phoneNumber) {
//Put content values
ContentValues values = new ContentValues();
values.put(Telephony.Sms.ADDRESS, phoneNumber);
values.put(Telephony.Sms.DATE, System.currentTimeMillis());
values.put(Telephony.Sms.BODY, message);
//Insert the message
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
context.getContentResolver().insert(Telephony.Sms.Sent.CONTENT_URI, values);
}
else {
context.getContentResolver().insert(Uri.parse("content://sms/sent"), values);
}
}
Well, this is what i wanna do but with my own app and not with the app Fake Text Message that downloaded to the play store.
Make the fake message and what should i see on my default sms app:
With the help from Mike M. I finally finished my program. So, this is the code that you must add to your app to be able to send sms without using network:
Manifest:
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- My activity -->
<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>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".ComposeSmsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
Main Activity:
Context context;
Button button;
String sender,body,defaultSmsApp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get current context
context = this;
//Set composant
button = (Button) findViewById(R.id.button);
//Get default sms app
defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(context);
//Set the number and the body for the sms
sender = "0042";
body = "Android fake message";
//Button to write to the default sms app
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Get the package name and check if my app is not the default sms app
final String myPackageName = getPackageName();
if (!Telephony.Sms.getDefaultSmsPackage(context).equals(myPackageName)) {
//Change the default sms app to my app
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());
startActivityForResult(intent, 1);
}
}
});
}
//Write to the default sms app
private void WriteSms(String message, String phoneNumber) {
//Put content values
ContentValues values = new ContentValues();
values.put(Telephony.Sms.ADDRESS, phoneNumber);
values.put(Telephony.Sms.DATE, System.currentTimeMillis());
values.put(Telephony.Sms.BODY, message);
//Insert the message
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
context.getContentResolver().insert(Telephony.Sms.Sent.CONTENT_URI, values);
}
else {
context.getContentResolver().insert(Uri.parse("content://sms/sent"), values);
}
//Change my sms app to the last default sms
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);
context.startActivity(intent);
}
//Get result from default sms dialog pops up
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
final String myPackageName = getPackageName();
if (Telephony.Sms.getDefaultSmsPackage(context).equals(myPackageName)) {
//Write to the default sms app
WriteSms(body, sender);
}
}
}
}
As a result of adding things in your manifest you must add 4 classes: SmsReceiver, MmsReceiver, ComposeSmsActivity and HeadlessSmsSendService. You can let them empty as shown below.
SmsReceiver:
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
MmsReceiver:
public class MmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
ComposeSmsActivity:
public class ComposeSmsActivity extends ActionBarActivity {
}
HeadlessSmsSendService:
public class HeadlessSmsSendService extends IntentService {
public HeadlessSmsSendService() {
super(HeadlessSmsSendService.class.getName());
}
#Override
protected void onHandleIntent(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
If you need more help to understand this program have a look there:
Youtube - DevBytes: Android 4.4 SMS APIs
Android developers - Getting Your SMS Apps Ready for KitKat
Possiblemobile - KitKat SMS and MMS supports