Android Send SMS Crash - java

I want to sent SMS with my Application with :
Intent smsIntent = new Intent(Intent.ACTION_VIEW);
smsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
smsIntent.setData(Uri.parse("smsto:" + sms));
smsIntent.putExtra("smsto", sms);
smsIntent.putExtra("sms_body", "MYSMSBOBY");
mActivity.startActivity(smsIntent);
It's work fine in devices that there is SMS Application, but in some devices i get this crash error:
No Activity found to handle Intent { act=android.intent.action.VIEW dat=smsto:xxxxxxxxxx flg=0x10000000 (has extras) }
Any idea how i can recognize if SMS Application installed on the device?

Any idea how i can recognize if SMS Application installed on the device?
While you can use PackageManager to see if there's any app to handle your intent, that's should not be really of your concern at all. What you should take care of is just the crash itself, so instead of just:
mActivity.startActivity(smsIntent);
you should at least have generic exception handling code:
try {
mActivity.startActivity(smsIntent);
} catch ( Exception e ) {
e.printStackTrace();
// show toast or something so user knows why it is not working
}
and catch any failure of startActivity(). You may also want to make create separate catch for this particular type of exception, ActivityNotFoundException

<!-- SMS -->
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
/**
* Test if device can send SMS
* #param context
* #return
*/
public static boolean canSendSMS(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
}

Related

Getting Empty SMS body

Hi trying to send SMS with android using below code.
public static void sendsmsstd(String number, String message, Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("vnd.android-dir/mms-sms");
intent.putExtra("address", number);
intent.putExtra("sms-body", message);
context.startActivity(intent);
}
Many sites have suggested it , but when code runs and SMS app opens, it choose right contact to send message but message body is always empty.
What else can be done to fix it. I m missing some code.
You're using sms-body. Change that to sms_body and that should fix it.

Security Exception: Permission Denial

The app used to run. However, just recently it began to stop working. The device is running Android Nutella. Below is the LogCat.
java.lang.SecurityException: Permission Denial: reading com.google.android.music.store.ConfigContentProvider uri content://com.google.android.music.ConfigContent/one-key/2/ExplicitRestrictedByParentControl from pid=2500, uid=10373 requires the provider be exported, or grantUriPermission()
The app crashes in the the following code snippet on the last line(contained in a SongParser method).
String[] projection2 = {MediaStore.Audio.Media.ARTIST};
Uri songUri=null;
try {
songUri = Uri.parse("content://com.google.android.music.MusicContent/audio");
} catch (NullPointerException e){
e.printStackTrace();
}
if (songUri!=null) {
CursorLoader cl2 = new CursorLoader(context,
songUri, projection2, null, null, null);
cursor = cl2.loadInBackground();
I grant the Uri permissions in the following method after asking for permissions through the runtime permissions methods.
private void startService() {
//start intent to RssService for feedback
intent = new Intent(getActivity(), SongService.class);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
getContext().grantUriPermission("xxx.xxx.xxx.SongService",Uri.parse("content://com.google.android.music.MusicContent/audio"),Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(SongService.RECEIVER, resultReceiver);
getActivity().startService(intent);
}
Here is where SongService calls SongParser.
#Override
protected void onHandleIntent(Intent intent) {
List<String> eventItems= null;
if (haveNetworkConnection()) {
parser = new SongParser();
eventItems = parser.getAllArtists(getApplicationContext());
}
Bundle bundle = new Bundle();
bundle.putSerializable(ITEMS, (Serializable) eventItems);
ResultReceiver receiver = intent.getParcelableExtra(RECEIVER);
receiver.send(0, bundle);}}
I have contained the permissions in the manifest as well. Again, this exception seemingly happened on its own.
<permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
What's happening is that for some reason, the (exported) MusicContent provider will redirect to ConfigContentProvider, which is not exported.
It seems that the way to solve it is to open Google Play Music. If you haven't launched it in a while, it will redirect to com.google.android.music.store.ConfigContentProvider and trigger a SecurityException. It's kind of problematic but at least I can tell my users what to do. Let me know if you can come up with something better.
It might also be a good idea to file a bug.
You do not have access to that ContentProvider. It is not exported, and that app did not pass you a Uri that you can use to access it.
Since presumably the Uri is from an app that you did not write, apparently an update to that app changed this behavior.

Android - Send Telegram message to a specific number

I'm trying to send a Telegram message to a specific number from within my Android app. Right now my code launches Telegram app, and then the user has to select the destinatary. What I want to do is to send the message to the specified number, without having the user select the contact. My code is as follows:
/**
* Intent to send a telegram message
* #param msg
*/
void intentMessageTelegram(String msg)
{
final String appName = "org.telegram.messenger";
final boolean isAppInstalled = isAppAvailable(mUIActivity.getApplicationContext(), appName);
if (isAppInstalled)
{
Intent myIntent = new Intent(Intent.ACTION_SEND);
myIntent.setType("text/plain");
myIntent.setPackage(appName);
myIntent.putExtra(Intent.EXTRA_TEXT, msg);//
mUIActivity.startActivity(Intent.createChooser(myIntent, "Share with"));
}
else
{
Toast.makeText(mUIActivity, "Telegram not Installed", Toast.LENGTH_SHORT).show();
}
}
You can't send to special number, But You can do this by USERID
try {
Intent telegramIntent = new Intent(Intent.ACTION_VIEW);
telegramIntent.setData(Uri.parse("http://telegram.me/USERID"));
startActivity(telegramIntent);
} catch (Exception e) {
// show error message
}
This code will show user an alert for choosing applications that support telegram uri's like Telegram itself and Mobogram!
Tip: don't set package name. some people install telegram alternatives like mobogram.
The Telegram Android App does not have a way to send messages directly to telegram users, so if you use the share intent, you'll get what telegram / any other app wants to do with the message shared. In this case, open the contact list to send this message to him.
If you want to send messages directly to Telegram users you should use the Telegram API
https://core.telegram.org/api#getting-started
once you have configured your API key in your app, you could send messages, read them or even get the telegram contacts with these methods
https://core.telegram.org/methods
This one worked for me:
try {
Intent telegram = new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/USER_NAME"));
telegram.setPackage("org.telegram.messenger");
startActivity(telegram);
}catch (Exception e)
{
Toast.makeText(getContext(), "Telegram app is not installed", Toast.LENGTH_LONG).show();
}
Tip: You can get USER_NAME by click on you telegram profile option you will get option of username in Account session --> if username is none create unique username and put here its work for me.
This one worked for me:
//check if application is installed first before running this code.
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("http://telegram.me/+UT_USER_ID_HERE"));
final String appName = "org.telegram.messenger";
i.setPackage(appName);
this.startActivity(i);
try the intent like this
tg://resolve?domain=YOUR_USER_ID
it's more direct then https://t.me
I'm using this for send message on background :
this cod is api telegram for use send message by url token bot
1 - use WebView on xml like this :
<WebView
android:id="#+id/webView_sendToTelegram"
android:layout_width="0dp"
android:layout_height="0dp"/>
2 - on java use this cod:
public static void SendMessageToBotTelegram(String chatID, String text, String botToken,WebView webView) {
webView.loadUrl(MessageFormat.format("https://api.telegram.org/bot{0}/sendMessage?chat_id={1}&text={2}", botToken, chatID, text));
}
chatID : your telegram id #RawDataBot for get id
text : text your message
botToken : your bot for get message if you don't have bot using #BotFather for crate bot
webView : your id WebView on xml

