diff --git a/README.md b/README.md new file mode 100644 index 0000000..14ac111 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# ⚡ Spark Women - A Women Safety Application +## _Feel Safe Everywhere_ + + +Women Safety App is user friendly application built in Android Studio, +it is simple to implement,easy to understand. + +Demo Download App : [Click Here](https://drive.google.com/file/d/1ZWB_HUyxm86T6GtpMhTWbOwuw6i7G4Wp/view?usp=sharing) + +[](https://t.me/vinayak_09) + + + + +## Features + +- Easy to implement +- Easy to understand +- Shake detector +- Siren sound +- Call to registered mobile +- Shake device to send SOS to registered mobile and play siren +- Sends Last Known Location to registered mobile +- Now we can add multiple contacts to send SOS + +#### Prerequisites : +- Android Studio +- Basic knowledge about Firebase Authentication and Realtime database. +## Build and Run Application + +###### SparkWomen A Women Safety Application requires Android Oreo or newer version to run. +Follow this steps to get Working Project! +``` +Clone this repository or download file +Extract zip if downloaded code +Open project in Android Studio +Wait while Android Studio Download gradle or required files +Hit Run Button ! +``` + +------------ + +Full Project demonstration Youtube :
+Link - https://youtu.be/E0WLnlkPDJY + +**Free Software, Hell Yeah!** diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..839b2df --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,48 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.darkness.sparkwomen" + minSdkVersion 24 + targetSdkVersion 31 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'com.google.android.material:material:1.5.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + + implementation 'com.google.android.gms:play-services-maps:18.0.2' + implementation 'com.google.android.gms:play-services-location:19.0.1' + implementation 'com.github.tbouron.shakedetector:library:1.0.0@aar' + + implementation 'com.karumi:dexter:6.2.3' + + +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -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 \ No newline at end of file diff --git a/app/src/androidTest/java/com/darkness/sparkwomen/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/darkness/sparkwomen/ExampleInstrumentedTest.java new file mode 100644 index 0000000..d6b7e2f --- /dev/null +++ b/app/src/androidTest/java/com/darkness/sparkwomen/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.darkness.sparkwomen; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.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 Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.darkness.sparkwomen", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..748e0f8 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/darkness/sparkwomen/ContactActivity.java b/app/src/main/java/com/darkness/sparkwomen/ContactActivity.java new file mode 100644 index 0000000..2fa2a74 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/ContactActivity.java @@ -0,0 +1,190 @@ +package com.darkness.sparkwomen; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.app.Dialog; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Set; + +public class ContactActivity extends AppCompatActivity { + + + EditText contact; + Button addContact; + + RecyclerView recyclerView; + + HashMap contacts; + + ArrayList send; + + ContactsAdapter adapter; + MyOnClickListener onClickListener; + + ImageView edit; + + TextView callerInfo; + + + @Override + public void onBackPressed() { + super.onBackPressed(); + startActivity(new Intent(this,MainActivity.class)); + this.finish(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_contact); + + + + edit = findViewById(R.id.editCallButton); + + + edit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Dialog dialog = new Dialog(ContactActivity.this); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setCancelable(false); + dialog.setContentView(R.layout.dialog); + + Button close,save; + close = dialog.findViewById(R.id.dialogCancel); + save = dialog.findViewById(R.id.dialogSave); + EditText number = dialog.findViewById(R.id.dialogEditText); + + save.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String numberText = number.getText().toString(); + if(numberText.length() == 10){ + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString("firstNumber",numberText); + editor.apply(); + setCallingInformation(); + dialog.dismiss(); + }else { + Toast.makeText(ContactActivity.this, "Enter valid number!", Toast.LENGTH_SHORT).show(); + } + } + }); + + close.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + dialog.dismiss(); + } + }); + + + dialog.show(); + } + }); + + + + + callerInfo = findViewById(R.id.callText); + + + setCallingInformation(); + + + contacts = new HashMap<>(); + send = new ArrayList<>(); + + adapter = new ContactsAdapter(this, send, new MyOnClickListener() { + @Override + public void onItemClicked(int position) { + deleteItemFromDatabase(position); + } + }); + + recyclerView = findViewById(R.id.contacts); + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + + getData(); + + contact = findViewById(R.id.contactGet); + addContact = findViewById(R.id.addContact); + + addContact.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + createContact(contact.getText().toString()); + } + }); + } + + private void createContact(String contactString) { + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + Set oldNumbers = sharedPreferences.getStringSet("enumbers", new LinkedHashSet<>()); + oldNumbers.add(contactString); + editor.remove("enumbers"); + editor.putStringSet("enumbers",oldNumbers); + editor.apply(); + + contact.setText(""); + editor.apply(); + getData(); + + } + + + private void setCallingInformation(){ + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + String firstNumber = sharedPreferences.getString("firstNumber","null"); + + if (firstNumber.isEmpty()||firstNumber.equalsIgnoreCase("null")){ + callerInfo.setText("Please add number."); + }else { + callerInfo.setText(firstNumber); + } + + } + + + + + private void deleteItemFromDatabase(int position) { + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + Set oldNumbers = sharedPreferences.getStringSet("enumbers", new LinkedHashSet<>()); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.remove("enumbers"); + oldNumbers.remove(send.get(position)); + editor.putStringSet("enumbers",oldNumbers); + editor.apply(); + getData(); + } + + + + private void getData() { + send.clear(); + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + Set oldNumbers = sharedPreferences.getStringSet("enumbers", new LinkedHashSet<>()); + send.addAll(oldNumbers); + adapter.notifyDataSetChanged(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkness/sparkwomen/ContactsAdapter.java b/app/src/main/java/com/darkness/sparkwomen/ContactsAdapter.java new file mode 100644 index 0000000..77b89ff --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/ContactsAdapter.java @@ -0,0 +1,58 @@ +package com.darkness.sparkwomen; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.HashMap; + +public class ContactsAdapter extends RecyclerView.Adapter { + + HashMap contacts; + Context context; + ArrayList send; + MyOnClickListener myOnClickListener; + + ContactsAdapter(Context context, ArrayList send,MyOnClickListener myOnClickListener){ + this.send = send; + this.context = context; + this.myOnClickListener = myOnClickListener; + } + + @NonNull + @Override + public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.contact_item,parent,false)); + } + + @Override + public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { + holder.contact.setText(send.get(position)); + holder.delete.setOnClickListener(view -> myOnClickListener.onItemClicked(position)); + } + + @Override + public int getItemCount() { + return send.size(); + } + + class MyViewHolder extends RecyclerView.ViewHolder{ + + TextView name,contact; + ImageView delete; + + public MyViewHolder(@NonNull View itemView) { + super(itemView); + contact = itemView.findViewById(R.id.contactItem); + delete = itemView.findViewById(R.id.deleteIcon); + } + } + +} diff --git a/app/src/main/java/com/darkness/sparkwomen/LawDisplayerActivity.java b/app/src/main/java/com/darkness/sparkwomen/LawDisplayerActivity.java new file mode 100644 index 0000000..3519954 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/LawDisplayerActivity.java @@ -0,0 +1,64 @@ +package com.darkness.sparkwomen; + +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +public class LawDisplayerActivity extends AppCompatActivity implements View.OnClickListener { + + TextView big,oneLine; + String[] laws, lawsContent; + int counter; + Button back, next; + View closeBtn; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_law_displayer); + + big = findViewById(R.id.bigLaws); + oneLine = findViewById(R.id.lawString); + counter = getIntent().getIntExtra("position",0); + laws = new String[]{"The Prohibition of Child Marriage Act, 2006","Special Marriage Act, 1954","Dowry Prohibition Act, 1961","Indian Divorce Act, 1969","Maternity Benefit Act,1861","Medical Termination of Pregnancy Act,1971","Sexual Harassment of Women at Workplace (Prevention, Prohibition and Redress) Act, 2013","Indecent Representation of Women(Prevention) Act,1986","National Commission for Women Act, 1990","Equal Remuneration Act, 1976"}; + lawsContent = this.getResources().getStringArray(R.array.lawsBig); + + closeBtn = findViewById(R.id.closeBtn); + closeBtn.setOnClickListener(view -> { + onBackPressed(); + LawDisplayerActivity.this.finish(); + }); + + back = findViewById(R.id.backBtn); + next = findViewById(R.id.nextBtn); + next.setOnClickListener(this); + back.setOnClickListener(this); + setData(); + } + + public void setData(){ + oneLine.setText(laws[counter]); + big.setText(lawsContent[counter]); + } + + @Override + public void onClick(View view) { + if(view.getId() == R.id.nextBtn){ + if(counter<9){ + counter++; + }else { + counter = 0; + } + } else if (view.getId() == R.id.backBtn) { + if(counter == 0){ + counter = (laws.length-1); + }else { + counter--; + } + } + + setData(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkness/sparkwomen/LawModel.java b/app/src/main/java/com/darkness/sparkwomen/LawModel.java new file mode 100644 index 0000000..8ec8771 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/LawModel.java @@ -0,0 +1,29 @@ +package com.darkness.sparkwomen; + +public class LawModel { + String lawString, lawDescription; + + public LawModel(String lawString, String lawDescription) { + this.lawString = lawString; + this.lawDescription = lawDescription; + } + + public LawModel() { + } + + public String getLawString() { + return lawString; + } + + public void setLawString(String lawString) { + this.lawString = lawString; + } + + public String getLawDescription() { + return lawDescription; + } + + public void setLawDescription(String lawDescription) { + this.lawDescription = lawDescription; + } +} diff --git a/app/src/main/java/com/darkness/sparkwomen/LawsActivity.java b/app/src/main/java/com/darkness/sparkwomen/LawsActivity.java new file mode 100644 index 0000000..1f5c247 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/LawsActivity.java @@ -0,0 +1,42 @@ +package com.darkness.sparkwomen; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.content.Intent; +import android.os.Bundle; + +public class LawsActivity extends AppCompatActivity { + + @Override + public void onBackPressed() { + super.onBackPressed(); + startActivity(new Intent(LawsActivity.this,MainActivity.class)); + LawsActivity.this.finish(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_laws); + RecyclerView recyclerView = findViewById(R.id.recycleLaws); + String[] laws = new String[]{"The Prohibition of Child Marriage Act, 2006","Special Marriage Act, 1954","Dowry Prohibition Act, 1961","Indian Divorce Act, 1969","Maternity Benefit Act,1861","Medical Termination of Pregnancy Act,1971","Sexual Harassment of Women at Workplace (Prevention, Prohibition and Redress) Act, 2013","Indecent Representation of Women(Prevention) Act,1986","National Commission for Women Act, 1990","Equal Remuneration Act, 1976"}; + + MyAdapter adapter = new MyAdapter(this, laws, position -> { + Intent intent = new Intent(LawsActivity.this,LawDisplayerActivity.class); + intent.putExtra("position",position); + startActivity(intent); + }); + + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + + + + findViewById(R.id.backBtn).setOnClickListener(view -> { + startActivity(new Intent(LawsActivity.this,MainActivity.class)); + LawsActivity.this.finish(); + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkness/sparkwomen/MainActivity.java b/app/src/main/java/com/darkness/sparkwomen/MainActivity.java new file mode 100644 index 0000000..ea4dae0 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/MainActivity.java @@ -0,0 +1,89 @@ +package com.darkness.sparkwomen; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; + +import android.Manifest; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import android.telephony.SmsManager; +import android.view.View; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationServices; + +import java.util.HashSet; +import java.util.Set; + +public class MainActivity extends AppCompatActivity implements View.OnClickListener { + + FusedLocationProviderClient fusedLocationClient; + String myLocation = "", numberCall; + SmsManager manager = SmsManager.getDefault(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); + findViewById(R.id.panicBtn).setOnClickListener(this); + findViewById(R.id.fourth).setOnClickListener(this); + findViewById(R.id.first).setOnClickListener(this); + findViewById(R.id.second).setOnClickListener(this); + findViewById(R.id.fifth).setOnClickListener(this); + } + + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.fourth) { + startActivity(new Intent(MainActivity.this, LawsActivity.class)); + MainActivity.this.finish(); + }else if(id == R.id.first){ + startActivity(new Intent(MainActivity.this, ContactActivity.class)); + MainActivity.this.finish(); + }else if(id == R.id.fifth){ + startActivity(new Intent(MainActivity.this, SelfDefenseActivity.class)); + } else if(id == R.id.second){ + startActivity(new Intent(MainActivity.this, SmsActivity.class)); + MainActivity.this.finish(); + } else if (id == R.id.panicBtn) { + + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + return; + } + fusedLocationClient.getLastLocation() + .addOnSuccessListener(location -> { + if (location != null) { + location.getAltitude(); + location.getLongitude(); + myLocation = "http://maps.google.com/maps?q=loc:"+location.getLatitude()+","+location.getLongitude(); + }else { + myLocation = "Unable to Find Location :("; + } + sendMsg(); + }); + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + numberCall = sharedPreferences.getString("firstNumber","None"); + if(!numberCall.equalsIgnoreCase("None")){ + Intent intent = new Intent(Intent.ACTION_CALL); + intent.setData(Uri.parse("tel:"+numberCall)); + startActivity(intent); + } + + } + + + } + void sendMsg(){ + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + Set oldNumbers = sharedPreferences.getStringSet("enumbers", new HashSet<>()); + if(!oldNumbers.isEmpty()){ + for(String ENUM : oldNumbers) + manager.sendTextMessage(ENUM,null,"Im in Trouble!\nSending My Location :\n"+myLocation,null,null); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkness/sparkwomen/MyAdapter.java b/app/src/main/java/com/darkness/sparkwomen/MyAdapter.java new file mode 100644 index 0000000..a9ad794 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/MyAdapter.java @@ -0,0 +1,55 @@ +package com.darkness.sparkwomen; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +public class MyAdapter extends RecyclerView.Adapter{ + + + String[] laws; + Context context; + MyOnClickListener myOnClickListener; + + public MyAdapter(Context context, String[] laws,MyOnClickListener onClickListener){ + this.laws = laws; + this.context = context; + this.myOnClickListener = onClickListener; + } + + @NonNull + @Override + public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.law_item,parent,false)); + } + + @Override + public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { + int newPosition = position + 1; + String displayString = newPosition + " " + laws[position]; + holder.law.setText(displayString); + holder.law.setOnClickListener(view -> myOnClickListener.onItemClicked(position)); + } + + @Override + public int getItemCount() { + return laws.length; + } + + static class MyViewHolder extends RecyclerView.ViewHolder{ + + TextView law; + + public MyViewHolder(@NonNull View itemView) { + super(itemView); + law = itemView.findViewById(R.id.lawItem); + + } + } + +} diff --git a/app/src/main/java/com/darkness/sparkwomen/MyOnClickListener.java b/app/src/main/java/com/darkness/sparkwomen/MyOnClickListener.java new file mode 100644 index 0000000..8681349 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/MyOnClickListener.java @@ -0,0 +1,5 @@ +package com.darkness.sparkwomen; + +public interface MyOnClickListener { + void onItemClicked(int position); +} diff --git a/app/src/main/java/com/darkness/sparkwomen/SelfDefenseActivity.java b/app/src/main/java/com/darkness/sparkwomen/SelfDefenseActivity.java new file mode 100644 index 0000000..f38c0bc --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/SelfDefenseActivity.java @@ -0,0 +1,27 @@ +package com.darkness.sparkwomen; + +import android.os.Bundle; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +import androidx.appcompat.app.AppCompatActivity; + +public class SelfDefenseActivity extends AppCompatActivity { + + WebView webView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_self_defense); + + webView = findViewById(R.id.webView); + + webView.setWebChromeClient(new WebChromeClient()); + webView.getSettings().setLoadsImagesAutomatically(true); + webView.getSettings().setJavaScriptEnabled(true); + webView.loadUrl("https://www.youtube.com/embed/T7aNSRoDCmg"); + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/darkness/sparkwomen/ServiceMine.java b/app/src/main/java/com/darkness/sparkwomen/ServiceMine.java new file mode 100644 index 0000000..4c85713 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/ServiceMine.java @@ -0,0 +1,185 @@ + +package com.darkness.sparkwomen; + +import android.Manifest; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.location.Location; +import android.media.MediaPlayer; +import android.os.Build; +import android.os.IBinder; +import android.telephony.SmsManager; +import android.view.View; + +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; + +import com.github.tbouron.shakedetector.library.ShakeDetector; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationServices; +import com.google.android.gms.tasks.OnSuccessListener; + +import java.util.HashSet; +import java.util.Set; + +public class ServiceMine extends Service { + + static boolean isRunning = false; + + static MediaPlayer mediaPlayer; + + FusedLocationProviderClient fusedLocationClient; + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + SmsManager manager = SmsManager.getDefault(); +// WindowManager windowManager; + String myLocation; + View view; + @Override + public void onCreate() { + + super.onCreate(); + + mediaPlayer = MediaPlayer.create(getBaseContext(),R.raw.siren); + mediaPlayer.setLooping(true); + + + + fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + return; + } + fusedLocationClient.getLastLocation() + .addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Location location) { + if (location != null) { + // Logic to handle location object + location.getAltitude(); + location.getLongitude(); + myLocation = "http://maps.google.com/maps?q=loc:"+location.getLatitude()+","+location.getLongitude(); + }else { + myLocation = "Unable to Find Location :("; + } + } + }); + + + +// windowManager= (WindowManager) getSystemService(WINDOW_SERVICE); +// +// WindowManager.LayoutParams params= null; +// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { +// params = new WindowManager.LayoutParams( +// WindowManager.LayoutParams.WRAP_CONTENT, +// WindowManager.LayoutParams.WRAP_CONTENT, +// WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, +// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, +// PixelFormat.TRANSLUCENT); +// } +// +// params.gravity = Gravity.START; +// params.x = 0; +// params.y = 100; +// +// LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); +// view = inflater.inflate(R.layout.floating_menu, null); +// Button panic = view.findViewById(R.id.panicService); +// panic.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// mediaPlayer.start(); +// +// +// SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); +// Set oldNumbers = sharedPreferences.getStringSet("enumbers", new HashSet<>()); +// if(!oldNumbers.isEmpty()){ +// for(String ENUM : oldNumbers) +// manager.sendTextMessage(ENUM,null,"Im in Trouble!\nSending My Location :\n"+myLocation,null,null); +// } +// +// } +// }); +// +// windowManager.addView(view,params); + + + + ShakeDetector.create(this, () -> { + + mediaPlayer.start(); + + + SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref",MODE_PRIVATE); + Set oldNumbers = sharedPreferences.getStringSet("enumbers", new HashSet<>()); + if(!oldNumbers.isEmpty()){ + for(String ENUM : oldNumbers) + manager.sendTextMessage(ENUM,null,"Im in Trouble!\nSending My Location :\n"+myLocation,null,null); + } + + }); + + } + + + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + + if (intent.getAction().equalsIgnoreCase("STOP")) { + if(isRunning){ + mediaPlayer.stop(); + this.stopForeground(true); + this.stopSelf(); +// windowManager.removeView(view); + isRunning = false; + } + } else { + Intent notificationIntent = new Intent(this, SmsActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel("MYID", "CHANNELFOREGROUND", NotificationManager.IMPORTANCE_DEFAULT); + + NotificationManager m = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + m.createNotificationChannel(channel); + + Notification notification = new Notification.Builder(this, "MYID") + .setContentTitle("Women Safety") + .setContentText("Shake Device to Send SOS") + .setSmallIcon(R.drawable.girlpower) + .setContentIntent(pendingIntent) + .build(); + this.startForeground(115, notification); + isRunning = true; + return START_NOT_STICKY; + } + if (intent.getAction().equalsIgnoreCase("PLAY")) { + mediaPlayer.start(); + } + } + + return super.onStartCommand(intent,flags,startId); + + + } + + @Override + public void onDestroy() { + mediaPlayer.stop(); + mediaPlayer.release(); + super.onDestroy(); + } +} diff --git a/app/src/main/java/com/darkness/sparkwomen/SmsActivity.java b/app/src/main/java/com/darkness/sparkwomen/SmsActivity.java new file mode 100644 index 0000000..d9d1f09 --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/SmsActivity.java @@ -0,0 +1,87 @@ +package com.darkness.sparkwomen; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.provider.Settings; +import android.view.View; +import android.widget.Button; + +import com.google.android.material.snackbar.Snackbar; + +public class SmsActivity extends AppCompatActivity { + + + + Button start,stop; + + + @Override + public void onBackPressed() { + super.onBackPressed(); + startActivity(new Intent(SmsActivity.this,MainActivity.class)); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sms); + stop = findViewById(R.id.stopService); + start = findViewById(R.id.startService); + + start.setOnClickListener(this::startServiceV); + + stop.setOnClickListener(this::stopService); + + } + + + public void stopService(View view) { + + Intent notificationIntent = new Intent(this,ServiceMine.class); + notificationIntent.setAction("stop"); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if(ServiceMine.isRunning){ + getApplicationContext().startForegroundService(notificationIntent); + Snackbar.make(findViewById(android.R.id.content),"Service Stopped!", Snackbar.LENGTH_LONG).show(); + } + }else { + if(ServiceMine.isRunning){ +// getApplicationContext().startService(notificationIntent); + getApplicationContext().startService(notificationIntent); + Snackbar.make(findViewById(android.R.id.content),"Service Stopped!", Snackbar.LENGTH_LONG).show(); + } + } + } + + public void startServiceV(View view) { + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (!Settings.canDrawOverlays(this)) { + Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, + Uri.parse("package:" + getPackageName())); + startActivity(intent); + } + } + + if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) { + Intent notificationIntent = new Intent(this,ServiceMine.class); + notificationIntent.setAction("Start"); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + getApplicationContext().startForegroundService(notificationIntent); + Snackbar.make(findViewById(android.R.id.content),"Service Started!", Snackbar.LENGTH_LONG).show(); + }else { + getApplicationContext().startService(notificationIntent); + Snackbar.make(findViewById(android.R.id.content),"Service Started!", Snackbar.LENGTH_LONG).show(); + } + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/darkness/sparkwomen/SplashActivity.java b/app/src/main/java/com/darkness/sparkwomen/SplashActivity.java new file mode 100644 index 0000000..abb7f1a --- /dev/null +++ b/app/src/main/java/com/darkness/sparkwomen/SplashActivity.java @@ -0,0 +1,96 @@ +package com.darkness.sparkwomen; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Location; +import android.os.Bundle; +import android.widget.Toast; + +import com.google.android.gms.location.LocationCallback; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationResult; +import com.google.android.gms.location.LocationServices; +import com.karumi.dexter.Dexter; +import com.karumi.dexter.MultiplePermissionsReport; +import com.karumi.dexter.PermissionToken; +import com.karumi.dexter.listener.PermissionRequest; +import com.karumi.dexter.listener.multi.MultiplePermissionsListener; + +import java.util.List; + +public class SplashActivity extends AppCompatActivity { + + boolean isAllPermissionsGranted = false; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_splash); + requestPermission(); + findViewById(R.id.btnGetStarted).setOnClickListener(view -> { + if(isAllPermissionsGranted){ + startActivity(new Intent(SplashActivity.this,MainActivity.class)); + SplashActivity.this.finish(); + }else { + Toast.makeText(this, "Please grant required permissions!", Toast.LENGTH_SHORT).show(); + requestPermission(); + } + }); + } + + + + + private void requestPermission() { + Dexter.withContext(this) + .withPermissions( + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.CALL_PHONE, + Manifest.permission.SEND_SMS + ).withListener(new MultiplePermissionsListener() { + @Override public void onPermissionsChecked(MultiplePermissionsReport report) { + if(report.areAllPermissionsGranted()){ + isAllPermissionsGranted = true; + requestLocation(); + } + } + @Override public void onPermissionRationaleShouldBeShown(List permissions, PermissionToken token) { + token.continuePermissionRequest(); + } + }).check(); + } + + + + + void requestLocation(){ + LocationRequest mLocationRequest = com.google.android.gms.location.LocationRequest.create(); + mLocationRequest.setInterval(60000); + mLocationRequest.setFastestInterval(5000); + mLocationRequest.setPriority(com.google.android.gms.location.LocationRequest.PRIORITY_HIGH_ACCURACY); + LocationCallback mLocationCallback = new LocationCallback() { + @Override + public void onLocationResult(LocationResult locationResult) { + if (locationResult == null) { + return; + } + for (Location location : locationResult.getLocations()) { + if (location != null) { + //TODO: UI updates. + } + } + } + }; + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + return; + } + LocationServices.getFusedLocationProviderClient(SplashActivity.this).requestLocationUpdates(mLocationRequest, mLocationCallback, null); + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/law_image.xml b/app/src/main/res/drawable-v24/law_image.xml new file mode 100644 index 0000000..43ec7f7 --- /dev/null +++ b/app/src/main/res/drawable-v24/law_image.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/contact.xml b/app/src/main/res/drawable/contact.xml new file mode 100644 index 0000000..96393e8 --- /dev/null +++ b/app/src/main/res/drawable/contact.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/girl.jpg b/app/src/main/res/drawable/girl.jpg new file mode 100644 index 0000000..10957c6 Binary files /dev/null and b/app/src/main/res/drawable/girl.jpg differ diff --git a/app/src/main/res/drawable/girlpower.png b/app/src/main/res/drawable/girlpower.png new file mode 100644 index 0000000..7435b19 Binary files /dev/null and b/app/src/main/res/drawable/girlpower.png differ diff --git a/app/src/main/res/drawable/ic_baseline_account_circle_24.xml b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml new file mode 100644 index 0000000..873b40c --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_close_24.xml b/app/src/main/res/drawable/ic_baseline_close_24.xml new file mode 100644 index 0000000..4223ae5 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_close_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_delete_24.xml b/app/src/main/res/drawable/ic_baseline_delete_24.xml new file mode 100644 index 0000000..91d0651 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_delete_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_edit_24.xml b/app/src/main/res/drawable/ic_baseline_edit_24.xml new file mode 100644 index 0000000..12388c1 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_edit_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_logout_24.xml b/app/src/main/res/drawable/ic_baseline_logout_24.xml new file mode 100644 index 0000000..17f6ac0 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_logout_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_message_24.xml b/app/src/main/res/drawable/ic_baseline_message_24.xml new file mode 100644 index 0000000..9e8a1ce --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_message_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/laws.png b/app/src/main/res/drawable/laws.png new file mode 100644 index 0000000..bd2764d Binary files /dev/null and b/app/src/main/res/drawable/laws.png differ diff --git a/app/src/main/res/drawable/oval_purple_full.xml b/app/src/main/res/drawable/oval_purple_full.xml new file mode 100644 index 0000000..e602c20 --- /dev/null +++ b/app/src/main/res/drawable/oval_purple_full.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/purple_background.xml b/app/src/main/res/drawable/purple_background.xml new file mode 100644 index 0000000..5ce947f --- /dev/null +++ b/app/src/main/res/drawable/purple_background.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rectangle_border.xml b/app/src/main/res/drawable/rectangle_border.xml new file mode 100644 index 0000000..9057a66 --- /dev/null +++ b/app/src/main/res/drawable/rectangle_border.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/self_defence.xml b/app/src/main/res/drawable/self_defence.xml new file mode 100644 index 0000000..2b12445 --- /dev/null +++ b/app/src/main/res/drawable/self_defence.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/drawable/settings.xml b/app/src/main/res/drawable/settings.xml new file mode 100644 index 0000000..89b4a0f --- /dev/null +++ b/app/src/main/res/drawable/settings.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/sitting_girl.png b/app/src/main/res/drawable/sitting_girl.png new file mode 100644 index 0000000..dac74ce Binary files /dev/null and b/app/src/main/res/drawable/sitting_girl.png differ diff --git a/app/src/main/res/drawable/top_left_corner_oval.xml b/app/src/main/res/drawable/top_left_corner_oval.xml new file mode 100644 index 0000000..01f4a5c --- /dev/null +++ b/app/src/main/res/drawable/top_left_corner_oval.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_contact.xml b/app/src/main/res/layout/activity_contact.xml new file mode 100644 index 0000000..1e39817 --- /dev/null +++ b/app/src/main/res/layout/activity_contact.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +