2

Ich entwickle eine Anwendung, die Headset-Taste Einzel- und Doppelklick erkennen (Code unten). Einfacher und doppelter Klick funktioniert gut, aber langer Klick funktioniert nicht. Der folgende Code befindet sich in einer Klasse, die BroadcastReceiver erweitert. Wie kann ich dieses Problem lösen? Vielen Dank.Android - So erkennen Aktion Media Taste lange drücken

@Override 
public void onReceive(Context context, Intent intent) 
{ 
    context1=context; 
    intent1=intent; 
    String intentAction=intent.getAction(); 
    if (!Intent.ACTION_MEDIA_BUTTON.equalsIgnoreCase(intentAction)) 
    { 
     return; 
    } 
    KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); 
    if (event == null) { 
     return; 
    } 
    int action = event.getAction(); 
    if (action == KeyEvent.ACTION_DOWN) 
    { 
     // do something 

      d++; 
      Handler handler = new Handler(); 
      Runnable r = new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        // single click ******************************* 
        if (d == 1) 
        { 
         Toast.makeText(context1, "single click!", Toast.LENGTH_SHORT).show(); 
        } 
        // double click ********************************* 
        if (d == 2) 
        { 
         Toast.makeText(context1, "Double click!!", Toast.LENGTH_SHORT).show(); 
        } 
        d = 0; 
       } 
      }; 
      if (d == 1) 
      { 

       handler.postDelayed(r, 500); 
      } 
    } 
    /** 
    * for long click 
    */ 
    if (action == KeyEvent.ACTION_UP) 
    { 
     if (SystemClock.uptimeMillis() - event.getDownTime() > 2000) 
     { 
      Toast.makeText(context, "Long click!", Toast.LENGTH_SHORT).show(); 
     } 
    } 
    abortBroadcast(); 
} 

UPDATE

Dies ist Main.class

public class Main extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener 
{ 
private static final String TAG = "MainActivity"; 
PreferenceFragment pf; 
@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.layout_main); 

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    FragmentManager fragmentManager= getFragmentManager(); 
    SingoloClick singoloClick= new SingoloClick(); 
    FragmentTransaction ft=fragmentManager.beginTransaction(); 
    ft.replace(R.id.content_frame, singoloClick); 
    ft.commit(); 

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
      this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
    drawer.setDrawerListener(toggle); 
    toggle.syncState(); 

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 
    navigationView.setNavigationItemSelectedListener(this); 

    IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);//"android.intent.action.MEDIA_BUTTON" 
    MediaButtonIntentReceiver r = new MediaButtonIntentReceiver(); 
    filter.setPriority(999); //this line sets receiver priority 
    registerReceiver(r, filter); 
((AudioManager)getSystemService(AUDIO_SERVICE)).registerMediaButtonEventReceiver(new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName())); 
} 

@Override public void onResume() 
{ 
    super.onResume(); 
} 

@Override 
public void onBackPressed() 
{ 
    moveTaskToBack(true); 
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
    if (drawer.isDrawerOpen(GravityCompat.START)) 
    { 
     drawer.closeDrawer(GravityCompat.START); 
    } 
    /*else 
    { 
     super.onBackPressed(); 
    }*/ 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) 
{ 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) 
    { 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 

@SuppressWarnings("StatementWithEmptyBody") 
@Override 
public boolean onNavigationItemSelected(MenuItem item) { 
    // Handle navigation view item clicks here. 
    int id = item.getItemId(); 
    if (id == R.id.nav_singoloClick) 
    { 
     setTitle(""+getResources().getString(R.string.singoloClick)); 
     FragmentManager fragmentManager= getFragmentManager(); 
     SingoloClick singoloClick= new SingoloClick(); 
     FragmentTransaction ft=fragmentManager.beginTransaction(); 
     ft.replace(R.id.content_frame, singoloClick); 
     ft.commit(); 
    } else if (id == R.id.nav_doppioClick) 
    { 
     setTitle(""+getResources().getString(R.string.doppioClick)); 
     FragmentManager fragmentManager= getFragmentManager(); 
     DoppioClick doppioClick= new DoppioClick(); 
     FragmentTransaction ft=fragmentManager.beginTransaction(); 
     ft.replace(R.id.content_frame, doppioClick); 
     ft.commit(); 
    } else if (id == R.id.nav_lungoClick) 
    { 
    } 

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
    drawer.closeDrawer(GravityCompat.START); 
    return true; 
} 


@Override 
protected void onDestroy() 
{ 
    super.onDestroy(); 
    android.os.Process.killProcess(android.os.Process.myPid());*/ 
} 

@Override public void onPause() 
{ 
    super.onPause(); 
} 
} 

