提交 9995a623 编写于 作者: S Simon Fels

Add Android application to handle system ui part

Based on shashlikd from https://github.com/shashlik/shashlikd
上级 84429abb
android
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/../../android/gen" />
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/../../android/gen" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/../../android/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/../../android/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/../../android/assets" />
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/../../android/libs" />
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/../../android/proguard_logs" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/production/android" />
<output-test url="file://$MODULE_DIR$/build/test/android" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
</content>
<orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?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
<component name="CopyrightManager">
<settings default="" />
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<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_6" default="false" assert-keyword="true" jdk-15="true" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/android.iml" filepath="$PROJECT_DIR$/.idea/android.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
\ No newline at end of file
此差异已折叠。
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/src/java
LOCAL_SRC_FILES := $(call all-java-files-under, java)
LOCAL_JAVA_LIBRARIES := telephony-common
# Block certain packages from being installed
LOCAL_OVERRIDES_PACKAGES := \
SystemUI \
Home \
Launcher2 \
Calculator \
BasicDreams \
Calendar \
PrintSpooler \
WallpaperCropper
LOCAL_PACKAGE_NAME := anboxd
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.anbox" >
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".NotificationListener"
android:enabled="true"
android:exported="true"
android:label="@string/service_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service
android:name=".NavBar"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="org.anbox.NavBar"/>
</intent-filter>
</service>
</application>
</manifest>
# Android Anbox service
This is based on shashlikd from https://github.com/shashlik/shashlikd
/*___Generated_by_IDEA___*/
package org.anbox;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}
\ No newline at end of file
/*___Generated_by_IDEA___*/
package org.anbox;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}
\ No newline at end of file
/*___Generated_by_IDEA___*/
package org.anbox;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}
\ No newline at end of file
package org.anbox;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.os.SystemProperties;
import android.os.StrictMode;
import java.lang.Process;
import java.lang.ProcessBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.net.Uri;
import java.io.RandomAccessFile;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.File;
public class BootReceiver extends BroadcastReceiver {
public BootReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
//start shashlikd app wide services
MainApplication app = ((MainApplication) context.getApplicationContext());
app.startServices();
//Make a HTTP request
//this does two things; fetches the name of the APK to run (bit overkill, when it could be a simple built prop)
//informs the desktop side we're loaded, incase it needs to send anything with a fully operation system
//Android generally blocks network in the main thread, but we're only going to be showing a black screen idling anyway.
//may as well disable that setting
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
//Get and install the APK if needed
//if the APK doesn't exist the server will return a 403
//10.0.2.2 is a special qemu setup for localhost
try {
Log.d("Shashlikd", "Fetching APK");
URL url = new URL("http://10.0.2.2:60057/apk_file");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// opens input stream from the HTTP connection
InputStream inputStream = conn.getInputStream();
Log.d("Shashlikd", "Saving APK");
// opens an output stream to save into file
File outputDir = context.getCacheDir();
File outputFile = File.createTempFile("apkSave", ".apk", outputDir);
outputFile.setReadable(true, false);
FileOutputStream outputStream = new FileOutputStream(outputFile);
int bytesRead = -1;
byte[] buffer = new byte[4096];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
Log.d("Shashlikd", "File downloaded");
Log.d("Shashlikd", outputFile.getPath());
Log.d("Shashlikd", "Installing APK");
Process result = new ProcessBuilder()
.command("pm", "install", "-r", "-d", outputFile.getPath())
.start();
result.waitFor();
Log.d("Shashlikd", "Apk install finished with " + result.exitValue());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Find the name of the APK to run and start the main activity
try {
Log.d("Shashlikd", "Getting APK ID");
URL url = new URL("http://10.0.2.2:60057/startup");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
InputStream inputStream = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String apk = reader.readLine();
if (!apk.isEmpty()) {
//now try to start that APK
Log.d("Shashlikd", "STARTING");
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(apk);
if (launchIntent != null) {
context.startActivity(launchIntent);
} else {
Log.e("Shashlikd", "APK not installed");
}
} else {
Log.w("Shashlikd", "No APK name returned");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.anbox;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.TypedArray;
import android.hardware.input.InputManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
//import org.anbox.R;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
public class KeyButtonView extends ImageView {
private static final String TAG = "StatusBar.KeyButtonView";
private static final boolean DEBUG = false;
// TODO: Get rid of this
public static final float DEFAULT_QUIESCENT_ALPHA = 1f;
private long mDownTime;
private int mCode;
private int mTouchSlop;
private float mDrawingAlpha = 1f;
private float mQuiescentAlpha = DEFAULT_QUIESCENT_ALPHA;
private boolean mSupportsLongpress = true;
private AudioManager mAudioManager;
private Animator mAnimateToQuiescent = new ObjectAnimator();
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
if (isPressed()) {
// Log.d("KeyButtonView", "longpressed: " + this);
if (isLongClickable()) {
// Just an old-fashioned ImageView
performLongClick();
} else {
sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
}
}
}
};
public KeyButtonView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public KeyButtonView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyButtonView,
defStyle, 0);
mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);
mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
setDrawingAlpha(mQuiescentAlpha);
a.recycle();
setClickable(true);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
//setBackground(new KeyButtonRipple(context, this));
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
if (mCode != 0) {
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACTION_CLICK, null));
if (mSupportsLongpress) {
info.addAction(
new AccessibilityNodeInfo.AccessibilityAction(ACTION_LONG_CLICK, null));
}
}
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility != View.VISIBLE) {
jumpDrawablesToCurrentState();
}
}
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == ACTION_CLICK && mCode != 0) {
sendEvent(KeyEvent.ACTION_DOWN, 0, SystemClock.uptimeMillis());
sendEvent(KeyEvent.ACTION_UP, 0);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
playSoundEffect(SoundEffectConstants.CLICK);
return true;
} else if (action == ACTION_LONG_CLICK && mCode != 0 && mSupportsLongpress) {
sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
sendEvent(KeyEvent.ACTION_UP, 0);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
return true;
}
return super.performAccessibilityAction(action, arguments);
}
public void setQuiescentAlpha(float alpha, boolean animate) {
mAnimateToQuiescent.cancel();
alpha = Math.min(Math.max(alpha, 0), 1);
if (alpha == mQuiescentAlpha && alpha == mDrawingAlpha) return;
mQuiescentAlpha = alpha;
if (DEBUG) Log.d(TAG, "New quiescent alpha = " + mQuiescentAlpha);
if (animate) {
mAnimateToQuiescent = animateToQuiescent();
mAnimateToQuiescent.start();
} else {
setDrawingAlpha(mQuiescentAlpha);
}
}
private ObjectAnimator animateToQuiescent() {
return ObjectAnimator.ofFloat(this, "drawingAlpha", mQuiescentAlpha);
}
public float getQuiescentAlpha() {
return mQuiescentAlpha;
}
public float getDrawingAlpha() {
return mDrawingAlpha;
}
public void setDrawingAlpha(float x) {
setImageAlpha((int) (x * 255));
mDrawingAlpha = x;
}
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
int x, y;
switch (action) {
case MotionEvent.ACTION_DOWN:
mDownTime = SystemClock.uptimeMillis();
setPressed(true);
if (mCode != 0) {
sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
} else {
// Provide the same haptic feedback that the system offers for virtual keys.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
if (mSupportsLongpress) {
removeCallbacks(mCheckLongPress);
postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
}
break;
case MotionEvent.ACTION_MOVE:
x = (int)ev.getX();
y = (int)ev.getY();
setPressed(x >= -mTouchSlop
&& x < getWidth() + mTouchSlop
&& y >= -mTouchSlop
&& y < getHeight() + mTouchSlop);
break;
case MotionEvent.ACTION_CANCEL:
setPressed(false);
if (mCode != 0) {
sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
}
if (mSupportsLongpress) {
removeCallbacks(mCheckLongPress);
}
break;
case MotionEvent.ACTION_UP:
final boolean doIt = isPressed();
setPressed(false);
if (mCode != 0) {
if (doIt) {
sendEvent(KeyEvent.ACTION_UP, 0);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
playSoundEffect(SoundEffectConstants.CLICK);
} else {
sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
}
} else {
// no key code, just a regular ImageView
if (doIt) {
performClick();
}
}
if (mSupportsLongpress) {
removeCallbacks(mCheckLongPress);
}
break;
}
return true;
}
public void playSoundEffect(int soundConstant) {
// mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());
};
public void sendEvent(int action, int flags) {
sendEvent(action, flags, SystemClock.uptimeMillis());
}
void sendEvent(int action, int flags, long when) {
final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
InputDevice.SOURCE_KEYBOARD);
InputManager.getInstance().injectInputEvent(ev,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
}
package org.anbox;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(MainActivity.this, NotificationListener.class));
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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);
}
}
package org.anbox;
import android.app.Application;
public class MainApplication extends Application {
private NavBar mNavBar;
public void startServices() {
mNavBar = new NavBar(this);
}
}
package org.anbox;
import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
public class NavBar extends Service {
private NavigationBarView mNavigationBarView = null;
private Context mContext;
private WindowManager mWindowManager;
public NavBar(Context context) {
mContext = context;
mNavigationBarView =
(NavigationBarView) View.inflate(mContext, R.layout.navigation_bar, null);
mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
show();
}
private WindowManager.LayoutParams getNavigationBarLayoutParams() {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW+19, //TYPE_NAVIGATION_BAR, Private API, which for some reason I can't include...
0
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.TRANSLUCENT);
// this will allow the navbar to run in an overlay on devices that support this
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
lp.setTitle("NavigationBar");
lp.windowAnimations = 0;
return lp;
}
public void show() {
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
mWindowManager.updateViewLayout(mNavigationBarView, lp);
}
public void hide() {
WindowManager.LayoutParams lp =
(android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
mWindowManager.updateViewLayout(mNavigationBarView, lp);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
package org.anbox;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.util.Log;
import android.view.MotionEvent;
public class NavigationBarView extends LinearLayout {
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
\ No newline at end of file
package org.anbox;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
public class NotificationListener extends NotificationListenerService {
public NotificationListener() {
}
@Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
@Override
public void onListenerConnected() {
super.onListenerConnected();
}
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
Log.e("ShashlikController", "new notification");
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册