-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7d902e1
commit 098c035
Showing
42 changed files
with
1,373 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,42 @@ | ||
# SMSNotify | ||
Android app to automatically send text messages from any API endpoint | ||
An Android app to automatically send text messages from any API endpoint. The app pols the server(s) every minute for new messages. If there are any messages it will send them one by one and hit the completed API endpoint with the message id once it has been sent successfully. | ||
|
||
*Please note this app has been thrown together and is not fully tested. It is designed to work running on a phone that is plugged in 24/7. Android 6+ has some power management features that may cause this app to stop running in the background if the device is not plugged in. The app also has no UI level logging or error messages and should be used as more of a starting point rather than a complete solution* | ||
|
||
*Android has an anti-spam feature to protect your phone from sending too many messages too quickly so nasty apps can't rack up excessive carrier charges. You will need to disable this feature if you intend to send many messages quickly. A guide is available at https://www.xda-developers.com/change-sms-limit-android/ on how to do this.* | ||
|
||
*Always check your carrier limits and fact sheets so your are not violating your terms of service* | ||
|
||
## API | ||
You can configure your own urls for this app to communicate to but you must have the 2 following endpoints at each url. | ||
|
||
### Get Pending Messages | ||
|
||
`http://yoururl.com/anyOtherSuffix/SMSPending?key={optional}` | ||
|
||
The key is optional to check on your server to add some level of security that only you can retrieve the pending sms. This endpoint should return a JSON array of any pending SMS to send. The JSON should be in the following format | ||
``` | ||
{ | ||
id: integer, | ||
mobile: string, | ||
msg: string | ||
} | ||
``` | ||
|
||
* id: A unique id for the sms which will be sent back to the server once the message has been sent. | ||
* mobile: The mobile number to send the message to, this doesn't need the country code if sent locally. | ||
* msg: The sms message to be sent. | ||
|
||
### Message Sent | ||
|
||
`http://yoururl.com/anyOtherSuffix/SMSSent?id={msgId}&key={optional}` | ||
|
||
This endpoint doesn't need to return anything and can be used for your server to mark the SMS as sent so you're not sending duplicates. Each time an SMS is sent via the app this URL will be called with the id of the sms that was sent and the optional API Key. | ||
|
||
## Using The App | ||
1. Download and install the latest release, or compile it yourself. | ||
2. Enter the endpoints you want the app to check. You must fully qualify these endpoings with http:// or https://. You can enter as many as you like the app will check all the endpoints each time is runs | ||
3. enter an optional API key to be used in the requests to your server. If you leave this blank no API key will be sent | ||
|
||
## Going Further | ||
Feel free to download and edit the app as required if you need something more specific or just want to make some changes! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
apply plugin: 'com.android.application' | ||
|
||
android { | ||
compileSdkVersion 26 | ||
defaultConfig { | ||
applicationId "com.smsnotify" | ||
minSdkVersion 19 | ||
targetSdkVersion 26 | ||
versionCode 1 | ||
versionName "1.0" | ||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||
} | ||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
} | ||
|
||
dependencies { | ||
compile 'com.android.support:design:26.1.0' | ||
implementation fileTree(dir: 'libs', include: ['*.jar']) | ||
implementation 'com.android.support:appcompat-v7:26.1.0' | ||
testImplementation 'junit:junit:4.12' | ||
androidTestImplementation 'com.android.support.test:runner:1.0.1' | ||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1},"path":"app-release.apk","properties":{"packageId":"com.smsnotify","split":"","minSdkVersion":"19"}}] |
26 changes: 26 additions & 0 deletions
26
app/src/androidTest/java/com/intelliguard/smsnotify/ExampleInstrumentedTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.smsnotify; | ||
|
||
import android.content.Context; | ||
import android.support.test.InstrumentationRegistry; | ||
import android.support.test.runner.AndroidJUnit4; | ||
|
||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
/** | ||
* Instrumented test, which will execute on an Android device. | ||
* | ||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a> | ||
*/ | ||
@RunWith(AndroidJUnit4.class) | ||
public class ExampleInstrumentedTest { | ||
@Test | ||
public void useAppContext() throws Exception { | ||
// Context of the app under test. | ||
Context appContext = InstrumentationRegistry.getTargetContext(); | ||
|
||
assertEquals("com.smsnotify", appContext.getPackageName()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.smsnotify"> | ||
|
||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission android:name="android.permission.READ_SMS" /> | ||
<uses-permission android:name="android.permission.WRITE_SMS" /> | ||
<uses-permission android:name="android.permission.SEND_SMS" /> | ||
<uses-permission android:name="android.permission.WAKE_LOCK" /> | ||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | ||
|
||
<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"> | ||
<service android:name=".ServiceTest" /> | ||
|
||
<receiver android:name=".ReceiverCall"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.BOOT_COMPLETED" /> | ||
</intent-filter> | ||
</receiver> | ||
|
||
<activity | ||
android:name=".MainActivity" | ||
android:label="@string/title_activity_main" | ||
android:theme="@style/AppTheme.NoActionBar"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
|
||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
</application> | ||
|
||
</manifest> |
163 changes: 163 additions & 0 deletions
163
app/src/main/java/com/intelliguard/smsnotify/MainActivity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package com.smsnotify; | ||
|
||
import android.Manifest; | ||
import android.content.Context; | ||
import android.content.DialogInterface; | ||
import android.content.Intent; | ||
import android.content.SharedPreferences; | ||
import android.content.pm.PackageManager; | ||
import android.os.Bundle; | ||
import android.support.design.widget.TextInputEditText; | ||
import android.support.v4.app.ActivityCompat; | ||
import android.support.v4.content.ContextCompat; | ||
import android.support.v7.app.AlertDialog; | ||
import android.support.v7.app.AppCompatActivity; | ||
import android.view.View; | ||
import android.view.WindowManager; | ||
import android.widget.AdapterView; | ||
import android.widget.ArrayAdapter; | ||
import android.widget.Button; | ||
import android.widget.EditText; | ||
import android.widget.LinearLayout; | ||
import android.widget.ListView; | ||
import android.widget.Toast; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
public class MainActivity extends AppCompatActivity { | ||
ArrayList<String> listItems = new ArrayList<String>(); | ||
ArrayAdapter<String> adapter; | ||
|
||
@Override | ||
protected void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
setContentView(R.layout.activity_main); | ||
addListeners(); | ||
setupListview(); | ||
setupApiKey(); | ||
checkPermission(); | ||
} | ||
|
||
private void checkPermission() { | ||
// Here, thisActivity is the current activity | ||
if (ContextCompat.checkSelfPermission(this, | ||
Manifest.permission.SEND_SMS) | ||
!= PackageManager.PERMISSION_GRANTED) { | ||
|
||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS}, 0); | ||
} else { | ||
startService(new Intent(this, ServiceTest.class)); | ||
} | ||
} | ||
|
||
private void setupListview() { | ||
//add adapter | ||
adapter = new ArrayAdapter<String>(this, | ||
android.R.layout.simple_list_item_1, | ||
listItems); | ||
final ListView lstEndpoints = findViewById(R.id.lstEndpoints); | ||
lstEndpoints.setAdapter(adapter); | ||
|
||
//add items to list | ||
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.preferences_endpoints), Context.MODE_PRIVATE); | ||
Map<String, ?> prefs = sharedPref.getAll(); | ||
for (Map.Entry<String, ?> entry : prefs.entrySet()) { | ||
listItems.add(entry.getValue().toString()); | ||
} | ||
|
||
//link on long hold | ||
lstEndpoints.setLongClickable(true); | ||
lstEndpoints.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { | ||
public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) { | ||
return listItem_onLongClick(position); | ||
} | ||
}); | ||
} | ||
|
||
private boolean listItem_onLongClick(int position) { | ||
//remove endpoint from shared pref | ||
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.preferences_endpoints), Context.MODE_PRIVATE); | ||
Map<String, ?> prefs = sharedPref.getAll(); | ||
Set keys = prefs.keySet(); | ||
String key = keys.toArray()[position].toString(); | ||
SharedPreferences.Editor editor = sharedPref.edit(); | ||
editor.remove(key); | ||
editor.commit(); | ||
//update list | ||
listItems.remove(position); | ||
adapter.notifyDataSetChanged(); | ||
return true; | ||
} | ||
|
||
private void setupApiKey() { | ||
final Button btnSaveKey = findViewById(R.id.btnSaveKey); | ||
btnSaveKey.setOnClickListener(new View.OnClickListener() { | ||
public void onClick(View v) { | ||
btnSaveKey_onClick(); | ||
} | ||
}); | ||
|
||
SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(getString(R.string.preferences_key), Context.MODE_PRIVATE); | ||
String apiKey = sharedPref.getString(getString(R.string.preferences_key), ""); | ||
final EditText txtKey = findViewById(R.id.txtKey); | ||
txtKey.setText(apiKey); | ||
} | ||
|
||
private void addListeners() { | ||
final Button btnAddSource = findViewById(R.id.btnAddSource); | ||
btnAddSource.setOnClickListener(new View.OnClickListener() { | ||
public void onClick(View v) { | ||
btnAddSource_onClick(); | ||
} | ||
}); | ||
} | ||
|
||
private void btnAddSource_onClick() { | ||
//get endpoint text | ||
final EditText txtEndpoint = findViewById(R.id.txtEndpoint); | ||
String endpoint = txtEndpoint.getText().toString(); | ||
|
||
//add to shared preferences | ||
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.preferences_endpoints), Context.MODE_PRIVATE); | ||
Map<String, ?> prefs = sharedPref.getAll(); | ||
String nextId = "1"; | ||
//get next preference key | ||
if (prefs.size() > 0) { | ||
Set keys = prefs.keySet(); | ||
int lastId = Integer.parseInt(keys.toArray()[keys.size() - 1].toString()); | ||
lastId++; | ||
nextId = Integer.toString(lastId); | ||
} | ||
SharedPreferences.Editor editor = sharedPref.edit(); | ||
editor.putString(nextId, endpoint); | ||
editor.commit(); | ||
//add to list | ||
listItems.add(endpoint); | ||
adapter.notifyDataSetChanged(); | ||
} | ||
|
||
private void btnSaveKey_onClick() { | ||
//get endpoint text | ||
final EditText txtKey = findViewById(R.id.txtKey); | ||
String endpoint = txtKey.getText().toString(); | ||
|
||
//add to shared preferences | ||
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.preferences_key), Context.MODE_PRIVATE); | ||
SharedPreferences.Editor editor = sharedPref.edit(); | ||
editor.putString(getString(R.string.preferences_key), endpoint); | ||
editor.commit(); | ||
} | ||
|
||
@Override | ||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { | ||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | ||
startService(new Intent(this, ServiceTest.class)); | ||
} else { | ||
// permission denied, boo! Disable the | ||
// functionality that depends on this permission. | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.