Prevent Android phone from connecting to WiFi network unless my app approves it?

I want to develop an app that can prevent connection to a WiFi network unless I approve it. I want to be able to query the MAC address of the access point and compare that to a list of known addresses corresponding to SSIDs. The goal of the app is to protect users from accidentally connecting to malicious access points, such as the types that can be produced with pineapple devices.
I'm not clear from my research how I would achieve this goal. Questions such as How to be notified on wifi network status change? explain how to detect the connection has happened, but for my use case that's already too late.
Neither ConnectivityManager nor WifiManager seem to offer methods for adding listeners that could interrupt a connection in progress.
Some thoughts I've had for a solution:
Install myself as a proxy and make the decision as to whether to allow data through. However, this doesn't seem to be an option based on Do Android proxy settings apply to all apps on the device? (hint: the answer is "No").
Replace the existing WiFi manager with something of my own creation. However, I've really struggled to find any information in the Android developer guides regarding replacing system components. Consequently, I'm not sure this is possible on non-rooted phones.
Store the network passwords within my app and set the passwords in the WiFi manager to nonsense values. Then capture a broadcast message that warns of a failed connection (presumably something like WifiManager.WPS_AUTH_FAILURE) and selectively decide to reconnect back to that network. Might be a possible (if ugly) solution, but can I set the password back to a nonsense value while the network is still connected, to ensure we don't quietly connect to another SSID of the same name? I'm not sure. It occurs to me that pineapple devices would probably accept any password, thus rendering this approach void.
Find some way to prevent Android automatically connecting to known networks (i.e. networks that have been used before or have a password stored with them). Then I could manage all connections/disconnections from my app. I can't see how to do this manually on my phone, however, so I'm doubtful this is possible programmatically.
Can anyone suggest an approach that would work on a non-rooted phone?
You can't implement a very robust system without rooting the device. Here's the closest you can get, I think:
Use getConfiguredNetworks() to fetch a list of networks currently configured on the user's device
For each WifiConfiguration in the list, set the public field BSSID to the desired "safe" MAC address
Call saveConfiguration() to persist the changes
Alternatively for step (2.), you could call disableNetwork() for each configured network, and selectively enabled them based on the BSSID. Note that MAC addresses can still be spoofed fairly easily.
you can listen to connectivity change of wifi and act on that events to enable disable wifi
private ConnectivityManager connectionManager;
boolean previousConnectivityStatus;
private WifiManager wifiManager;
/* Register Connectivity Receiver */
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
context.registerReceiver(networkBroadcastReceiver, intentFilter);
/* Register Wifi State Listener */
IntentFilter wifiStateIntentFilter = new IntentFilter();
wifiStateIntentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
context.registerReceiver(wifiStateReceiver, wifiStateIntentFilter);
connectionManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
private BroadcastReceiver wifiStateReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
Utility.traceM("NetworkController.wifiStateReceiver.new BroadcastReceiver() {...}::onReceive");
int extraWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
switch (extraWifiState)
{
case WifiManager.WIFI_STATE_DISABLED:
{
Utility.trace("Broadcast Wifi State Disabled");
if(isWifiStateEventsEnabled)
{
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_DISABLED));
}
break;
}
case WifiManager.WIFI_STATE_ENABLED:
{
Utility.trace("Broadcast Wifi State Enabled");
if(isWifiStateEventsEnabled)
{
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_ENABLED));
}
break;
}
}
}
};
private BroadcastReceiver networkBroadcastReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
Utility.traceM("NetworkController.networkBroadcastReceiver.new BroadcastReceiver() {...}::onReceive");
boolean connectivityStatus = isInternetConnectivityAvailable();
if (previousConnectivityStatus != connectivityStatus)
{
if (connectivityStatus)
{
previousConnectivityStatus = true;
Utility.trace("Broadcast Internet Available");
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_CONNECTED));
}
else
{
previousConnectivityStatus = false;
Utility.trace("Broadcast Internet Disconnected");
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_DISCONNECTED));
}
}
}
};
as you know when connecting to the Wifi the sifi manager app displays a hint message under the Wifi name that is connecting,
like connecting, authenticating, obtaining IP ... etc
so i tried to search how can detect those stages of connecting to a Wifi network
i came to an answer showing how is this done,
it was done using the a receiver to SUPPLICANT_STATE_CHANGED_ACTION
and i tried to implement it adding the code to just disconnect ... and that was success as the Wifi never got connected, the icon did not appear on the notification bar
and the logs keep repeating the steps, though some how it say's connected (at logs) but nothing actually appears on the device itself, so maybe it got connected for like (10 MS)
anyhow , below is the code i used:
public class MyNetworkMonitor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// EXTRA_BSSID
// SUPPLICANT_STATE_CHANGED_ACTION
// EXTRA_NEW_STATE
// Log.i("YAZAN", intent.getAction() + " " +
// intent.getStringExtra(WifiManager.EXTRA_BSSID));
// Log.i("YAZAN", intent.getAction() + " "
// +intent.getStringExtra(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
// Log.i("YAZAN", intent.getAction() + " "
// +intent.getStringExtra(WifiManager.EXTRA_NEW_STATE));
//Log.i("YAZAN", intent.getAction() + " " + intent.getStringExtra(WifiManager.EXTRA_BSSID));
String action = intent.getAction();
if(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)){
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Log.d("YAZAN", ">>>>SUPPLICANT_STATE_CHANGED_ACTION<<<<<<");
SupplicantState supl_state=((SupplicantState)intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
switch(supl_state){
case ASSOCIATED:Log.i("YAZAN", "ASSOCIATED");
break;
case ASSOCIATING:
Log.i("YAZAN", "ASSOCIATING");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case AUTHENTICATING:Log.i("YAZAN", "Authenticating...");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case COMPLETED:Log.i("YAZAN", "Connected");
break;
case DISCONNECTED:Log.i("YAZAN", "Disconnected");
break;
case DORMANT:Log.i("YAZAN", "DORMANT");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case FOUR_WAY_HANDSHAKE:Log.i("YAZAN", "FOUR_WAY_HANDSHAKE");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case GROUP_HANDSHAKE:Log.i("YAZAN", "GROUP_HANDSHAKE");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case INACTIVE:Log.i("YAZAN", "INACTIVE");
break;
case INTERFACE_DISABLED:Log.i("YAZAN", "INTERFACE_DISABLED");
break;
case INVALID:Log.i("YAZAN", "INVALID");
break;
case SCANNING:Log.i("YAZAN", "SCANNING");
break;
case UNINITIALIZED:Log.i("YAZAN", "UNINITIALIZED");
break;
default:Log.i("YAZAN", "Unknown");
break;
}
int supl_error=intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
if(supl_error==WifiManager.ERROR_AUTHENTICATING){
Log.i("YAZAN", "ERROR_AUTHENTICATING!");
}
}//if
}// onReceive()
where ever you find a wifi.disconnect(); thats how i interrupted the connection.
what remains here, is to get the network name or mac address to allow or disallow the process to complete
Permissions:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
adding the broadcast receiver:
<receiver android:name=".MyNetworkMonitor" >
<intent-filter>
<action android:name="android.net.wifi.supplicant.STATE_CHANGE" />
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
thanks

