initial version
authorChristian Weiske <[email protected]>
Tue, 22 Mar 2016 22:36:13 +0000 (23:36 +0100)
committerChristian Weiske <[email protected]>
Tue, 22 Mar 2016 22:36:13 +0000 (23:36 +0100)
22 files changed:
.gitignore [new file with mode: 0644]
.idea/.name [new file with mode: 0644]
.idea/compiler.xml [new file with mode: 0644]
.idea/copyright/profiles_settings.xml [new file with mode: 0644]
.idea/gradle.xml [new file with mode: 0644]
.idea/misc.xml [new file with mode: 0644]
.idea/modules.xml [new file with mode: 0644]
.idea/runConfigurations.xml [new file with mode: 0644]
.idea/vcs.xml [new file with mode: 0644]
AndroidManifest.xml [new file with mode: 0644]
build.gradle [new file with mode: 0644]
headphones.svg [new file with mode: 0644]
headphones_w.svg [new file with mode: 0644]
res/drawable/headphones.png [new file with mode: 0644]
res/drawable/headphones_w.png [new file with mode: 0644]
res/layout/activity_main.xml [new file with mode: 0644]
res/values/strings.xml [new file with mode: 0644]
settings.gradle [new file with mode: 0644]
src/de/cweiske/headphoneindicator/Autostart.java [new file with mode: 0644]
src/de/cweiske/headphoneindicator/BackgroundService.java [new file with mode: 0644]
src/de/cweiske/headphoneindicator/MainActivity.java [new file with mode: 0644]
src/de/cweiske/headphoneindicator/NotificationReceiver.java [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..2ae6c0c
--- /dev/null
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+/gen
diff --git a/.idea/.name b/.idea/.name
new file mode 100644 (file)
index 0000000..bdc75f7
--- /dev/null
@@ -0,0 +1 @@
+HeadphoneIndicator
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644 (file)
index 0000000..96cc43e
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <resourceExtensions />
+    <wildcardResourcePatterns>
+      <entry name="!?*.java" />
+      <entry name="!?*.form" />
+      <entry name="!?*.class" />
+      <entry name="!?*.groovy" />
+      <entry name="!?*.scala" />
+      <entry name="!?*.flex" />
+      <entry name="!?*.kt" />
+      <entry name="!?*.clj" />
+      <entry name="!?*.aj" />
+    </wildcardResourcePatterns>
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="false">
+        <processorPath useClasspath="true" />
+      </profile>
+    </annotationProcessing>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644 (file)
index 0000000..e7bedf3
--- /dev/null
@@ -0,0 +1,3 @@
+<component name="CopyrightManager">
+  <settings default="" />
+</component>
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644 (file)
index 0000000..288ea0b
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="LOCAL" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.8" />
+        <option name="gradleJvm" value="1.7" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+          </set>
+        </option>
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644 (file)
index 0000000..1a3eaff
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="EntryPointsManager">
+    <entry_points version="2.0" />
+  </component>
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+    <OptionsSetting value="true" id="Add" />
+    <OptionsSetting value="true" id="Remove" />
+    <OptionsSetting value="true" id="Checkout" />
+    <OptionsSetting value="true" id="Update" />
+    <OptionsSetting value="true" id="Status" />
+    <OptionsSetting value="true" id="Edit" />
+    <ConfirmationsSetting value="0" id="Add" />
+    <ConfirmationsSetting value="0" id="Remove" />
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644 (file)
index 0000000..0837d2f
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/headphoneindicator.iml" filepath="$PROJECT_DIR$/headphoneindicator.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644 (file)
index 0000000..7f68460
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644 (file)
index 0000000..6564d52
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..278e85a
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="de.cweiske.headphoneindicator">
+
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/headphones_w"
+        android:label="@string/app_name"
+        android:supportsRtl="true">
+
+        <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=".BackgroundService"/>
+
+        <!-- auto-start after boot -->
+        <receiver android:name=".Autostart" >
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+    </application>
+
+</manifest>
diff --git a/build.gradle b/build.gradle
new file mode 100644 (file)
index 0000000..27796ac
--- /dev/null
@@ -0,0 +1,43 @@
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:1.5.0'
+    }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 19
+    buildToolsVersion "23.0.2"
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest.xml'
+            java.srcDirs = ['src']
+            resources.srcDirs = ['src']
+            aidl.srcDirs = ['src']
+            renderscript.srcDirs = ['src']
+            res.srcDirs = ['res']
+            assets.srcDirs = ['res']
+        }
+    }
+    defaultConfig {
+        applicationId "de.cweiske.headphoneindicator"
+        minSdkVersion 19
+        targetSdkVersion 19
+        versionCode 1
+        versionName "1.0"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+        }
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/headphones.svg b/headphones.svg
new file mode 100644 (file)
index 0000000..b6366e4
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!-- Creator: CorelDRAW X5 -->
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:ns1="http://sozi.baierouge.fr"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:cc="http://web.resource.org/cc/"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xml:space="preserve"
+    style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
+    viewBox="0 0 7493 5700"
+  >
+ <defs
+    >
+  <style
+        type="text/css"
+      >
+   
+    .fil0 {fill:black}
+   
+  </style
+    >
+ </defs
+  >
+ <g
+      id="Layer_x0020_1"
+    >
+  <metadata
+        id="CorelCorpID_0Corel-Layer"
+    />
+  <path
+        class="fil0"
+        d="M1522 3175c77,15 152,37 224,66l0 2369c-146,58 -305,90 -471,90 -704,0 -1275,-571 -1275,-1275 0,-620 442,-1136 1028,-1251 0,-10 0,-18 0,-24 0,-861 300,-1644 784,-2213 493,-580 1177,-938 1935,-938 758,0 1441,359 1935,938 484,569 784,1351 784,2213 0,6 0,14 0,24 586,115 1028,631 1028,1251 0,704 -571,1275 -1275,1275 -166,0 -325,-32 -471,-90l0 -2369c72,-29 147,-51 224,-66l0 -24c0,-743 -254,-1412 -664,-1894 -401,-471 -953,-763 -1560,-763 -608,0 -1159,291 -1560,763 -410,482 -664,1151 -664,1894l0 24z"
+    />
+ </g
+  >
+<metadata
+    ><rdf:RDF
+      ><cc:Work
+        ><dc:format
+          >image/svg+xml</dc:format
+        ><dc:type
+            rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+        /><cc:license
+            rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+        /><dc:publisher
+          ><cc:Agent
+              rdf:about="http://openclipart.org/"
+            ><dc:title
+              >Openclipart</dc:title
+            ></cc:Agent
+          ></dc:publisher
+        ></cc:Work
+      ><cc:License
+          rdf:about="http://creativecommons.org/licenses/publicdomain/"
+        ><cc:permits
+            rdf:resource="http://creativecommons.org/ns#Reproduction"
+        /><cc:permits
+            rdf:resource="http://creativecommons.org/ns#Distribution"
+        /><cc:permits
+            rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+        /></cc:License
+      ></rdf:RDF
+    ></metadata
+  ></svg
+>
diff --git a/headphones_w.svg b/headphones_w.svg
new file mode 100644 (file)
index 0000000..4cd58cf
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: CorelDRAW X5 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xml:space="preserve"
+   style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
+   viewBox="0 0 7493 5700"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"
+   sodipodi:docname="headphones.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1440"
+     inkscape:window-height="826"
+     id="namedview14"
+     showgrid="false"
+     inkscape:zoom="0.041403509"
+     inkscape:cx="3794.8051"
+     inkscape:cy="2850"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" /><defs
+     id="defs4"><style
+       type="text/css"
+       id="style6">
+   
+    .fil0 {fill:black}
+   
+  </style></defs><g
+     id="Layer_x0020_1"
+     style="fill:#ffffff"><metadata
+       id="CorelCorpID_0Corel-Layer" /><path
+       class="fil0"
+       d="M1522 3175c77,15 152,37 224,66l0 2369c-146,58 -305,90 -471,90 -704,0 -1275,-571 -1275,-1275 0,-620 442,-1136 1028,-1251 0,-10 0,-18 0,-24 0,-861 300,-1644 784,-2213 493,-580 1177,-938 1935,-938 758,0 1441,359 1935,938 484,569 784,1351 784,2213 0,6 0,14 0,24 586,115 1028,631 1028,1251 0,704 -571,1275 -1275,1275 -166,0 -325,-32 -471,-90l0 -2369c72,-29 147,-51 224,-66l0 -24c0,-743 -254,-1412 -664,-1894 -401,-471 -953,-763 -1560,-763 -608,0 -1159,291 -1560,763 -410,482 -664,1151 -664,1894l0 24z"
+       id="path10"
+       style="fill:#ffffff" /></g><metadata
+     id="metadata12"><rdf:RDF><cc:Work><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" /><dc:publisher><cc:Agent
+             rdf:about="http://openclipart.org/"><dc:title>Openclipart</dc:title></cc:Agent></dc:publisher><dc:title></dc:title></cc:Work><cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/"><cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata></svg>
\ No newline at end of file
diff --git a/res/drawable/headphones.png b/res/drawable/headphones.png
new file mode 100644 (file)
index 0000000..b755b18
Binary files /dev/null and b/res/drawable/headphones.png differ
diff --git a/res/drawable/headphones_w.png b/res/drawable/headphones_w.png
new file mode 100644 (file)
index 0000000..d313c96
Binary files /dev/null and b/res/drawable/headphones_w.png differ
diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml
new file mode 100644 (file)
index 0000000..6677691
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="16dp"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"
+    android:paddingTop="16dp"
+    tools:context="de.cweiske.headphoneindicator.MainActivity"
+    android:theme="@android:style/Theme">
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/image"
+        android:layout_centerVertical="true"
+        android:layout_centerHorizontal="true" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:text="@string/unplugged"
+        android:id="@+id/label"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true" />
+</RelativeLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644 (file)
index 0000000..a5ea8fe
--- /dev/null
@@ -0,0 +1,5 @@
+<resources>
+    <string name="app_name">Headphone indicator</string>
+    <string name="plugged">Headphones are plugged in</string>
+    <string name="unplugged">Headphones are NOT plugged in</string>
+</resources>
diff --git a/settings.gradle b/settings.gradle
new file mode 100644 (file)
index 0000000..fddff8a
--- /dev/null
@@ -0,0 +1 @@
+include ':'
diff --git a/src/de/cweiske/headphoneindicator/Autostart.java b/src/de/cweiske/headphoneindicator/Autostart.java
new file mode 100644 (file)
index 0000000..200112d
--- /dev/null
@@ -0,0 +1,18 @@
+package de.cweiske.headphoneindicator;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Called when the phone finishes booting.
+ *
+ * @author Christian Weiske, [email protected]
+ */
+public class Autostart extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        context.startService(new Intent(context, BackgroundService.class));
+    }
+}
diff --git a/src/de/cweiske/headphoneindicator/BackgroundService.java b/src/de/cweiske/headphoneindicator/BackgroundService.java
new file mode 100644 (file)
index 0000000..43e8972
--- /dev/null
@@ -0,0 +1,39 @@
+package de.cweiske.headphoneindicator;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.IBinder;
+
+/**
+ * Permanent service that runs even when the app itself is stopped
+ *
+ * @author Christian Weiske, [email protected]
+ */
+public class BackgroundService extends Service
+{
+    protected NotificationReceiver notificationReceiver;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
+        this.notificationReceiver = new NotificationReceiver();
+        registerReceiver(this.notificationReceiver, filter);
+    }
+
+    @Override
+    public void onDestroy() {
+        unregisterReceiver(this.notificationReceiver);
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        return START_STICKY;
+    }
+}
diff --git a/src/de/cweiske/headphoneindicator/MainActivity.java b/src/de/cweiske/headphoneindicator/MainActivity.java
new file mode 100644 (file)
index 0000000..b92d3ef
--- /dev/null
@@ -0,0 +1,65 @@
+package de.cweiske.headphoneindicator;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * Shows headphone icon and text, and starts the background service
+ *
+ * @author Christian Weiske, [email protected]
+ */
+public class MainActivity extends Activity {
+    BroadcastReceiver headsetPlugReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Bundle extras = intent.getExtras();
+            if (extras == null) {
+                return;
+            }
+            if (extras.getInt("state") == 1) {
+                setPlugged(true);
+            } else {
+                setPlugged(false);
+            }
+        }
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        startService(new Intent(this, BackgroundService.class));
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
+        registerReceiver(this.headsetPlugReceiver, filter);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        this.unregisterReceiver(this.headsetPlugReceiver);
+    }
+
+    public void setPlugged(boolean plugged)
+    {
+        ImageView view = (ImageView) findViewById(R.id.image);
+        TextView label = (TextView) findViewById(R.id.label);
+        if (plugged) {
+            view.setImageResource(R.drawable.headphones_w);
+            label.setText(R.string.plugged);
+        } else {
+            view.setImageResource(0);
+            label.setText(R.string.unplugged);
+        }
+    }
+}
diff --git a/src/de/cweiske/headphoneindicator/NotificationReceiver.java b/src/de/cweiske/headphoneindicator/NotificationReceiver.java
new file mode 100644 (file)
index 0000000..ff0d4a8
--- /dev/null
@@ -0,0 +1,41 @@
+package de.cweiske.headphoneindicator;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Shows and hides the status bar notification.
+ *
+ * @author Christian Weiske, [email protected]
+ */
+public class NotificationReceiver extends BroadcastReceiver {
+    static int NOT_ID = 1;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Bundle extras = intent.getExtras();
+        if (extras == null) {
+            return;
+        }
+
+        NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        if (extras.getInt("state") == 1) {
+            //plugged
+            nm.notify(
+                NOT_ID,
+                new Notification.Builder(context)
+                    .setSmallIcon(R.drawable.headphones_w)
+                    .setContentTitle(context.getResources().getString(R.string.plugged))
+                    .setContentText("")
+                    .build()
+            );
+        } else {
+            //unplugged
+            nm.cancel(NOT_ID);
+        }
+    }
+}