/*
* Copyright (C) 2013 75py
*
* 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 com.nagopy.android.xposed.utilities;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.IBinder;
import android.service.notification.StatusBarNotification;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ScrollView;
import android.widget.TextView;
import com.nagopy.android.xposed.util.XConst;
import com.nagopy.android.xposed.util.XUtil;
import com.nagopy.android.xposed.utilities.XposedModules.HandleInitPackageResources;
import com.nagopy.android.xposed.utilities.XposedModules.HandleLoadPackage;
import com.nagopy.android.xposed.utilities.XposedModules.XMinSdkVersion;
import com.nagopy.android.xposed.utilities.XposedModules.XposedModule;
import com.nagopy.android.xposed.utilities.setting.ModNotificationSettingsGen;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam;
import de.robv.android.xposed.callbacks.XC_LayoutInflated;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
@XposedModule(setting = ModNotificationSettingsGen.class)
public class ModNotification {
@HandleInitPackageResources(summary = "ヘッダーを非表示にする", targetPackage = XConst.PKG_SYSTEM_UI)
public static void hideNotificationHeader(
final String modulePath,
final InitPackageResourcesParam resparam,
final ModNotificationSettingsGen mNotificationSettings
) throws Throwable {
if (!mNotificationSettings.hideNotificationHeader) {
return;
}
resparam.res.hookLayout(XConst.PKG_SYSTEM_UI, "layout", "super_status_bar",
new XC_LayoutInflated() {
@Override
public void handleLayoutInflated(LayoutInflatedParam liparam)
throws Throwable {
// ヘッダー
LinearLayout header = (LinearLayout) liparam.view.findViewById(
liparam.res.getIdentifier("header", "id", XConst.PKG_SYSTEM_UI));
header.setVisibility(View.GONE);
}
});
}
@HandleInitPackageResources(summary = "キャリアを非表示にする", targetPackage = XConst.PKG_SYSTEM_UI)
public static void hideNotificationExpandedCarrier(
final String modulePath,
final InitPackageResourcesParam resparam,
final ModNotificationSettingsGen mNotificationSettings
) throws Throwable {
if (!mNotificationSettings.hideNotificationExpandedCarrier) {
return;
}
resparam.res.hookLayout(XConst.PKG_SYSTEM_UI, "layout", "super_status_bar",
new XC_LayoutInflated() {
@Override
public void handleLayoutInflated(LayoutInflatedParam liparam)
throws Throwable {
// キャリア表示
TextView carrierLabel = (TextView) liparam.view.findViewById(
liparam.res.getIdentifier("carrier_label", "id",
XConst.PKG_SYSTEM_UI));
carrierLabel.setVisibility(View.GONE);
carrierLabel.setPadding(0, 0, 0, 1000);
}
});
}
@HandleInitPackageResources(summary = "下寄せ・ヘッダー移動", targetPackage = XConst.PKG_SYSTEM_UI)
public static void notificationExpandedGravityBottom(
final String modulePath,
final InitPackageResourcesParam resparam,
final ModNotificationSettingsGen mNotificationSettings
) throws Throwable {
if (!mNotificationSettings.notificationExpandedGravityBottom) {
return;
}
resparam.res.hookLayout(XConst.PKG_SYSTEM_UI, "layout", "super_status_bar",
new XC_LayoutInflated() {
@Override
public void handleLayoutInflated(LayoutInflatedParam liparam)
throws Throwable {
// ヘッダー
LinearLayout header = (LinearLayout) liparam.view.findViewById(
liparam.res.getIdentifier("header", "id", XConst.PKG_SYSTEM_UI));
// キャリア表示
TextView carrierLabel = (TextView) liparam.view.findViewById(
liparam.res.getIdentifier("carrier_label", "id",
XConst.PKG_SYSTEM_UI));
// キャリア表示部分にヘッダー分のマージンをセット
FrameLayout.LayoutParams carrierLabelParams = (FrameLayout.LayoutParams) carrierLabel
.getLayoutParams();
carrierLabelParams.gravity = Gravity.TOP;
carrierLabelParams.topMargin = carrierLabel
.getContext().getResources()
.getDimensionPixelSize(
liparam.res.getIdentifier(
"notification_panel_header_height",
"dimen",
XConst.PKG_SYSTEM_UI));
// うまいことやる
LinearLayout parentLayout = (LinearLayout) header.getParent();
FrameLayout.LayoutParams parentLayoutParams = (FrameLayout.LayoutParams) parentLayout
.getLayoutParams();
parentLayoutParams.height = FrameLayout.LayoutParams.MATCH_PARENT;
ScrollView scrollView = (ScrollView) liparam.view.findViewById(
liparam.res.getIdentifier("scroll", "id", XConst.PKG_SYSTEM_UI));
FrameLayout.LayoutParams svParams = (FrameLayout.LayoutParams) scrollView
.getLayoutParams();
svParams.gravity = Gravity.BOTTOM;
FrameLayout svParent = (FrameLayout) scrollView.getParent();
LinearLayout.LayoutParams svParentParams = (LinearLayout.LayoutParams) svParent
.getLayoutParams();
svParentParams.height = 0;
svParentParams.weight = 1;
}
});
}
@HandleInitPackageResources(summary = "ヘッダーをフッターにする", targetPackage = XConst.PKG_SYSTEM_UI)
public static void notificationHeaderBottom(
final String modulePath,
final InitPackageResourcesParam resparam,
final ModNotificationSettingsGen mNotificationSettings
) throws Throwable {
if (!mNotificationSettings.notificationHeaderBottom) {
return;
}
resparam.res.hookLayout(XConst.PKG_SYSTEM_UI, "layout", "super_status_bar",
new XC_LayoutInflated() {
@Override
public void handleLayoutInflated(LayoutInflatedParam liparam)
throws Throwable {
// ヘッダー
LinearLayout header = (LinearLayout) liparam.view.findViewById(
liparam.res.getIdentifier("header", "id", XConst.PKG_SYSTEM_UI));
LinearLayout parentLayout = (LinearLayout) header.getParent();
LinearLayout.LayoutParams p = (LayoutParams) header.getLayoutParams();
parentLayout.removeView(header);
parentLayout.addView(header, p);
}
});
}
@HandleLoadPackage(summary = "順番を逆にしてみる", targetPackage = XConst.PKG_SYSTEM_UI)
public static void reverseNotification(
final String modulePath,
final LoadPackageParam lpparam,
final ModNotificationSettingsGen mNotificationSettings
) throws Throwable {
if (!mNotificationSettings.reverseNotificationExpanded) {
return;
}
Class<?> clsNotificationData = XposedHelpers.findClass(
"com.android.systemui.statusbar.NotificationData", lpparam.classLoader);
XposedHelpers.findAndHookMethod(clsNotificationData, "get", int.class,
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param)
throws Throwable {
int i = (Integer) param.args[0];
int size = (Integer) XposedHelpers.callMethod(param.thisObject, "size");
return XposedBridge.invokeOriginalMethod(param.method,
param.thisObject,
new Object[] {
size - i - 1
});
}
});
}
@HandleLoadPackage(summary = "全通知非表示", targetPackage = XConst.PKG_SYSTEM_UI)
@XMinSdkVersion(Build.VERSION_CODES.JELLY_BEAN_MR2)
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public static void hideAllNotification(
final String modulePath,
final LoadPackageParam lpparam,
final ModNotificationSettingsGen mNotificationSettings
) throws Throwable {
Class<?> clsPhoneStatusBar = XposedHelpers.findClass(
"com.android.systemui.statusbar.phone.PhoneStatusBar", lpparam.classLoader);
XposedHelpers.findAndHookMethod(clsPhoneStatusBar, "addNotification", IBinder.class,
StatusBarNotification.class, new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
StatusBarNotification stb = (StatusBarNotification) param.args[1];
String packageName = stb.getPackageName();
if (mNotificationSettings.hideAllNotificationPackages.contains(packageName)) {
// do nothing
return null;
} else {
return XUtil.invokeOriginalMethod(param);
}
}
});
}
@HandleLoadPackage(summary = "アイコンだけを非表示にする", targetPackage = XConst.PKG_SYSTEM_UI)
public static void hideNotificationIcon(
final String modulePath,
final LoadPackageParam lpparam,
final ModNotificationSettingsGen mNotificationSettings
) throws Throwable {
Class<?> clsStatusBarIcon = XposedHelpers.findClass(
"com.android.internal.statusbar.StatusBarIcon", lpparam.classLoader);
XposedBridge.hookAllConstructors(clsStatusBarIcon, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String iconPackage = (String) XposedHelpers.getObjectField(param.thisObject,
"iconPackage");
if (mNotificationSettings.hideNotificationIconPackages.contains(iconPackage)) {
XposedHelpers.setBooleanField(param.thisObject, "visible", false);
}
}
});
}
}