How to start a Skype call from an Android app?

I'm trying to start a Skype intent from my Android App, passing a phone number. So far, thanks to other people who ad similiar needs here on stackoverflow, I've managed to start skype, but still I can't pass the phone number. This is the code I'm using:
Intent sky = new Intent("android.intent.action.CALL_PRIVILEGED");
sky.setClassName("com.skype.raider",
"com.skype.raider.Main");
sky.setData(Uri.parse("tel:" + number));
Log.d("UTILS", "tel:" + number);
ctx.startActivity(sky);
What's happening is that skype starts, but gives me a toast saying that the number is not valid, and suggests me to add the international prefix.
The Log.d gives me tel:+39........ (the number works, I'm using it also for
public static void call(String number, Context ctx) {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:" + number));
ctx.startActivity(callIntent);
} catch (ActivityNotFoundException e) {
Log.e("helloandroid dialing example", "Call failed", e);
}
}
In fact, when I go to the Skype's view for calling, I see it's been composed +0
So what it seems to me is that I'm passing the phone number in the wrong way, or to the wrong Activity....any help would be very appreciated!
In the meantime, I just want to say that StackOverflow simply rocks.
See this answer: https://stackoverflow.com/a/8844526/819355
Jeff suggests using a skype:<user name> instead of tel:<phone number>
After some studing of the skype apk with apktool, as suggested in that answer, I came up with this code, for me it's working:
public static void skype(String number, Context ctx) {
try {
//Intent sky = new Intent("android.intent.action.CALL_PRIVILEGED");
//the above line tries to create an intent for which the skype app doesn't supply public api
Intent sky = new Intent("android.intent.action.VIEW");
sky.setData(Uri.parse("skype:" + number));
Log.d("UTILS", "tel:" + number);
ctx.startActivity(sky);
} catch (ActivityNotFoundException e) {
Log.e("SKYPE CALL", "Skype failed", e);
}
}
Refer to Skype developer: Skype URI tutorial: Android apps
Also remember to add "?call" in your url. E.g
intent.setData(Uri.parse("skype:" + phoneNumber + "?call"));
Without it, Skype may not dial the number.
You should not include a specific class when calling an external app. Let the user decide of the application he/she wants to use. That's the way android has been designed and it's a better solution than obliging people to use a soft (moreover quite a slow, closed and inconvenient app to my mind).
In other words, just use the Uri, that's the job of skype of declaring its ability to capture such intents.
Refer this skype doc link Skype URI tutorial: Android apps
First need to check skype is installed or not using
/**
* Determine whether the Skype for Android client is installed on this device.
*/
public boolean isSkypeClientInstalled(Context myContext) {
PackageManager myPackageMgr = myContext.getPackageManager();
try {
myPackageMgr.getPackageInfo("com.skype.raider", PackageManager.GET_ACTIVITIES);
}
catch (PackageManager.NameNotFoundException e) {
return (false);
}
return (true);
}
initiate skype uri using
/**
* Initiate the actions encoded in the specified URI.
*/
public void initiateSkypeUri(Context myContext, String mySkypeUri) {
// Make sure the Skype for Android client is installed.
if (!isSkypeClientInstalled(myContext)) {
goToMarket(myContext);
return;
}
// Create the Intent from our Skype URI.
Uri skypeUri = Uri.parse(mySkypeUri);
Intent myIntent = new Intent(Intent.ACTION_VIEW, skypeUri);
// Restrict the Intent to being handled by the Skype for Android client only.
myIntent.setComponent(new ComponentName("com.skype.raider", "com.skype.raider.Main"));
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Initiate the Intent. It should never fail because you've already established the
// presence of its handler (although there is an extremely minute window where that
// handler can go away).
myContext.startActivity(myIntent);
return;
}
if Skype is not installed then redirect to market place using
/**
* Install the Skype client through the market: URI scheme.
*/
public void goToMarket(Context myContext) {
Uri marketUri = Uri.parse("market://details?id=com.skype.raider");
Intent myIntent = new Intent(Intent.ACTION_VIEW, marketUri);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
myContext.startActivity(myIntent);
return;
}

Categories