Dies ist Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.example"> 

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> 

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" 
    android:supportsRtl="true" android:theme="@style/AppTheme"> 
    <activity android:name=".Main" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 

    <receiver android:name=".MediaButtonIntentReceiver"> 
     <intent-filter android:priority="999"> 
      <action android:name="android.intent.action.MEDIA_BUTTON" /> 
     </intent-filter> 
     <intent-filter android:priority="0"> 
      <action android:name="android.intent.action.VOICE_COMMAND" /> 
      <category android:name="android.intent.category.DEFAULT" /> 
     </intent-filter> 
    </receiver> 
</application> 

+0

Sie können die tatsächliche Zeit, die es "ACTION_DOWN" ist, speichern und mit der tatsächlichen Zeit vergleichen, die es für Ihre '> 2000' Prüfung' ACTION_UP' ist. – Doomsknight

Antwort

0

Für h Andle zu langer Druck auf eine Taste:

@Override 
public boolean onKeyLongPress(int keyCode, KeyEvent event) { 
     // TODO Auto-generated method stub 
} 
+0

Kann ich diesen Code in einen Broadcast-Empfänger eingeben? –

+0

Nein, Sie können nicht – GensaGames

1

versuchen Sie einen anderen Schlüssel-Ereignis zu verwenden KeyEvent.OTHER ... Was ich in doc gefunden:

/** 
    * This flag is set for the first key repeat that occurs after the 
    * long press timeout. 
    */ 
    public static final int FLAG_LONG_PRESS = 0x80; 

UPDATE: Eine andere Lösung, die Zeit für die Erfassung , wenn die Taste gedrückt wird.

final Timer timer = new Timer(); 
button.setOnTouchListener(new OnTouchListener() { 
    @Override 
    public boolean onTouch(View arg0, MotionEvent arg1) { 
     switch (arg1.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      //start timer 
      timer.schedule(new TimerTask() { 
       @Override 
       public void run() { 
        // invoke intent 
       } 
      }, 5000); //time out 5s 
      return true; 
     case MotionEvent.ACTION_UP: 
      //stop timer 
      timer.cancel(); 
      return true; 
     } 
     return false; 
    } 
}); 

UPDATE 2:

Es sieht aus wie Ihr Problem ist der Weg Sie Touch-Ereignisse in onTouchEvent umgehen. Diese Methode ACTION_UP - funktioniert nicht! Sie müssen true von onTouchEvent zurückgeben, wenn Sie Berührungsereignisse behandeln möchten. Wenn Sie also ACTION_DOWN erhalten und false von onTouchEvent zurückgeben, sendet Ihnen das System keine weiteren Berührungsereignisse bis zum nächsten ACTION_DOWN-Ereignis.

Wenn Sie andere Berührungsereignisse als ACTION_DOWN erhalten möchten, müssen Sie true von onTouchEvent, dieser Schaltfläche, zurückgeben. Aber Sie können das nicht tun, also müssen Sie über eine andere Lösung nachdenken.

UPDATE 3

Wie gesagt, müssen etwas andere Lösung zu schaffen, weil KEY_ACTION_UP funktioniert nicht. Vielleicht versuchen this Lösung auch.

+0

Aber dieser Code funktioniert für Button. Ich würde das lange Drücken der Hardware-Taste (Headset-Taste) erkennen. –

+0

Okey. Wenn keine anderen KeyEvents vorhanden sind, versuchen Sie, den Timer zu verwenden. Initialisieren Sie es einfach für das Aktionsereignis KEY_DOWN und stoppen Sie den Timer für KEY_UP. Überprüfen Sie die Timer-Größe bei langem Klick. – GensaGames

+0

Danke. Ich werde es bald versuchen und ich hoffe, dass es funktioniert –